init
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
BasedOnStyle: LLVM
|
||||
UseTab: Always
|
||||
IndentWidth: 4
|
||||
TabWidth: 4
|
||||
BreakBeforeBraces: Attach
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
IndentCaseLabels: false
|
||||
@@ -0,0 +1,10 @@
|
||||
name: New MCP server
|
||||
version: 0.0.1
|
||||
schema: v1
|
||||
mcpServers:
|
||||
- name: New MCP server
|
||||
command: npx
|
||||
args:
|
||||
- -y
|
||||
- <your-mcp-server>
|
||||
env: {}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "windows-gcc-x86",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"compilerPath": "C:/mingw/bin/gcc.exe",
|
||||
"cStandard": "${default}",
|
||||
"cppStandard": "${default}",
|
||||
"intelliSenseMode": "windows-gcc-x86",
|
||||
"compilerArgs": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
Vendored
+84
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "STLink@Arm-Debugger (launch)",
|
||||
"type": "arm-debugger",
|
||||
"request": "launch",
|
||||
"connectionAddress": "${command:device-manager.getSerialNumber}",
|
||||
"connectionType": "ST-Link",
|
||||
"programs": "${command:cmsis-csolution.getBinaryFiles}",
|
||||
"cmsisPack": "${command:cmsis-csolution.getDfpName}",
|
||||
"deviceName": "${command:cmsis-csolution.getDeviceName}",
|
||||
"processorName": "${command:cmsis-csolution.getProcessorName}",
|
||||
"workspaceFolder": "${workspaceFolder}/"
|
||||
},
|
||||
{
|
||||
"name": "STLink@pyOCD (launch)",
|
||||
"type": "gdbtarget",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}/",
|
||||
"program": "out/Robot_V2/GD32C103CB/Release/Robot_V2.axf",
|
||||
"gdb": "arm-none-eabi-gdb",
|
||||
"auxiliaryGdb": true,
|
||||
"preLaunchTask": "CMSIS Load",
|
||||
"initCommands": [
|
||||
"monitor reset halt",
|
||||
"tbreak main"
|
||||
],
|
||||
"customResetCommands": [
|
||||
"monitor reset halt",
|
||||
"maintenance flush register-cache",
|
||||
"maintenance flush dcache",
|
||||
"tbreak main",
|
||||
"continue"
|
||||
],
|
||||
"target": {
|
||||
"server": "pyocd",
|
||||
"serverParameters": [
|
||||
"gdbserver",
|
||||
"--probe",
|
||||
"stlink:",
|
||||
"--connect",
|
||||
"attach",
|
||||
"--cbuild-run",
|
||||
"${command:cmsis-csolution.getCbuildRunFile}",
|
||||
"--quiet",
|
||||
"--log",
|
||||
"*.cbuild_run,*server=info"
|
||||
],
|
||||
"port": "3333"
|
||||
},
|
||||
"cmsis": {
|
||||
"cbuildRunFile": "${command:cmsis-csolution.getCbuildRunFile}",
|
||||
"updateConfiguration": "auto"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "STLink@pyOCD (attach)",
|
||||
"type": "gdbtarget",
|
||||
"request": "attach",
|
||||
"cwd": "${workspaceFolder}/",
|
||||
"program": "out/Robot_V2/GD32C103CB/Release/Robot_V2.axf",
|
||||
"gdb": "arm-none-eabi-gdb",
|
||||
"auxiliaryGdb": true,
|
||||
"initCommands": [
|
||||
""
|
||||
],
|
||||
"customResetCommands": [
|
||||
"monitor reset halt",
|
||||
"maintenance flush register-cache",
|
||||
"maintenance flush dcache",
|
||||
"tbreak main",
|
||||
"continue"
|
||||
],
|
||||
"target": {
|
||||
"port": "3333"
|
||||
},
|
||||
"cmsis": {
|
||||
"cbuildRunFile": "${command:cmsis-csolution.getCbuildRunFile}",
|
||||
"updateConfiguration": "auto"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"clangd.arguments": [
|
||||
"--compile-commands-dir=g:\\Robot_v2\\BOOT\\out\\Robot_V2\\GD32C103CB\\Release"
|
||||
],
|
||||
"debug.hideSlowPreLaunchWarning": true,
|
||||
"debug.showInStatusBar": "never"
|
||||
}
|
||||
Vendored
+112
@@ -0,0 +1,112 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "CMSIS Load+Run",
|
||||
"problemMatcher": [],
|
||||
"dependsOn": [
|
||||
"CMSIS Load",
|
||||
"CMSIS Run"
|
||||
],
|
||||
"dependsOrder": "sequence"
|
||||
},
|
||||
{
|
||||
"label": "CMSIS Erase",
|
||||
"type": "shell",
|
||||
"command": "pyocd",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/",
|
||||
"shell": {
|
||||
"executable": "cmd.exe",
|
||||
"args": [
|
||||
"/d",
|
||||
"/c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"args": [
|
||||
"erase",
|
||||
"--probe",
|
||||
"stlink:",
|
||||
"--chip",
|
||||
"--cbuild-run",
|
||||
"${command:cmsis-csolution.getCbuildRunFile}"
|
||||
],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "CMSIS Load",
|
||||
"type": "shell",
|
||||
"command": "pyocd",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/",
|
||||
"shell": {
|
||||
"executable": "cmd.exe",
|
||||
"args": [
|
||||
"/d",
|
||||
"/c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"args": [
|
||||
"load",
|
||||
"--probe",
|
||||
"stlink:",
|
||||
"--cbuild-run",
|
||||
"${command:cmsis-csolution.getCbuildRunFile}"
|
||||
],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "CMSIS Run",
|
||||
"type": "shell",
|
||||
"command": "pyocd",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/",
|
||||
"shell": {
|
||||
"executable": "cmd.exe",
|
||||
"args": [
|
||||
"/d",
|
||||
"/c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"args": [
|
||||
"gdbserver",
|
||||
"--probe",
|
||||
"stlink:",
|
||||
"--connect",
|
||||
"attach",
|
||||
"--persist",
|
||||
"--reset-run",
|
||||
"--cbuild-run",
|
||||
"${command:cmsis-csolution.getCbuildRunFile}",
|
||||
"--quiet",
|
||||
"--log",
|
||||
"*.cbuild_run,*server=info"
|
||||
],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "CMSIS TargetInfo",
|
||||
"type": "shell",
|
||||
"command": "pyocd",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/",
|
||||
"shell": {
|
||||
"executable": "cmd.exe",
|
||||
"args": [
|
||||
"/d",
|
||||
"/c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"args": [
|
||||
"list",
|
||||
"--cbuild-run",
|
||||
"${command:cmsis-csolution.getCbuildRunFile}"
|
||||
],
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
build-idx:
|
||||
generated-by: csolution version 2.12.0+p41-gfeadfc5e
|
||||
cdefault: ${CMSIS_COMPILER_ROOT}/cdefault.yml
|
||||
csolution: Robot_V2.csolution.yml
|
||||
cbuild-run: out/Robot_V2+GD32C103CB.cbuild-run.yml
|
||||
tmpdir: tmp
|
||||
cprojects:
|
||||
- cproject: Robot_V2/Robot_V2.cproject.yml
|
||||
cbuilds:
|
||||
- cbuild: out/Robot_V2/GD32C103CB/Release/Robot_V2.Release+GD32C103CB.cbuild.yml
|
||||
project: Robot_V2
|
||||
configuration: .Release+GD32C103CB
|
||||
messages:
|
||||
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
|
||||
@@ -0,0 +1,8 @@
|
||||
cbuild-pack:
|
||||
resolved-packs:
|
||||
- resolved-pack: ARM::CMSIS@4.5.0
|
||||
selected-by-pack:
|
||||
- ARM::CMSIS
|
||||
- resolved-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
selected-by-pack:
|
||||
- GigaDevice::GD32C10x_DFP
|
||||
@@ -0,0 +1,52 @@
|
||||
# A solution is a collection of related projects that share same base configuration.
|
||||
solution:
|
||||
created-for: CMSIS-Toolbox@2.12.0
|
||||
cdefault: # use CMSIS-Toolbox default Compiler options
|
||||
|
||||
# Compilers that can be selected
|
||||
select-compiler:
|
||||
- compiler: AC6
|
||||
- compiler: GCC
|
||||
- compiler: IAR
|
||||
- compiler: CLANG
|
||||
|
||||
# List of miscellaneous tool-specific controls
|
||||
misc:
|
||||
- for-compiler: AC6 # GDB requires DWARF 5, remove when using uVision Debugger
|
||||
C-CPP:
|
||||
- -gdwarf-5
|
||||
ASM:
|
||||
- -gdwarf-5
|
||||
|
||||
# List the packs that define the device and/or board.
|
||||
packs:
|
||||
- pack: GigaDevice::GD32C10x_DFP
|
||||
- pack: ARM::CMSIS
|
||||
|
||||
# List different hardware targets that are used to deploy the solution.
|
||||
target-types:
|
||||
- type: GD32C103CB
|
||||
device: GD32C103CB
|
||||
target-set:
|
||||
- set:
|
||||
images:
|
||||
- project-context: Robot_V2.Release
|
||||
debugger:
|
||||
name: ST-Link@pyOCD
|
||||
clock: 10000000
|
||||
protocol: swd
|
||||
|
||||
# List of different build configurations.
|
||||
build-types:
|
||||
- type: Debug
|
||||
debug: on
|
||||
optimize: none
|
||||
|
||||
- type: Release
|
||||
debug: off
|
||||
optimize: balanced
|
||||
|
||||
# List related projects.
|
||||
projects:
|
||||
- project: Robot_V2/Robot_V2.cproject.yml
|
||||
compiler: AC6
|
||||
@@ -0,0 +1,424 @@
|
||||
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__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'
|
||||
- >-
|
||||
-IC:/Users/cbb/AppData/Local/arm/packs/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc
|
||||
- >-
|
||||
-IC:/Users/cbb/AppData/Local/arm/packs/GigaDevice/GD32C10x_DFP/1.0.1/Device/Include
|
||||
- >-
|
||||
-IC:/Users/cbb/AppData/Local/arm/packs/GigaDevice/GD32C10x_DFP/1.0.1/Device/Utilities
|
||||
- '-IG:/Robot_v2/BOOT/Robot_V2'
|
||||
- '-IG:/Robot_v2/BOOT/Robot_V2/sys'
|
||||
- '-IG:/Robot_v2/BOOT/Robot_V2/device'
|
||||
@@ -0,0 +1,290 @@
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,411 @@
|
||||
// 函数声明
|
||||
#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
|
||||
@@ -0,0 +1,151 @@
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
#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
|
||||
@@ -0,0 +1,60 @@
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#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
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef THERMAL_H
|
||||
#define THERMAL_H
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
Stack seal size definition
|
||||
*----------------------------------------------------------------------------*/
|
||||
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
|
||||
#define __STACKSEAL_SIZE 8
|
||||
#else
|
||||
#define __STACKSEAL_SIZE 0
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Scatter File Definitions definition
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
LR_ROM0 __ROM0_BASE __ROM0_SIZE {
|
||||
|
||||
ER_ROM0 __ROM0_BASE __ROM0_SIZE {
|
||||
*.o (RESET, +First)
|
||||
*(InRoot$$Sections)
|
||||
*(+RO +XO)
|
||||
}
|
||||
|
||||
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
|
||||
ER_CMSE_VENEER AlignExpr(+0, 32) (__ROM0_SIZE - AlignExpr(ImageLength(ER_ROM0), 32)) {
|
||||
*(Veneer$$CMSE)
|
||||
}
|
||||
#endif
|
||||
|
||||
RW_NOINIT __RAM0_BASE UNINIT (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - __STACKSEAL_SIZE) {
|
||||
*.o(.bss.noinit)
|
||||
*.o(.bss.noinit.*)
|
||||
}
|
||||
|
||||
RW_RAM0 AlignExpr(+0, 8) (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - __STACKSEAL_SIZE - AlignExpr(ImageLength(RW_NOINIT), 8)) {
|
||||
*(+RW +ZI)
|
||||
}
|
||||
|
||||
#if __HEAP_SIZE > 0
|
||||
ARM_LIB_HEAP (AlignExpr(+0, 8)) EMPTY __HEAP_SIZE { ; Reserve empty region for heap
|
||||
}
|
||||
#endif
|
||||
|
||||
ARM_LIB_STACK (__RAM0_BASE + __RAM0_SIZE - __STACKSEAL_SIZE) EMPTY -__STACK_SIZE { ; Reserve empty region for stack
|
||||
}
|
||||
|
||||
#if __STACKSEAL_SIZE > 0
|
||||
STACKSEAL +0 EMPTY __STACKSEAL_SIZE { ; Reserve empty region for stack seal immediately after stack
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __RAM1_SIZE > 0
|
||||
RW_RAM1 __RAM1_BASE __RAM1_SIZE {
|
||||
.ANY (+RW +ZI)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __RAM2_SIZE > 0
|
||||
RW_RAM2 __RAM2_BASE __RAM2_SIZE {
|
||||
.ANY (+RW +ZI)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __RAM3_SIZE > 0
|
||||
RW_RAM3 __RAM3_BASE __RAM3_SIZE {
|
||||
.ANY (+RW +ZI)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if __ROM1_SIZE > 0
|
||||
LR_ROM1 __ROM1_BASE __ROM1_SIZE {
|
||||
ER_ROM1 +0 __ROM1_SIZE {
|
||||
.ANY (+RO +XO)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __ROM2_SIZE > 0
|
||||
LR_ROM2 __ROM2_BASE __ROM2_SIZE {
|
||||
ER_ROM2 +0 __ROM2_SIZE {
|
||||
.ANY (+RO +XO)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __ROM3_SIZE > 0
|
||||
LR_ROM3 __ROM3_BASE __ROM3_SIZE {
|
||||
ER_ROM3 +0 __ROM3_SIZE {
|
||||
.ANY (+RO +XO)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,992 @@
|
||||
/*!
|
||||
\file gd32c10x_adc.c
|
||||
\brief ADC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_adc.h"
|
||||
|
||||
/* discontinuous mode macro*/
|
||||
#define ADC_CHANNEL_LENGTH_SUBTRACT_ONE ((uint8_t)1U)
|
||||
|
||||
/* ADC regular channel macro */
|
||||
#define ADC_REGULAR_CHANNEL_RANK_SIX ((uint8_t)6U)
|
||||
#define ADC_REGULAR_CHANNEL_RANK_TWELVE ((uint8_t)12U)
|
||||
#define ADC_REGULAR_CHANNEL_RANK_SIXTEEN ((uint8_t)16U)
|
||||
#define ADC_REGULAR_CHANNEL_RANK_LENGTH ((uint8_t)5U)
|
||||
|
||||
/* ADC sampling time macro */
|
||||
#define ADC_CHANNEL_SAMPLE_TEN ((uint8_t)10U)
|
||||
#define ADC_CHANNEL_SAMPLE_EIGHTEEN ((uint8_t)18U)
|
||||
#define ADC_CHANNEL_SAMPLE_LENGTH ((uint8_t)3U)
|
||||
|
||||
/* ADC inserted channel macro */
|
||||
#define ADC_INSERTED_CHANNEL_RANK_LENGTH ((uint8_t)5U)
|
||||
#define ADC_INSERTED_CHANNEL_SHIFT_LENGTH ((uint8_t)15U)
|
||||
|
||||
/* ADC inserted channel offset macro */
|
||||
#define ADC_OFFSET_LENGTH ((uint8_t)3U)
|
||||
#define ADC_OFFSET_SHIFT_LENGTH ((uint8_t)4U)
|
||||
|
||||
/*!
|
||||
\brief reset ADC
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_deinit(uint32_t adc_periph)
|
||||
{
|
||||
switch(adc_periph){
|
||||
case ADC0:
|
||||
/* reset ADC0 */
|
||||
rcu_periph_reset_enable(RCU_ADC0RST);
|
||||
rcu_periph_reset_disable(RCU_ADC0RST);
|
||||
break;
|
||||
case ADC1:
|
||||
/* reset ADC1 */
|
||||
rcu_periph_reset_enable(RCU_ADC1RST);
|
||||
rcu_periph_reset_disable(RCU_ADC1RST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the ADC sync mode
|
||||
\param[in] mode: ADC mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_MODE_FREE: all the ADCs work independently
|
||||
\arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL: ADC0 and ADC1 work in combined regular parallel + inserted parallel mode
|
||||
\arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION: ADC0 and ADC1 work in combined regular parallel + trigger rotation mode
|
||||
\arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode
|
||||
\arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode
|
||||
\arg ADC_DAUL_INSERTED_PARALLEL: ADC0 and ADC1 work in inserted parallel mode only
|
||||
\arg ADC_DAUL_REGULAL_PARALLEL: ADC0 and ADC1 work in regular parallel mode only
|
||||
\arg ADC_DAUL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in follow-up fast mode only
|
||||
\arg ADC_DAUL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in follow-up slow mode only
|
||||
\arg ADC_DAUL_INSERTED_TRIGGER_ROTATION: ADC0 and ADC1 work in trigger rotation mode only
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_mode_config(uint32_t mode)
|
||||
{
|
||||
ADC_CTL0(ADC0) &= ~(ADC_CTL0_SYNCM);
|
||||
ADC_CTL0(ADC0) |= mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable or disable ADC special function
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] function: the function to config
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_SCAN_MODE: scan mode select
|
||||
\arg ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically
|
||||
\arg ADC_CONTINUOUS_MODE: continuous mode select
|
||||
\param[in] newvalue: ENABLE or DISABLE
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_special_function_config(uint32_t adc_periph , uint32_t function , ControlStatus newvalue)
|
||||
{
|
||||
if(newvalue){
|
||||
if(0U != (function & ADC_SCAN_MODE)){
|
||||
/* enable scan mode */
|
||||
ADC_CTL0(adc_periph) |= ADC_SCAN_MODE;
|
||||
}
|
||||
if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){
|
||||
/* enable inserted channel group convert automatically */
|
||||
ADC_CTL0(adc_periph) |= ADC_INSERTED_CHANNEL_AUTO;
|
||||
}
|
||||
if(0U != (function & ADC_CONTINUOUS_MODE)){
|
||||
/* enable continuous mode */
|
||||
ADC_CTL1(adc_periph) |= ADC_CONTINUOUS_MODE;
|
||||
}
|
||||
}else{
|
||||
if(0U != (function & ADC_SCAN_MODE)){
|
||||
/* disable scan mode */
|
||||
ADC_CTL0(adc_periph) &= ~ADC_SCAN_MODE;
|
||||
}
|
||||
if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){
|
||||
/* disable inserted channel group convert automatically */
|
||||
ADC_CTL0(adc_periph) &= ~ADC_INSERTED_CHANNEL_AUTO;
|
||||
}
|
||||
if(0U != (function & ADC_CONTINUOUS_MODE)){
|
||||
/* disable continuous mode */
|
||||
ADC_CTL1(adc_periph) &= ~ADC_CONTINUOUS_MODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC data alignment
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] data_alignment: data alignment select
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_DATAALIGN_RIGHT: LSB alignment
|
||||
\arg ADC_DATAALIGN_LEFT: MSB alignment
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_data_alignment_config(uint32_t adc_periph , uint32_t data_alignment)
|
||||
{
|
||||
if(ADC_DATAALIGN_RIGHT != data_alignment){
|
||||
/* MSB alignment */
|
||||
ADC_CTL1(adc_periph) |= ADC_CTL1_DAL;
|
||||
}else{
|
||||
/* LSB alignment */
|
||||
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable ADC interface
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_enable(uint32_t adc_periph)
|
||||
{
|
||||
if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){
|
||||
/* enable ADC */
|
||||
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable ADC interface
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_disable(uint32_t adc_periph)
|
||||
{
|
||||
/* disable ADC */
|
||||
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief ADC calibration and reset calibration
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_calibration_enable(uint32_t adc_periph)
|
||||
{
|
||||
/* reset the selected ADC calibration registers */
|
||||
ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB;
|
||||
/* check the RSTCLB bit state */
|
||||
while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){
|
||||
}
|
||||
/* enable ADC calibration process */
|
||||
ADC_CTL1(adc_periph) |= ADC_CTL1_CLB;
|
||||
/* check the CLB bit state */
|
||||
while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable the temperature sensor and Vrefint channel
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_tempsensor_vrefint_enable(void)
|
||||
{
|
||||
/* enable the temperature sensor and Vrefint channel */
|
||||
ADC_CTL1(ADC0) |= ADC_CTL1_TSVREN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable the temperature sensor and Vrefint channel
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_tempsensor_vrefint_disable(void)
|
||||
{
|
||||
/* disable the temperature sensor and Vrefint channel */
|
||||
ADC_CTL1(ADC0) &= ~ADC_CTL1_TSVREN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC resolution
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] resolution: ADC resolution
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_RESOLUTION_12B: 12-bit ADC resolution
|
||||
\arg ADC_RESOLUTION_10B: 10-bit ADC resolution
|
||||
\arg ADC_RESOLUTION_8B: 8-bit ADC resolution
|
||||
\arg ADC_RESOLUTION_6B: 6-bit ADC resolution
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_resolution_config(uint32_t adc_periph , uint32_t resolution)
|
||||
{
|
||||
ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_DRES);
|
||||
ADC_OVSAMPCTL(adc_periph) |= (uint32_t)resolution;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC oversample mode
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] mode: ADC oversampling mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger
|
||||
\arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger
|
||||
\param[in] shift: ADC oversampling shift
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift
|
||||
\param[in] ratio: ADC oversampling ratio
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio multiple 2
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio multiple 4
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio multiple 8
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio multiple 16
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio multiple 32
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio multiple 64
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio multiple 128
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio multiple 256
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_oversample_mode_config(uint32_t adc_periph, uint32_t mode, uint16_t shift, uint8_t ratio)
|
||||
{
|
||||
if(ADC_OVERSAMPLING_ONE_CONVERT == mode){
|
||||
ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS;
|
||||
}else{
|
||||
ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS);
|
||||
}
|
||||
/* config the shift and ratio */
|
||||
ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS));
|
||||
ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable ADC oversample mode
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_oversample_mode_enable(uint32_t adc_periph)
|
||||
{
|
||||
ADC_OVSAMPCTL(adc_periph) |= ADC_OVSAMPCTL_OVSEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable ADC oversample mode
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_oversample_mode_disable(uint32_t adc_periph)
|
||||
{
|
||||
ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DMA request
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_dma_mode_enable(uint32_t adc_periph)
|
||||
{
|
||||
/* enable DMA request */
|
||||
ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DMA request
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_dma_mode_disable(uint32_t adc_periph)
|
||||
{
|
||||
/* disable DMA request */
|
||||
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC discontinuous mode
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel_group: select the channel group
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_REGULAR_CHANNEL: regular channel group
|
||||
\arg ADC_INSERTED_CHANNEL: inserted channel group
|
||||
\arg ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of regular & inserted channel
|
||||
\param[in] length: number of conversions in discontinuous mode,the number can be 1..8
|
||||
for regular channel ,the number has no effect for inserted channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length)
|
||||
{
|
||||
/* disable discontinuous mode of regular & inserted channel */
|
||||
ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_DISRC | ADC_CTL0_DISIC));
|
||||
switch(adc_channel_group){
|
||||
case ADC_REGULAR_CHANNEL:
|
||||
/* config the number of conversions in discontinuous mode */
|
||||
ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM);
|
||||
ADC_CTL0(adc_periph) |= CTL0_DISNUM(((uint32_t)length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE));
|
||||
/* enable regular channel group discontinuous mode */
|
||||
ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC;
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL:
|
||||
/* enable inserted channel group discontinuous mode */
|
||||
ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC;
|
||||
break;
|
||||
case ADC_CHANNEL_DISCON_DISABLE:
|
||||
/* disable discontinuous mode of regular & inserted channel */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the length of regular channel group or inserted channel group
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel_group: select the channel group
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_REGULAR_CHANNEL: regular channel group
|
||||
\arg ADC_INSERTED_CHANNEL: inserted channel group
|
||||
\param[in] length: the length of the channel
|
||||
regular channel 1-16
|
||||
inserted channel 1-4
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length)
|
||||
{
|
||||
switch(adc_channel_group){
|
||||
case ADC_REGULAR_CHANNEL:
|
||||
/* configure the length of regular channel group */
|
||||
ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL);
|
||||
ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE));
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL:
|
||||
/* configure the length of inserted channel group */
|
||||
ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL);
|
||||
ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC regular channel
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] rank: the regular group sequence rank,this parameter must be between 0 to 15
|
||||
\param[in] adc_channel: the selected ADC channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx
|
||||
\param[in] sample_time: the sample time value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_SAMPLETIME_1POINT5: 1.5 cycles
|
||||
\arg ADC_SAMPLETIME_7POINT5: 7.5 cycles
|
||||
\arg ADC_SAMPLETIME_13POINT5: 13.5 cycles
|
||||
\arg ADC_SAMPLETIME_28POINT5: 28.5 cycles
|
||||
\arg ADC_SAMPLETIME_41POINT5: 41.5 cycles
|
||||
\arg ADC_SAMPLETIME_55POINT5: 55.5 cycles
|
||||
\arg ADC_SAMPLETIME_71POINT5: 71.5 cycles
|
||||
\arg ADC_SAMPLETIME_239POINT5: 239.5 cycles
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_regular_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time)
|
||||
{
|
||||
uint32_t rsq,sampt;
|
||||
|
||||
/* ADC regular sequence config */
|
||||
if(rank < ADC_REGULAR_CHANNEL_RANK_SIX){
|
||||
/* the regular group sequence rank is smaller than six */
|
||||
rsq = ADC_RSQ2(adc_periph);
|
||||
rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank)));
|
||||
/* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */
|
||||
rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank));
|
||||
ADC_RSQ2(adc_periph) = rsq;
|
||||
}else if(rank < ADC_REGULAR_CHANNEL_RANK_TWELVE){
|
||||
/* the regular group sequence rank is smaller than twelve */
|
||||
rsq = ADC_RSQ1(adc_periph);
|
||||
rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX))));
|
||||
/* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */
|
||||
rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX)));
|
||||
ADC_RSQ1(adc_periph) = rsq;
|
||||
}else if(rank < ADC_REGULAR_CHANNEL_RANK_SIXTEEN){
|
||||
/* the regular group sequence rank is smaller than sixteen */
|
||||
rsq = ADC_RSQ0(adc_periph);
|
||||
rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE))));
|
||||
/* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */
|
||||
rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE)));
|
||||
ADC_RSQ0(adc_periph) = rsq;
|
||||
}else{
|
||||
}
|
||||
|
||||
/* ADC sampling time config */
|
||||
if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){
|
||||
/* the regular group sequence rank is smaller than ten */
|
||||
sampt = ADC_SAMPT1(adc_periph);
|
||||
sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel)));
|
||||
/* channel sample time set*/
|
||||
sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel));
|
||||
ADC_SAMPT1(adc_periph) = sampt;
|
||||
}else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){
|
||||
/* the regular group sequence rank is smaller than eighteen */
|
||||
sampt = ADC_SAMPT0(adc_periph);
|
||||
sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN))));
|
||||
/* channel sample time set*/
|
||||
sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN)));
|
||||
ADC_SAMPT0(adc_periph) = sampt;
|
||||
}else{
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC inserted channel
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3
|
||||
\param[in] adc_channel: the selected ADC channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx
|
||||
\param[in] sample_time: The sample time value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_SAMPLETIME_1POINT5: 1.5 cycles
|
||||
\arg ADC_SAMPLETIME_7POINT5: 7.5 cycles
|
||||
\arg ADC_SAMPLETIME_13POINT5: 13.5 cycles
|
||||
\arg ADC_SAMPLETIME_28POINT5: 28.5 cycles
|
||||
\arg ADC_SAMPLETIME_41POINT5: 41.5 cycles
|
||||
\arg ADC_SAMPLETIME_55POINT5: 55.5 cycles
|
||||
\arg ADC_SAMPLETIME_71POINT5: 71.5 cycles
|
||||
\arg ADC_SAMPLETIME_239POINT5: 239.5 cycles
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_inserted_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time)
|
||||
{
|
||||
uint8_t inserted_length;
|
||||
uint32_t isq,sampt;
|
||||
|
||||
/* get inserted channel group length */
|
||||
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)));
|
||||
ADC_ISQ(adc_periph) = isq;
|
||||
|
||||
/* ADC sampling time config */
|
||||
if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){
|
||||
/* the inserted group sequence rank is smaller than ten */
|
||||
sampt = ADC_SAMPT1(adc_periph);
|
||||
sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel)));
|
||||
/* channel sample time set*/
|
||||
sampt |= (uint32_t) sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel);
|
||||
ADC_SAMPT1(adc_periph) = sampt;
|
||||
}else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){
|
||||
/* the inserted group sequence rank is smaller than eighteen */
|
||||
sampt = ADC_SAMPT0(adc_periph);
|
||||
sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN))));
|
||||
/* channel sample time set*/
|
||||
sampt |= ((uint32_t)sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN)));
|
||||
ADC_SAMPT0(adc_periph) = sampt;
|
||||
}else{
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC inserted channel offset
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] inserted_channel : insert channel select
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_INSERTED_CHANNEL_0: inserted channel0
|
||||
\arg ADC_INSERTED_CHANNEL_1: inserted channel1
|
||||
\arg ADC_INSERTED_CHANNEL_2: inserted channel2
|
||||
\arg ADC_INSERTED_CHANNEL_3: inserted channel3
|
||||
\param[in] offset : the offset data
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_inserted_channel_offset_config(uint32_t adc_periph , uint8_t inserted_channel , uint16_t offset)
|
||||
{
|
||||
uint8_t inserted_length;
|
||||
uint32_t num = 0U;
|
||||
|
||||
inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U);
|
||||
num = ((uint32_t)ADC_OFFSET_LENGTH - ((uint32_t)inserted_length - (uint32_t)inserted_channel));
|
||||
|
||||
if(num <= ADC_OFFSET_LENGTH){
|
||||
/* calculate the offset of the register */
|
||||
num = num * ADC_OFFSET_SHIFT_LENGTH;
|
||||
/* config the offset of the selected channels */
|
||||
REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC external trigger source
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel_group: select the channel group
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_REGULAR_CHANNEL: regular channel group
|
||||
\arg ADC_INSERTED_CHANNEL: inserted channel group
|
||||
\param[in] external_trigger_source: regular or inserted group trigger source
|
||||
only one parameter can be selected which is shown as below:
|
||||
for regular channel:
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T0_CH0: timer 0 CC0 event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T0_CH1: timer 0 CC1 event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T0_CH2: timer 0 CC2 event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T1_CH1: timer 1 CC1 event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T2_TRGO: timer 2 TRGO event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T3_CH3: timer 3 CC3 event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T7_TRGO: timer 7 TRGO event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_EXTI_11 : external interrupt line 11
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_NONE: software trigger
|
||||
for inserted channel:
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T0_TRGO: timer 0 TRGO event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T0_CH3: timer 0 CC3 event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T1_TRGO: timer 1 TRGO event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T1_CH0: timer 1 CC0 event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T2_CH3: timer 2 CC3 event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T3_TRGO: timer 3 TRGO event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T7_CH3: timer 7 CC3 event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_NONE: software trigger
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source)
|
||||
{
|
||||
switch(adc_channel_group){
|
||||
case ADC_REGULAR_CHANNEL:
|
||||
/* configure ADC regular group external trigger source */
|
||||
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC);
|
||||
ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source;
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL:
|
||||
/* configure ADC inserted group external trigger source */
|
||||
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC);
|
||||
ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable ADC external trigger
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel_group: select the channel group
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg ADC_REGULAR_CHANNEL: regular channel group
|
||||
\arg ADC_INSERTED_CHANNEL: inserted channel group
|
||||
\param[in] newvalue: ENABLE or DISABLE
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue)
|
||||
{
|
||||
if(newvalue){
|
||||
if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){
|
||||
/* enable ADC regular channel group external trigger */
|
||||
ADC_CTL1(adc_periph) |= ADC_CTL1_ETERC;
|
||||
}
|
||||
if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){
|
||||
/* enable ADC inserted channel group external trigger */
|
||||
ADC_CTL1(adc_periph) |= ADC_CTL1_ETEIC;
|
||||
}
|
||||
}else{
|
||||
if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){
|
||||
/* disable ADC regular channel group external trigger */
|
||||
ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETERC;
|
||||
}
|
||||
if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){
|
||||
/* disable ADC regular channel group external trigger */
|
||||
ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETEIC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable ADC software trigger
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel_group: select the channel group
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg ADC_REGULAR_CHANNEL: regular channel group
|
||||
\arg ADC_INSERTED_CHANNEL: inserted channel group
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_software_trigger_enable(uint32_t adc_periph , uint8_t adc_channel_group)
|
||||
{
|
||||
if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){
|
||||
/* enable ADC regular channel group software trigger */
|
||||
ADC_CTL1(adc_periph) |= ADC_CTL1_SWRCST;
|
||||
}
|
||||
if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){
|
||||
/* enable ADC inserted channel group software trigger */
|
||||
ADC_CTL1(adc_periph) |= ADC_CTL1_SWICST;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
*/
|
||||
uint16_t adc_regular_data_read(uint32_t adc_periph)
|
||||
{
|
||||
return (uint16_t)(ADC_RDATA(adc_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read ADC inserted group data register
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] inserted_channel : insert channel select
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_INSERTED_CHANNEL_0: inserted Channel0
|
||||
\arg ADC_INSERTED_CHANNEL_1: inserted channel1
|
||||
\arg ADC_INSERTED_CHANNEL_2: inserted Channel2
|
||||
\arg ADC_INSERTED_CHANNEL_3: inserted Channel3
|
||||
\param[out] none
|
||||
\retval the conversion value
|
||||
*/
|
||||
uint16_t adc_inserted_data_read(uint32_t adc_periph , uint8_t inserted_channel)
|
||||
{
|
||||
uint32_t idata;
|
||||
/* read the data of the selected channel */
|
||||
switch(inserted_channel){
|
||||
case ADC_INSERTED_CHANNEL_0:
|
||||
/* read the data of channel 0 */
|
||||
idata = ADC_IDATA0(adc_periph);
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL_1:
|
||||
/* read the data of channel 1 */
|
||||
idata = ADC_IDATA1(adc_periph);
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL_2:
|
||||
/* read the data of channel 2 */
|
||||
idata = ADC_IDATA2(adc_periph);
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL_3:
|
||||
/* read the data of channel 3 */
|
||||
idata = ADC_IDATA3(adc_periph);
|
||||
break;
|
||||
default:
|
||||
idata = 0U;
|
||||
break;
|
||||
}
|
||||
return (uint16_t)idata;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read the last ADC0 and ADC1 conversion result data in sync mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the conversion value
|
||||
*/
|
||||
uint32_t adc_sync_mode_convert_value_read(void)
|
||||
{
|
||||
/* return conversion value */
|
||||
return ADC_RDATA(ADC0);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC analog watchdog single channel
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel: the selected ADC channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_CHANNEL_x: ADC Channelx(x=0..17)(x=16 and x=17 are only for ADC0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel)
|
||||
{
|
||||
ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL);
|
||||
/* analog watchdog channel select */
|
||||
ADC_CTL0(adc_periph) |= (uint32_t)adc_channel;
|
||||
ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC analog watchdog group channel
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel_group: the channel group use analog watchdog
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_REGULAR_CHANNEL: regular channel group
|
||||
\arg ADC_INSERTED_CHANNEL: inserted channel group
|
||||
\arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group)
|
||||
{
|
||||
ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC);
|
||||
/* select the group */
|
||||
switch(adc_channel_group){
|
||||
case ADC_REGULAR_CHANNEL:
|
||||
/* regular channel analog watchdog enable */
|
||||
ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN;
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL:
|
||||
/* inserted channel analog watchdog enable */
|
||||
ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_IWDEN;
|
||||
break;
|
||||
case ADC_REGULAR_INSERTED_CHANNEL:
|
||||
/* regular and inserted channel analog watchdog enable */
|
||||
ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable ADC analog watchdog
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_watchdog_disable(uint32_t adc_periph)
|
||||
{
|
||||
ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC analog watchdog threshold
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] low_threshold: analog watchdog low threshold,0..4095
|
||||
\param[in] high_threshold: analog watchdog high threshold,0..4095
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_watchdog_threshold_config(uint32_t adc_periph , uint16_t low_threshold , uint16_t high_threshold)
|
||||
{
|
||||
ADC_WDLT(adc_periph) = (uint32_t)WDLT_WDLT(low_threshold);
|
||||
ADC_WDHT(adc_periph) = (uint32_t)WDHT_WDHT(high_threshold);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the ADC flag bits
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_flag: the adc flag bits
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_FLAG_WDE: analog watchdog event flag
|
||||
\arg ADC_FLAG_EOC: end of group conversion flag
|
||||
\arg ADC_FLAG_EOIC: end of inserted group conversion flag
|
||||
\arg ADC_FLAG_STIC: start flag of inserted channel group
|
||||
\arg ADC_FLAG_STRC: start flag of regular channel group
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus adc_flag_get(uint32_t adc_periph , uint32_t adc_flag)
|
||||
{
|
||||
FlagStatus reval = RESET;
|
||||
if(ADC_STAT(adc_periph) & adc_flag){
|
||||
reval = SET;
|
||||
}
|
||||
return reval;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear the ADC flag bits
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_flag: the adc flag bits
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg ADC_FLAG_WDE: analog watchdog event flag
|
||||
\arg ADC_FLAG_EOC: end of group conversion flag
|
||||
\arg ADC_FLAG_EOIC: end of inserted group conversion flag
|
||||
\arg ADC_FLAG_STIC: start flag of inserted channel group
|
||||
\arg ADC_FLAG_STRC: start flag of regular channel group
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_flag_clear(uint32_t adc_periph , uint32_t adc_flag)
|
||||
{
|
||||
ADC_STAT(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
|
||||
*/
|
||||
FlagStatus adc_regular_software_startconv_flag_get(uint32_t adc_periph)
|
||||
{
|
||||
FlagStatus reval = RESET;
|
||||
if((uint32_t)RESET != (ADC_STAT(adc_periph) & ADC_STAT_STRC)){
|
||||
reval = SET;
|
||||
}
|
||||
return reval;
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
*/
|
||||
FlagStatus adc_inserted_software_startconv_flag_get(uint32_t adc_periph)
|
||||
{
|
||||
FlagStatus reval = RESET;
|
||||
if((uint32_t)RESET != (ADC_STAT(adc_periph) & ADC_STAT_STIC)){
|
||||
reval = SET;
|
||||
}
|
||||
return reval;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the ADC interrupt bits
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_interrupt: the adc interrupt bits
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_INT_FLAG_WDE: analog watchdog interrupt
|
||||
\arg ADC_INT_FLAG_EOC: end of group conversion interrupt
|
||||
\arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus adc_interrupt_flag_get(uint32_t adc_periph , uint32_t adc_interrupt)
|
||||
{
|
||||
FlagStatus interrupt_flag = RESET;
|
||||
uint32_t state;
|
||||
/* check the interrupt bits */
|
||||
switch(adc_interrupt){
|
||||
case ADC_INT_FLAG_WDE:
|
||||
/* get the ADC analog watchdog interrupt bits */
|
||||
state = ADC_STAT(adc_periph) & ADC_STAT_WDE;
|
||||
if((ADC_CTL0(adc_periph) & ADC_CTL0_WDEIE) && state){
|
||||
interrupt_flag = SET;
|
||||
}
|
||||
break;
|
||||
case ADC_INT_FLAG_EOC:
|
||||
/* get the ADC end of group conversion interrupt bits */
|
||||
state = ADC_STAT(adc_periph) & ADC_STAT_EOC;
|
||||
if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){
|
||||
interrupt_flag = SET;
|
||||
}
|
||||
break;
|
||||
case ADC_INT_FLAG_EOIC:
|
||||
/* get the ADC end of inserted group conversion interrupt bits */
|
||||
state = ADC_STAT(adc_periph) & ADC_STAT_EOIC;
|
||||
if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){
|
||||
interrupt_flag = SET;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return interrupt_flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear the ADC flag
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_interrupt: the adc status flag
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg ADC_INT_FLAG_WDE: analog watchdog interrupt
|
||||
\arg ADC_INT_FLAG_EOC: end of group conversion interrupt
|
||||
\arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_interrupt_flag_clear(uint32_t adc_periph , uint32_t adc_interrupt)
|
||||
{
|
||||
ADC_STAT(adc_periph) &= ~((uint32_t)adc_interrupt);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable ADC interrupt
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_interrupt: the adc interrupt
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg ADC_INT_WDE: analog watchdog interrupt flag
|
||||
\arg ADC_INT_EOC: end of group conversion interrupt flag
|
||||
\arg ADC_INT_EOIC: end of inserted group conversion interrupt flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_interrupt_enable(uint32_t adc_periph , uint32_t adc_interrupt)
|
||||
{
|
||||
/* enable ADC analog watchdog interrupt */
|
||||
if(0U != (adc_interrupt & ADC_INT_WDE)){
|
||||
ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDEIE;
|
||||
}
|
||||
/* enable ADC end of group conversion interrupt */
|
||||
if(0U != (adc_interrupt & ADC_INT_EOC)){
|
||||
ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOCIE;
|
||||
}
|
||||
/* enable ADC end of inserted group conversion interrupt */
|
||||
if(0U != (adc_interrupt & ADC_INT_EOIC)){
|
||||
ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOICIE;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable ADC interrupt
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_interrupt: the adc interrupt flag
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg ADC_INT_WDE: analog watchdog interrupt flag
|
||||
\arg ADC_INT_EOC: end of group conversion interrupt flag
|
||||
\arg ADC_INT_EOIC: end of inserted group conversion interrupt flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt)
|
||||
{
|
||||
/* disable ADC analog watchdog interrupt */
|
||||
if(0U != (adc_interrupt & ADC_INT_WDE)){
|
||||
ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_WDEIE;
|
||||
}
|
||||
/* disable ADC end of group conversion interrupt */
|
||||
if(0U != (adc_interrupt & ADC_INT_EOC)){
|
||||
ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOCIE;
|
||||
}
|
||||
/* disable ADC end of inserted group conversion interrupt */
|
||||
if(0U != (adc_interrupt & ADC_INT_EOIC)){
|
||||
ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOICIE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,992 @@
|
||||
/*!
|
||||
\file gd32c10x_adc.c
|
||||
\brief ADC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_adc.h"
|
||||
|
||||
/* discontinuous mode macro*/
|
||||
#define ADC_CHANNEL_LENGTH_SUBTRACT_ONE ((uint8_t)1U)
|
||||
|
||||
/* ADC regular channel macro */
|
||||
#define ADC_REGULAR_CHANNEL_RANK_SIX ((uint8_t)6U)
|
||||
#define ADC_REGULAR_CHANNEL_RANK_TWELVE ((uint8_t)12U)
|
||||
#define ADC_REGULAR_CHANNEL_RANK_SIXTEEN ((uint8_t)16U)
|
||||
#define ADC_REGULAR_CHANNEL_RANK_LENGTH ((uint8_t)5U)
|
||||
|
||||
/* ADC sampling time macro */
|
||||
#define ADC_CHANNEL_SAMPLE_TEN ((uint8_t)10U)
|
||||
#define ADC_CHANNEL_SAMPLE_EIGHTEEN ((uint8_t)18U)
|
||||
#define ADC_CHANNEL_SAMPLE_LENGTH ((uint8_t)3U)
|
||||
|
||||
/* ADC inserted channel macro */
|
||||
#define ADC_INSERTED_CHANNEL_RANK_LENGTH ((uint8_t)5U)
|
||||
#define ADC_INSERTED_CHANNEL_SHIFT_LENGTH ((uint8_t)15U)
|
||||
|
||||
/* ADC inserted channel offset macro */
|
||||
#define ADC_OFFSET_LENGTH ((uint8_t)3U)
|
||||
#define ADC_OFFSET_SHIFT_LENGTH ((uint8_t)4U)
|
||||
|
||||
/*!
|
||||
\brief reset ADC
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_deinit(uint32_t adc_periph)
|
||||
{
|
||||
switch(adc_periph){
|
||||
case ADC0:
|
||||
/* reset ADC0 */
|
||||
rcu_periph_reset_enable(RCU_ADC0RST);
|
||||
rcu_periph_reset_disable(RCU_ADC0RST);
|
||||
break;
|
||||
case ADC1:
|
||||
/* reset ADC1 */
|
||||
rcu_periph_reset_enable(RCU_ADC1RST);
|
||||
rcu_periph_reset_disable(RCU_ADC1RST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the ADC sync mode
|
||||
\param[in] mode: ADC mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_MODE_FREE: all the ADCs work independently
|
||||
\arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL: ADC0 and ADC1 work in combined regular parallel + inserted parallel mode
|
||||
\arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION: ADC0 and ADC1 work in combined regular parallel + trigger rotation mode
|
||||
\arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode
|
||||
\arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode
|
||||
\arg ADC_DAUL_INSERTED_PARALLEL: ADC0 and ADC1 work in inserted parallel mode only
|
||||
\arg ADC_DAUL_REGULAL_PARALLEL: ADC0 and ADC1 work in regular parallel mode only
|
||||
\arg ADC_DAUL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in follow-up fast mode only
|
||||
\arg ADC_DAUL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in follow-up slow mode only
|
||||
\arg ADC_DAUL_INSERTED_TRIGGER_ROTATION: ADC0 and ADC1 work in trigger rotation mode only
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_mode_config(uint32_t mode)
|
||||
{
|
||||
ADC_CTL0(ADC0) &= ~(ADC_CTL0_SYNCM);
|
||||
ADC_CTL0(ADC0) |= mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable or disable ADC special function
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] function: the function to config
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_SCAN_MODE: scan mode select
|
||||
\arg ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically
|
||||
\arg ADC_CONTINUOUS_MODE: continuous mode select
|
||||
\param[in] newvalue: ENABLE or DISABLE
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_special_function_config(uint32_t adc_periph , uint32_t function , ControlStatus newvalue)
|
||||
{
|
||||
if(newvalue){
|
||||
if(0U != (function & ADC_SCAN_MODE)){
|
||||
/* enable scan mode */
|
||||
ADC_CTL0(adc_periph) |= ADC_SCAN_MODE;
|
||||
}
|
||||
if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){
|
||||
/* enable inserted channel group convert automatically */
|
||||
ADC_CTL0(adc_periph) |= ADC_INSERTED_CHANNEL_AUTO;
|
||||
}
|
||||
if(0U != (function & ADC_CONTINUOUS_MODE)){
|
||||
/* enable continuous mode */
|
||||
ADC_CTL1(adc_periph) |= ADC_CONTINUOUS_MODE;
|
||||
}
|
||||
}else{
|
||||
if(0U != (function & ADC_SCAN_MODE)){
|
||||
/* disable scan mode */
|
||||
ADC_CTL0(adc_periph) &= ~ADC_SCAN_MODE;
|
||||
}
|
||||
if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){
|
||||
/* disable inserted channel group convert automatically */
|
||||
ADC_CTL0(adc_periph) &= ~ADC_INSERTED_CHANNEL_AUTO;
|
||||
}
|
||||
if(0U != (function & ADC_CONTINUOUS_MODE)){
|
||||
/* disable continuous mode */
|
||||
ADC_CTL1(adc_periph) &= ~ADC_CONTINUOUS_MODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC data alignment
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] data_alignment: data alignment select
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_DATAALIGN_RIGHT: LSB alignment
|
||||
\arg ADC_DATAALIGN_LEFT: MSB alignment
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_data_alignment_config(uint32_t adc_periph , uint32_t data_alignment)
|
||||
{
|
||||
if(ADC_DATAALIGN_RIGHT != data_alignment){
|
||||
/* MSB alignment */
|
||||
ADC_CTL1(adc_periph) |= ADC_CTL1_DAL;
|
||||
}else{
|
||||
/* LSB alignment */
|
||||
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable ADC interface
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_enable(uint32_t adc_periph)
|
||||
{
|
||||
if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){
|
||||
/* enable ADC */
|
||||
ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable ADC interface
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_disable(uint32_t adc_periph)
|
||||
{
|
||||
/* disable ADC */
|
||||
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief ADC calibration and reset calibration
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_calibration_enable(uint32_t adc_periph)
|
||||
{
|
||||
/* reset the selected ADC calibration registers */
|
||||
ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB;
|
||||
/* check the RSTCLB bit state */
|
||||
while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){
|
||||
}
|
||||
/* enable ADC calibration process */
|
||||
ADC_CTL1(adc_periph) |= ADC_CTL1_CLB;
|
||||
/* check the CLB bit state */
|
||||
while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable the temperature sensor and Vrefint channel
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_tempsensor_vrefint_enable(void)
|
||||
{
|
||||
/* enable the temperature sensor and Vrefint channel */
|
||||
ADC_CTL1(ADC0) |= ADC_CTL1_TSVREN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable the temperature sensor and Vrefint channel
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_tempsensor_vrefint_disable(void)
|
||||
{
|
||||
/* disable the temperature sensor and Vrefint channel */
|
||||
ADC_CTL1(ADC0) &= ~ADC_CTL1_TSVREN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC resolution
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] resolution: ADC resolution
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_RESOLUTION_12B: 12-bit ADC resolution
|
||||
\arg ADC_RESOLUTION_10B: 10-bit ADC resolution
|
||||
\arg ADC_RESOLUTION_8B: 8-bit ADC resolution
|
||||
\arg ADC_RESOLUTION_6B: 6-bit ADC resolution
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_resolution_config(uint32_t adc_periph , uint32_t resolution)
|
||||
{
|
||||
ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_DRES);
|
||||
ADC_OVSAMPCTL(adc_periph) |= (uint32_t)resolution;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC oversample mode
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] mode: ADC oversampling mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger
|
||||
\arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger
|
||||
\param[in] shift: ADC oversampling shift
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift
|
||||
\arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift
|
||||
\param[in] ratio: ADC oversampling ratio
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio multiple 2
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio multiple 4
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio multiple 8
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio multiple 16
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio multiple 32
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio multiple 64
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio multiple 128
|
||||
\arg ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio multiple 256
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_oversample_mode_config(uint32_t adc_periph, uint32_t mode, uint16_t shift, uint8_t ratio)
|
||||
{
|
||||
if(ADC_OVERSAMPLING_ONE_CONVERT == mode){
|
||||
ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS;
|
||||
}else{
|
||||
ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS);
|
||||
}
|
||||
/* config the shift and ratio */
|
||||
ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS));
|
||||
ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable ADC oversample mode
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_oversample_mode_enable(uint32_t adc_periph)
|
||||
{
|
||||
ADC_OVSAMPCTL(adc_periph) |= ADC_OVSAMPCTL_OVSEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable ADC oversample mode
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_oversample_mode_disable(uint32_t adc_periph)
|
||||
{
|
||||
ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DMA request
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_dma_mode_enable(uint32_t adc_periph)
|
||||
{
|
||||
/* enable DMA request */
|
||||
ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DMA request
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_dma_mode_disable(uint32_t adc_periph)
|
||||
{
|
||||
/* disable DMA request */
|
||||
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC discontinuous mode
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel_group: select the channel group
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_REGULAR_CHANNEL: regular channel group
|
||||
\arg ADC_INSERTED_CHANNEL: inserted channel group
|
||||
\arg ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of regular & inserted channel
|
||||
\param[in] length: number of conversions in discontinuous mode,the number can be 1..8
|
||||
for regular channel ,the number has no effect for inserted channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length)
|
||||
{
|
||||
/* disable discontinuous mode of regular & inserted channel */
|
||||
ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_DISRC | ADC_CTL0_DISIC));
|
||||
switch(adc_channel_group){
|
||||
case ADC_REGULAR_CHANNEL:
|
||||
/* config the number of conversions in discontinuous mode */
|
||||
ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM);
|
||||
ADC_CTL0(adc_periph) |= CTL0_DISNUM(((uint32_t)length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE));
|
||||
/* enable regular channel group discontinuous mode */
|
||||
ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC;
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL:
|
||||
/* enable inserted channel group discontinuous mode */
|
||||
ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC;
|
||||
break;
|
||||
case ADC_CHANNEL_DISCON_DISABLE:
|
||||
/* disable discontinuous mode of regular & inserted channel */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the length of regular channel group or inserted channel group
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel_group: select the channel group
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_REGULAR_CHANNEL: regular channel group
|
||||
\arg ADC_INSERTED_CHANNEL: inserted channel group
|
||||
\param[in] length: the length of the channel
|
||||
regular channel 1-16
|
||||
inserted channel 1-4
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length)
|
||||
{
|
||||
switch(adc_channel_group){
|
||||
case ADC_REGULAR_CHANNEL:
|
||||
/* configure the length of regular channel group */
|
||||
ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL);
|
||||
ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE));
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL:
|
||||
/* configure the length of inserted channel group */
|
||||
ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL);
|
||||
ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC regular channel
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] rank: the regular group sequence rank,this parameter must be between 0 to 15
|
||||
\param[in] adc_channel: the selected ADC channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx
|
||||
\param[in] sample_time: the sample time value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_SAMPLETIME_1POINT5: 1.5 cycles
|
||||
\arg ADC_SAMPLETIME_7POINT5: 7.5 cycles
|
||||
\arg ADC_SAMPLETIME_13POINT5: 13.5 cycles
|
||||
\arg ADC_SAMPLETIME_28POINT5: 28.5 cycles
|
||||
\arg ADC_SAMPLETIME_41POINT5: 41.5 cycles
|
||||
\arg ADC_SAMPLETIME_55POINT5: 55.5 cycles
|
||||
\arg ADC_SAMPLETIME_71POINT5: 71.5 cycles
|
||||
\arg ADC_SAMPLETIME_239POINT5: 239.5 cycles
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_regular_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time)
|
||||
{
|
||||
uint32_t rsq,sampt;
|
||||
|
||||
/* ADC regular sequence config */
|
||||
if(rank < ADC_REGULAR_CHANNEL_RANK_SIX){
|
||||
/* the regular group sequence rank is smaller than six */
|
||||
rsq = ADC_RSQ2(adc_periph);
|
||||
rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank)));
|
||||
/* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */
|
||||
rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank));
|
||||
ADC_RSQ2(adc_periph) = rsq;
|
||||
}else if(rank < ADC_REGULAR_CHANNEL_RANK_TWELVE){
|
||||
/* the regular group sequence rank is smaller than twelve */
|
||||
rsq = ADC_RSQ1(adc_periph);
|
||||
rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX))));
|
||||
/* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */
|
||||
rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX)));
|
||||
ADC_RSQ1(adc_periph) = rsq;
|
||||
}else if(rank < ADC_REGULAR_CHANNEL_RANK_SIXTEEN){
|
||||
/* the regular group sequence rank is smaller than sixteen */
|
||||
rsq = ADC_RSQ0(adc_periph);
|
||||
rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE))));
|
||||
/* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */
|
||||
rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE)));
|
||||
ADC_RSQ0(adc_periph) = rsq;
|
||||
}else{
|
||||
}
|
||||
|
||||
/* ADC sampling time config */
|
||||
if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){
|
||||
/* the regular group sequence rank is smaller than ten */
|
||||
sampt = ADC_SAMPT1(adc_periph);
|
||||
sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel)));
|
||||
/* channel sample time set*/
|
||||
sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel));
|
||||
ADC_SAMPT1(adc_periph) = sampt;
|
||||
}else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){
|
||||
/* the regular group sequence rank is smaller than eighteen */
|
||||
sampt = ADC_SAMPT0(adc_periph);
|
||||
sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN))));
|
||||
/* channel sample time set*/
|
||||
sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN)));
|
||||
ADC_SAMPT0(adc_periph) = sampt;
|
||||
}else{
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC inserted channel
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3
|
||||
\param[in] adc_channel: the selected ADC channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx
|
||||
\param[in] sample_time: The sample time value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_SAMPLETIME_1POINT5: 1.5 cycles
|
||||
\arg ADC_SAMPLETIME_7POINT5: 7.5 cycles
|
||||
\arg ADC_SAMPLETIME_13POINT5: 13.5 cycles
|
||||
\arg ADC_SAMPLETIME_28POINT5: 28.5 cycles
|
||||
\arg ADC_SAMPLETIME_41POINT5: 41.5 cycles
|
||||
\arg ADC_SAMPLETIME_55POINT5: 55.5 cycles
|
||||
\arg ADC_SAMPLETIME_71POINT5: 71.5 cycles
|
||||
\arg ADC_SAMPLETIME_239POINT5: 239.5 cycles
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_inserted_channel_config(uint32_t adc_periph , uint8_t rank , uint8_t adc_channel , uint32_t sample_time)
|
||||
{
|
||||
uint8_t inserted_length;
|
||||
uint32_t isq,sampt;
|
||||
|
||||
/* get inserted channel group length */
|
||||
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)));
|
||||
ADC_ISQ(adc_periph) = isq;
|
||||
|
||||
/* ADC sampling time config */
|
||||
if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){
|
||||
/* the inserted group sequence rank is smaller than ten */
|
||||
sampt = ADC_SAMPT1(adc_periph);
|
||||
sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel)));
|
||||
/* channel sample time set*/
|
||||
sampt |= (uint32_t) sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel);
|
||||
ADC_SAMPT1(adc_periph) = sampt;
|
||||
}else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){
|
||||
/* the inserted group sequence rank is smaller than eighteen */
|
||||
sampt = ADC_SAMPT0(adc_periph);
|
||||
sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN))));
|
||||
/* channel sample time set*/
|
||||
sampt |= ((uint32_t)sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN)));
|
||||
ADC_SAMPT0(adc_periph) = sampt;
|
||||
}else{
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC inserted channel offset
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] inserted_channel : insert channel select
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_INSERTED_CHANNEL_0: inserted channel0
|
||||
\arg ADC_INSERTED_CHANNEL_1: inserted channel1
|
||||
\arg ADC_INSERTED_CHANNEL_2: inserted channel2
|
||||
\arg ADC_INSERTED_CHANNEL_3: inserted channel3
|
||||
\param[in] offset : the offset data
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_inserted_channel_offset_config(uint32_t adc_periph , uint8_t inserted_channel , uint16_t offset)
|
||||
{
|
||||
uint8_t inserted_length;
|
||||
uint32_t num = 0U;
|
||||
|
||||
inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U);
|
||||
num = ((uint32_t)ADC_OFFSET_LENGTH - ((uint32_t)inserted_length - (uint32_t)inserted_channel));
|
||||
|
||||
if(num <= ADC_OFFSET_LENGTH){
|
||||
/* calculate the offset of the register */
|
||||
num = num * ADC_OFFSET_SHIFT_LENGTH;
|
||||
/* config the offset of the selected channels */
|
||||
REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC external trigger source
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel_group: select the channel group
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_REGULAR_CHANNEL: regular channel group
|
||||
\arg ADC_INSERTED_CHANNEL: inserted channel group
|
||||
\param[in] external_trigger_source: regular or inserted group trigger source
|
||||
only one parameter can be selected which is shown as below:
|
||||
for regular channel:
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T0_CH0: timer 0 CC0 event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T0_CH1: timer 0 CC1 event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T0_CH2: timer 0 CC2 event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T1_CH1: timer 1 CC1 event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T2_TRGO: timer 2 TRGO event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T3_CH3: timer 3 CC3 event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_T7_TRGO: timer 7 TRGO event select
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_EXTI_11 : external interrupt line 11
|
||||
\arg ADC0_1_EXTTRIG_REGULAR_NONE: software trigger
|
||||
for inserted channel:
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T0_TRGO: timer 0 TRGO event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T0_CH3: timer 0 CC3 event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T1_TRGO: timer 1 TRGO event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T1_CH0: timer 1 CC0 event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T2_CH3: timer 2 CC3 event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T3_TRGO: timer 3 TRGO event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_T7_CH3: timer 7 CC3 event select
|
||||
\arg ADC0_1_EXTTRIG_INSERTED_NONE: software trigger
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source)
|
||||
{
|
||||
switch(adc_channel_group){
|
||||
case ADC_REGULAR_CHANNEL:
|
||||
/* configure ADC regular group external trigger source */
|
||||
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC);
|
||||
ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source;
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL:
|
||||
/* configure ADC inserted group external trigger source */
|
||||
ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC);
|
||||
ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable ADC external trigger
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel_group: select the channel group
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg ADC_REGULAR_CHANNEL: regular channel group
|
||||
\arg ADC_INSERTED_CHANNEL: inserted channel group
|
||||
\param[in] newvalue: ENABLE or DISABLE
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue)
|
||||
{
|
||||
if(newvalue){
|
||||
if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){
|
||||
/* enable ADC regular channel group external trigger */
|
||||
ADC_CTL1(adc_periph) |= ADC_CTL1_ETERC;
|
||||
}
|
||||
if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){
|
||||
/* enable ADC inserted channel group external trigger */
|
||||
ADC_CTL1(adc_periph) |= ADC_CTL1_ETEIC;
|
||||
}
|
||||
}else{
|
||||
if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){
|
||||
/* disable ADC regular channel group external trigger */
|
||||
ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETERC;
|
||||
}
|
||||
if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){
|
||||
/* disable ADC regular channel group external trigger */
|
||||
ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETEIC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable ADC software trigger
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel_group: select the channel group
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg ADC_REGULAR_CHANNEL: regular channel group
|
||||
\arg ADC_INSERTED_CHANNEL: inserted channel group
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_software_trigger_enable(uint32_t adc_periph , uint8_t adc_channel_group)
|
||||
{
|
||||
if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){
|
||||
/* enable ADC regular channel group software trigger */
|
||||
ADC_CTL1(adc_periph) |= ADC_CTL1_SWRCST;
|
||||
}
|
||||
if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){
|
||||
/* enable ADC inserted channel group software trigger */
|
||||
ADC_CTL1(adc_periph) |= ADC_CTL1_SWICST;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
*/
|
||||
uint16_t adc_regular_data_read(uint32_t adc_periph)
|
||||
{
|
||||
return (uint16_t)(ADC_RDATA(adc_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read ADC inserted group data register
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] inserted_channel : insert channel select
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_INSERTED_CHANNEL_0: inserted Channel0
|
||||
\arg ADC_INSERTED_CHANNEL_1: inserted channel1
|
||||
\arg ADC_INSERTED_CHANNEL_2: inserted Channel2
|
||||
\arg ADC_INSERTED_CHANNEL_3: inserted Channel3
|
||||
\param[out] none
|
||||
\retval the conversion value
|
||||
*/
|
||||
uint16_t adc_inserted_data_read(uint32_t adc_periph , uint8_t inserted_channel)
|
||||
{
|
||||
uint32_t idata;
|
||||
/* read the data of the selected channel */
|
||||
switch(inserted_channel){
|
||||
case ADC_INSERTED_CHANNEL_0:
|
||||
/* read the data of channel 0 */
|
||||
idata = ADC_IDATA0(adc_periph);
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL_1:
|
||||
/* read the data of channel 1 */
|
||||
idata = ADC_IDATA1(adc_periph);
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL_2:
|
||||
/* read the data of channel 2 */
|
||||
idata = ADC_IDATA2(adc_periph);
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL_3:
|
||||
/* read the data of channel 3 */
|
||||
idata = ADC_IDATA3(adc_periph);
|
||||
break;
|
||||
default:
|
||||
idata = 0U;
|
||||
break;
|
||||
}
|
||||
return (uint16_t)idata;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read the last ADC0 and ADC1 conversion result data in sync mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the conversion value
|
||||
*/
|
||||
uint32_t adc_sync_mode_convert_value_read(void)
|
||||
{
|
||||
/* return conversion value */
|
||||
return ADC_RDATA(ADC0);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC analog watchdog single channel
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel: the selected ADC channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_CHANNEL_x: ADC Channelx(x=0..17)(x=16 and x=17 are only for ADC0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel)
|
||||
{
|
||||
ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL);
|
||||
/* analog watchdog channel select */
|
||||
ADC_CTL0(adc_periph) |= (uint32_t)adc_channel;
|
||||
ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC analog watchdog group channel
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_channel_group: the channel group use analog watchdog
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_REGULAR_CHANNEL: regular channel group
|
||||
\arg ADC_INSERTED_CHANNEL: inserted channel group
|
||||
\arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group)
|
||||
{
|
||||
ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC);
|
||||
/* select the group */
|
||||
switch(adc_channel_group){
|
||||
case ADC_REGULAR_CHANNEL:
|
||||
/* regular channel analog watchdog enable */
|
||||
ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN;
|
||||
break;
|
||||
case ADC_INSERTED_CHANNEL:
|
||||
/* inserted channel analog watchdog enable */
|
||||
ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_IWDEN;
|
||||
break;
|
||||
case ADC_REGULAR_INSERTED_CHANNEL:
|
||||
/* regular and inserted channel analog watchdog enable */
|
||||
ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable ADC analog watchdog
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_watchdog_disable(uint32_t adc_periph)
|
||||
{
|
||||
ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure ADC analog watchdog threshold
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] low_threshold: analog watchdog low threshold,0..4095
|
||||
\param[in] high_threshold: analog watchdog high threshold,0..4095
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_watchdog_threshold_config(uint32_t adc_periph , uint16_t low_threshold , uint16_t high_threshold)
|
||||
{
|
||||
ADC_WDLT(adc_periph) = (uint32_t)WDLT_WDLT(low_threshold);
|
||||
ADC_WDHT(adc_periph) = (uint32_t)WDHT_WDHT(high_threshold);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the ADC flag bits
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_flag: the adc flag bits
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_FLAG_WDE: analog watchdog event flag
|
||||
\arg ADC_FLAG_EOC: end of group conversion flag
|
||||
\arg ADC_FLAG_EOIC: end of inserted group conversion flag
|
||||
\arg ADC_FLAG_STIC: start flag of inserted channel group
|
||||
\arg ADC_FLAG_STRC: start flag of regular channel group
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus adc_flag_get(uint32_t adc_periph , uint32_t adc_flag)
|
||||
{
|
||||
FlagStatus reval = RESET;
|
||||
if(ADC_STAT(adc_periph) & adc_flag){
|
||||
reval = SET;
|
||||
}
|
||||
return reval;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear the ADC flag bits
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_flag: the adc flag bits
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg ADC_FLAG_WDE: analog watchdog event flag
|
||||
\arg ADC_FLAG_EOC: end of group conversion flag
|
||||
\arg ADC_FLAG_EOIC: end of inserted group conversion flag
|
||||
\arg ADC_FLAG_STIC: start flag of inserted channel group
|
||||
\arg ADC_FLAG_STRC: start flag of regular channel group
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_flag_clear(uint32_t adc_periph , uint32_t adc_flag)
|
||||
{
|
||||
ADC_STAT(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
|
||||
*/
|
||||
FlagStatus adc_regular_software_startconv_flag_get(uint32_t adc_periph)
|
||||
{
|
||||
FlagStatus reval = RESET;
|
||||
if((uint32_t)RESET != (ADC_STAT(adc_periph) & ADC_STAT_STRC)){
|
||||
reval = SET;
|
||||
}
|
||||
return reval;
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
*/
|
||||
FlagStatus adc_inserted_software_startconv_flag_get(uint32_t adc_periph)
|
||||
{
|
||||
FlagStatus reval = RESET;
|
||||
if((uint32_t)RESET != (ADC_STAT(adc_periph) & ADC_STAT_STIC)){
|
||||
reval = SET;
|
||||
}
|
||||
return reval;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the ADC interrupt bits
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_interrupt: the adc interrupt bits
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg ADC_INT_FLAG_WDE: analog watchdog interrupt
|
||||
\arg ADC_INT_FLAG_EOC: end of group conversion interrupt
|
||||
\arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus adc_interrupt_flag_get(uint32_t adc_periph , uint32_t adc_interrupt)
|
||||
{
|
||||
FlagStatus interrupt_flag = RESET;
|
||||
uint32_t state;
|
||||
/* check the interrupt bits */
|
||||
switch(adc_interrupt){
|
||||
case ADC_INT_FLAG_WDE:
|
||||
/* get the ADC analog watchdog interrupt bits */
|
||||
state = ADC_STAT(adc_periph) & ADC_STAT_WDE;
|
||||
if((ADC_CTL0(adc_periph) & ADC_CTL0_WDEIE) && state){
|
||||
interrupt_flag = SET;
|
||||
}
|
||||
break;
|
||||
case ADC_INT_FLAG_EOC:
|
||||
/* get the ADC end of group conversion interrupt bits */
|
||||
state = ADC_STAT(adc_periph) & ADC_STAT_EOC;
|
||||
if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){
|
||||
interrupt_flag = SET;
|
||||
}
|
||||
break;
|
||||
case ADC_INT_FLAG_EOIC:
|
||||
/* get the ADC end of inserted group conversion interrupt bits */
|
||||
state = ADC_STAT(adc_periph) & ADC_STAT_EOIC;
|
||||
if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){
|
||||
interrupt_flag = SET;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return interrupt_flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear the ADC flag
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_interrupt: the adc status flag
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg ADC_INT_FLAG_WDE: analog watchdog interrupt
|
||||
\arg ADC_INT_FLAG_EOC: end of group conversion interrupt
|
||||
\arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_interrupt_flag_clear(uint32_t adc_periph , uint32_t adc_interrupt)
|
||||
{
|
||||
ADC_STAT(adc_periph) &= ~((uint32_t)adc_interrupt);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable ADC interrupt
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_interrupt: the adc interrupt
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg ADC_INT_WDE: analog watchdog interrupt flag
|
||||
\arg ADC_INT_EOC: end of group conversion interrupt flag
|
||||
\arg ADC_INT_EOIC: end of inserted group conversion interrupt flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_interrupt_enable(uint32_t adc_periph , uint32_t adc_interrupt)
|
||||
{
|
||||
/* enable ADC analog watchdog interrupt */
|
||||
if(0U != (adc_interrupt & ADC_INT_WDE)){
|
||||
ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDEIE;
|
||||
}
|
||||
/* enable ADC end of group conversion interrupt */
|
||||
if(0U != (adc_interrupt & ADC_INT_EOC)){
|
||||
ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOCIE;
|
||||
}
|
||||
/* enable ADC end of inserted group conversion interrupt */
|
||||
if(0U != (adc_interrupt & ADC_INT_EOIC)){
|
||||
ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOICIE;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable ADC interrupt
|
||||
\param[in] adc_periph: ADCx,x=0,1
|
||||
\param[in] adc_interrupt: the adc interrupt flag
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg ADC_INT_WDE: analog watchdog interrupt flag
|
||||
\arg ADC_INT_EOC: end of group conversion interrupt flag
|
||||
\arg ADC_INT_EOIC: end of inserted group conversion interrupt flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt)
|
||||
{
|
||||
/* disable ADC analog watchdog interrupt */
|
||||
if(0U != (adc_interrupt & ADC_INT_WDE)){
|
||||
ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_WDEIE;
|
||||
}
|
||||
/* disable ADC end of group conversion interrupt */
|
||||
if(0U != (adc_interrupt & ADC_INT_EOC)){
|
||||
ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOCIE;
|
||||
}
|
||||
/* disable ADC end of inserted group conversion interrupt */
|
||||
if(0U != (adc_interrupt & ADC_INT_EOIC)){
|
||||
ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOICIE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
/*!
|
||||
\file gd32c10x_bkp.c
|
||||
\brief BKP driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_bkp.h"
|
||||
|
||||
/* BKP register bits offset */
|
||||
#define BKP_TAMPER_BITS_OFFSET ((uint32_t)8U)
|
||||
|
||||
/*!
|
||||
\brief reset BKP registers
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_deinit(void)
|
||||
{
|
||||
/* reset BKP domain register*/
|
||||
rcu_bkp_reset_enable();
|
||||
rcu_bkp_reset_disable();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief write BKP data register
|
||||
\param[in] register_number: refer to bkp_data_register_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg BKP_DATA_x(x = 0..41): bkp data register number x
|
||||
\param[in] data: the data to be write in BKP data register
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_data_write(bkp_data_register_enum register_number, uint16_t data)
|
||||
{
|
||||
if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){
|
||||
BKP_DATA10_41(register_number-1U) = data;
|
||||
}else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){
|
||||
BKP_DATA0_9(register_number-1U) = data;
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read BKP data register
|
||||
\param[in] register_number: refer to bkp_data_register_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg BKP_DATA_x(x = 0..41): bkp data register number x
|
||||
\param[out] none
|
||||
\retval data of BKP data register
|
||||
*/
|
||||
uint16_t bkp_data_read(bkp_data_register_enum register_number)
|
||||
{
|
||||
uint16_t data = 0U;
|
||||
|
||||
/* get the data from the BKP data register */
|
||||
if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){
|
||||
data = BKP_DATA10_41(register_number-1U);
|
||||
}else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){
|
||||
data = BKP_DATA0_9(register_number-1U);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable RTC clock calibration output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_calibration_output_enable(void)
|
||||
{
|
||||
BKP_OCTL |= (uint16_t)BKP_OCTL_COEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable RTC clock calibration output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_calibration_output_disable(void)
|
||||
{
|
||||
BKP_OCTL &= (uint16_t)~BKP_OCTL_COEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable RTC alarm or second signal output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_signal_output_enable(void)
|
||||
{
|
||||
BKP_OCTL |= (uint16_t)BKP_OCTL_ASOEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable RTC alarm or second signal output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_signal_output_disable(void)
|
||||
{
|
||||
BKP_OCTL &= (uint16_t)~BKP_OCTL_ASOEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select RTC output
|
||||
\param[in] outputsel: RTC output selection
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg RTC_OUTPUT_ALARM_PULSE: RTC alarm pulse is selected as the RTC output
|
||||
\arg RTC_OUTPUT_SECOND_PULSE: RTC second pulse is selected as the RTC output
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_output_select(uint16_t outputsel)
|
||||
{
|
||||
uint16_t ctl = 0U;
|
||||
|
||||
/* configure BKP_OCTL_ROSEL with outputsel */
|
||||
ctl = BKP_OCTL;
|
||||
ctl &= (uint16_t)~BKP_OCTL_ROSEL;
|
||||
ctl |= outputsel;
|
||||
BKP_OCTL = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select RTC clock output
|
||||
\param[in] clocksel: RTC clock output selection
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg RTC_CLOCK_DIV_64: RTC clock div 64
|
||||
\arg RTC_CLOCK_DIV_1: RTC clock
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_clock_output_select(uint16_t clocksel)
|
||||
{
|
||||
uint16_t ctl = 0U;
|
||||
|
||||
/* configure BKP_OCTL_CCOSEL with clocksel */
|
||||
ctl = BKP_OCTL;
|
||||
ctl &= (uint16_t)~BKP_OCTL_CCOSEL;
|
||||
ctl |= clocksel;
|
||||
BKP_OCTL = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select RTC clock calibration direction
|
||||
\param[in] direction: RTC clock calibration direction
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg RTC_CLOCK_SLOW_DOWN: RTC clock slow down
|
||||
\arg RTC_CLOCK_SPEED_UP: RTC clock speed up
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_clock_calibration_direction_select(uint16_t direction)
|
||||
{
|
||||
uint16_t ctl = 0U;
|
||||
|
||||
/* configure BKP_OCTL_CALDIR with direction */
|
||||
ctl = BKP_OCTL;
|
||||
ctl &= (uint16_t)~BKP_OCTL_CALDIR;
|
||||
ctl |= direction;
|
||||
BKP_OCTL = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set RTC clock calibration value
|
||||
\param[in] value: RTC clock calibration value
|
||||
\arg 0x00 - 0x7F
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_calibration_value_set(uint8_t value)
|
||||
{
|
||||
uint16_t ctl;
|
||||
|
||||
/* configure BKP_OCTL_RCCV with value */
|
||||
ctl = BKP_OCTL;
|
||||
ctl &= (uint16_t)~BKP_OCTL_RCCV;
|
||||
ctl |= (uint16_t)OCTL_RCCV(value);
|
||||
BKP_OCTL = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable tamper detection
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_tamper_detection_enable(void)
|
||||
{
|
||||
BKP_TPCTL |= (uint16_t)BKP_TPCTL_TPEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable tamper detection
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_tamper_detection_disable(void)
|
||||
{
|
||||
BKP_TPCTL &= (uint16_t)~BKP_TPCTL_TPEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set tamper pin active level
|
||||
\param[in] level: tamper active level
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg TAMPER_PIN_ACTIVE_HIGH: the tamper pin is active high
|
||||
\arg TAMPER_PIN_ACTIVE_LOW: the tamper pin is active low
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_tamper_active_level_set(uint16_t level)
|
||||
{
|
||||
uint16_t ctl = 0U;
|
||||
|
||||
/* configure BKP_TPCTL_TPAL with level */
|
||||
ctl = BKP_TPCTL;
|
||||
ctl &= (uint16_t)~BKP_TPCTL_TPAL;
|
||||
ctl |= level;
|
||||
BKP_TPCTL = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable tamper interrupt
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_interrupt_enable(void)
|
||||
{
|
||||
BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable tamper interrupt
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_interrupt_disable(void)
|
||||
{
|
||||
BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get tamper flag state
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus bkp_flag_get(void)
|
||||
{
|
||||
if(RESET != (BKP_TPCS & BKP_FLAG_TAMPER)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear tamper flag state
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_flag_clear(void)
|
||||
{
|
||||
BKP_TPCS |= (uint16_t)(BKP_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get tamper interrupt flag state
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus bkp_interrupt_flag_get(void)
|
||||
{
|
||||
if(RESET != (BKP_TPCS & BKP_INT_FLAG_TAMPER)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear tamper interrupt flag state
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_interrupt_flag_clear(void)
|
||||
{
|
||||
BKP_TPCS |= (uint16_t)(BKP_INT_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET);
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
/*!
|
||||
\file gd32c10x_bkp.c
|
||||
\brief BKP driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_bkp.h"
|
||||
|
||||
/* BKP register bits offset */
|
||||
#define BKP_TAMPER_BITS_OFFSET ((uint32_t)8U)
|
||||
|
||||
/*!
|
||||
\brief reset BKP registers
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_deinit(void)
|
||||
{
|
||||
/* reset BKP domain register*/
|
||||
rcu_bkp_reset_enable();
|
||||
rcu_bkp_reset_disable();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief write BKP data register
|
||||
\param[in] register_number: refer to bkp_data_register_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg BKP_DATA_x(x = 0..41): bkp data register number x
|
||||
\param[in] data: the data to be write in BKP data register
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_data_write(bkp_data_register_enum register_number, uint16_t data)
|
||||
{
|
||||
if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){
|
||||
BKP_DATA10_41(register_number-1U) = data;
|
||||
}else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){
|
||||
BKP_DATA0_9(register_number-1U) = data;
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read BKP data register
|
||||
\param[in] register_number: refer to bkp_data_register_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg BKP_DATA_x(x = 0..41): bkp data register number x
|
||||
\param[out] none
|
||||
\retval data of BKP data register
|
||||
*/
|
||||
uint16_t bkp_data_read(bkp_data_register_enum register_number)
|
||||
{
|
||||
uint16_t data = 0U;
|
||||
|
||||
/* get the data from the BKP data register */
|
||||
if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){
|
||||
data = BKP_DATA10_41(register_number-1U);
|
||||
}else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){
|
||||
data = BKP_DATA0_9(register_number-1U);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable RTC clock calibration output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_calibration_output_enable(void)
|
||||
{
|
||||
BKP_OCTL |= (uint16_t)BKP_OCTL_COEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable RTC clock calibration output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_calibration_output_disable(void)
|
||||
{
|
||||
BKP_OCTL &= (uint16_t)~BKP_OCTL_COEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable RTC alarm or second signal output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_signal_output_enable(void)
|
||||
{
|
||||
BKP_OCTL |= (uint16_t)BKP_OCTL_ASOEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable RTC alarm or second signal output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_signal_output_disable(void)
|
||||
{
|
||||
BKP_OCTL &= (uint16_t)~BKP_OCTL_ASOEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select RTC output
|
||||
\param[in] outputsel: RTC output selection
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg RTC_OUTPUT_ALARM_PULSE: RTC alarm pulse is selected as the RTC output
|
||||
\arg RTC_OUTPUT_SECOND_PULSE: RTC second pulse is selected as the RTC output
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_output_select(uint16_t outputsel)
|
||||
{
|
||||
uint16_t ctl = 0U;
|
||||
|
||||
/* configure BKP_OCTL_ROSEL with outputsel */
|
||||
ctl = BKP_OCTL;
|
||||
ctl &= (uint16_t)~BKP_OCTL_ROSEL;
|
||||
ctl |= outputsel;
|
||||
BKP_OCTL = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select RTC clock output
|
||||
\param[in] clocksel: RTC clock output selection
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg RTC_CLOCK_DIV_64: RTC clock div 64
|
||||
\arg RTC_CLOCK_DIV_1: RTC clock
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_clock_output_select(uint16_t clocksel)
|
||||
{
|
||||
uint16_t ctl = 0U;
|
||||
|
||||
/* configure BKP_OCTL_CCOSEL with clocksel */
|
||||
ctl = BKP_OCTL;
|
||||
ctl &= (uint16_t)~BKP_OCTL_CCOSEL;
|
||||
ctl |= clocksel;
|
||||
BKP_OCTL = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select RTC clock calibration direction
|
||||
\param[in] direction: RTC clock calibration direction
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg RTC_CLOCK_SLOW_DOWN: RTC clock slow down
|
||||
\arg RTC_CLOCK_SPEED_UP: RTC clock speed up
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_clock_calibration_direction_select(uint16_t direction)
|
||||
{
|
||||
uint16_t ctl = 0U;
|
||||
|
||||
/* configure BKP_OCTL_CALDIR with direction */
|
||||
ctl = BKP_OCTL;
|
||||
ctl &= (uint16_t)~BKP_OCTL_CALDIR;
|
||||
ctl |= direction;
|
||||
BKP_OCTL = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set RTC clock calibration value
|
||||
\param[in] value: RTC clock calibration value
|
||||
\arg 0x00 - 0x7F
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_rtc_calibration_value_set(uint8_t value)
|
||||
{
|
||||
uint16_t ctl;
|
||||
|
||||
/* configure BKP_OCTL_RCCV with value */
|
||||
ctl = BKP_OCTL;
|
||||
ctl &= (uint16_t)~BKP_OCTL_RCCV;
|
||||
ctl |= (uint16_t)OCTL_RCCV(value);
|
||||
BKP_OCTL = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable tamper detection
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_tamper_detection_enable(void)
|
||||
{
|
||||
BKP_TPCTL |= (uint16_t)BKP_TPCTL_TPEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable tamper detection
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_tamper_detection_disable(void)
|
||||
{
|
||||
BKP_TPCTL &= (uint16_t)~BKP_TPCTL_TPEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set tamper pin active level
|
||||
\param[in] level: tamper active level
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg TAMPER_PIN_ACTIVE_HIGH: the tamper pin is active high
|
||||
\arg TAMPER_PIN_ACTIVE_LOW: the tamper pin is active low
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_tamper_active_level_set(uint16_t level)
|
||||
{
|
||||
uint16_t ctl = 0U;
|
||||
|
||||
/* configure BKP_TPCTL_TPAL with level */
|
||||
ctl = BKP_TPCTL;
|
||||
ctl &= (uint16_t)~BKP_TPCTL_TPAL;
|
||||
ctl |= level;
|
||||
BKP_TPCTL = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable tamper interrupt
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_interrupt_enable(void)
|
||||
{
|
||||
BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable tamper interrupt
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_interrupt_disable(void)
|
||||
{
|
||||
BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get tamper flag state
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus bkp_flag_get(void)
|
||||
{
|
||||
if(RESET != (BKP_TPCS & BKP_FLAG_TAMPER)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear tamper flag state
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_flag_clear(void)
|
||||
{
|
||||
BKP_TPCS |= (uint16_t)(BKP_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get tamper interrupt flag state
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus bkp_interrupt_flag_get(void)
|
||||
{
|
||||
if(RESET != (BKP_TPCS & BKP_INT_FLAG_TAMPER)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear tamper interrupt flag state
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void bkp_interrupt_flag_clear(void)
|
||||
{
|
||||
BKP_TPCS |= (uint16_t)(BKP_INT_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,127 @@
|
||||
/*!
|
||||
\file gd32c10x_crc.c
|
||||
\brief CRC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_crc.h"
|
||||
|
||||
#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU)
|
||||
#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U)
|
||||
|
||||
/*!
|
||||
\brief deinit CRC calculation unit
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_deinit(void)
|
||||
{
|
||||
CRC_DATA = CRC_DATA_RESET_VALUE;
|
||||
CRC_FDATA = CRC_FDATA_RESET_VALUE;
|
||||
CRC_CTL = (uint32_t)CRC_CTL_RST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset data register(CRC_DATA) to the value of 0xFFFFFFFF
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_data_register_reset(void)
|
||||
{
|
||||
CRC_CTL |= (uint32_t)CRC_CTL_RST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read the value of the data register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval 32-bit value of the data register
|
||||
*/
|
||||
uint32_t crc_data_register_read(void)
|
||||
{
|
||||
uint32_t data;
|
||||
data = CRC_DATA;
|
||||
return (data);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read the value of the free data register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval 8-bit value of the free data register
|
||||
*/
|
||||
uint8_t crc_free_data_register_read(void)
|
||||
{
|
||||
uint8_t fdata;
|
||||
fdata = (uint8_t)CRC_FDATA;
|
||||
return (fdata);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief write data to the free data register
|
||||
\param[in] free_data: specified 8-bit data
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_free_data_register_write(uint8_t free_data)
|
||||
{
|
||||
CRC_FDATA = (uint32_t)free_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief calculate the CRC value of a 32-bit data
|
||||
\param[in] sdata: specified 32-bit data
|
||||
\param[out] none
|
||||
\retval 32-bit value calculated by CRC
|
||||
*/
|
||||
uint32_t crc_single_data_calculate(uint32_t sdata)
|
||||
{
|
||||
CRC_DATA = sdata;
|
||||
return (CRC_DATA);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief calculate the CRC value of an array of 32-bit values
|
||||
\param[in] array: pointer to an array of 32-bit values
|
||||
\param[in] size: size of the array
|
||||
\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 index;
|
||||
for(index = 0U; index < size; index++){
|
||||
CRC_DATA = *(array+index);
|
||||
}
|
||||
return (CRC_DATA);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*!
|
||||
\file gd32c10x_crc.c
|
||||
\brief CRC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_crc.h"
|
||||
|
||||
#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU)
|
||||
#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U)
|
||||
|
||||
/*!
|
||||
\brief deinit CRC calculation unit
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_deinit(void)
|
||||
{
|
||||
CRC_DATA = CRC_DATA_RESET_VALUE;
|
||||
CRC_FDATA = CRC_FDATA_RESET_VALUE;
|
||||
CRC_CTL = (uint32_t)CRC_CTL_RST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset data register(CRC_DATA) to the value of 0xFFFFFFFF
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_data_register_reset(void)
|
||||
{
|
||||
CRC_CTL |= (uint32_t)CRC_CTL_RST;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read the value of the data register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval 32-bit value of the data register
|
||||
*/
|
||||
uint32_t crc_data_register_read(void)
|
||||
{
|
||||
uint32_t data;
|
||||
data = CRC_DATA;
|
||||
return (data);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read the value of the free data register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval 8-bit value of the free data register
|
||||
*/
|
||||
uint8_t crc_free_data_register_read(void)
|
||||
{
|
||||
uint8_t fdata;
|
||||
fdata = (uint8_t)CRC_FDATA;
|
||||
return (fdata);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief write data to the free data register
|
||||
\param[in] free_data: specified 8-bit data
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void crc_free_data_register_write(uint8_t free_data)
|
||||
{
|
||||
CRC_FDATA = (uint32_t)free_data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief calculate the CRC value of a 32-bit data
|
||||
\param[in] sdata: specified 32-bit data
|
||||
\param[out] none
|
||||
\retval 32-bit value calculated by CRC
|
||||
*/
|
||||
uint32_t crc_single_data_calculate(uint32_t sdata)
|
||||
{
|
||||
CRC_DATA = sdata;
|
||||
return (CRC_DATA);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief calculate the CRC value of an array of 32-bit values
|
||||
\param[in] array: pointer to an array of 32-bit values
|
||||
\param[in] size: size of the array
|
||||
\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 index;
|
||||
for(index = 0U; index < size; index++){
|
||||
CRC_DATA = *(array+index);
|
||||
}
|
||||
return (CRC_DATA);
|
||||
}
|
||||
@@ -0,0 +1,388 @@
|
||||
/*!
|
||||
\file gd32c10x_ctc.c
|
||||
\brief CTC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_ctc.h"
|
||||
|
||||
#define CTC_FLAG_MASK ((uint32_t)0x00000700U)
|
||||
|
||||
/* CTC register bit offset */
|
||||
#define CTC_TRIMVALUE_OFFSET ((uint32_t)8U)
|
||||
#define CTC_TRIM_VALUE_OFFSET ((uint32_t)8U)
|
||||
#define CTC_REFCAP_OFFSET ((uint32_t)16U)
|
||||
#define CTC_LIMIT_VALUE_OFFSET ((uint32_t)16U)
|
||||
|
||||
/*!
|
||||
\brief reset CTC clock trim controller
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_deinit(void)
|
||||
{
|
||||
/* reset CTC */
|
||||
rcu_periph_reset_enable(RCU_CTCRST);
|
||||
rcu_periph_reset_disable(RCU_CTCRST);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable CTC trim counter
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_counter_enable(void)
|
||||
{
|
||||
CTC_CTL0 |= (uint32_t)CTC_CTL0_CNTEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable CTC trim counter
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_counter_disable(void)
|
||||
{
|
||||
CTC_CTL0 &= (uint32_t)(~CTC_CTL0_CNTEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the IRC48M trim value
|
||||
\param[in] ctc_trim_value: 8-bit IRC48M trim value
|
||||
\arg 0x00 - 0x3F
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_irc48m_trim_value_config(uint8_t trim_value)
|
||||
{
|
||||
/* clear TRIMVALUE bits */
|
||||
CTC_CTL0 &= (~(uint32_t)CTC_CTL0_TRIMVALUE);
|
||||
/* set TRIMVALUE bits */
|
||||
CTC_CTL0 |= ((uint32_t)trim_value << CTC_TRIM_VALUE_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief generate software reference source sync pulse
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_software_refsource_pulse_generate(void)
|
||||
{
|
||||
CTC_CTL0 |= (uint32_t)CTC_CTL0_SWREFPUL;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure hardware automatically trim mode
|
||||
\param[in] hardmode:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_HARDWARE_TRIM_MODE_ENABLE: hardware automatically trim mode enable
|
||||
\arg CTC_HARDWARE_TRIM_MODE_DISABLE: hardware automatically trim mode disable
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_hardware_trim_mode_config(uint32_t hardmode)
|
||||
{
|
||||
CTC_CTL0 &= (uint32_t)(~CTC_CTL0_AUTOTRIM);
|
||||
CTC_CTL0 |= (uint32_t)hardmode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure reference signal source polarity
|
||||
\param[in] polarity:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_REFSOURCE_POLARITY_FALLING: reference signal source polarity is falling edge
|
||||
\arg CTC_REFSOURCE_POLARITY_RISING: reference signal source polarity is rising edge
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_refsource_polarity_config(uint32_t polarity)
|
||||
{
|
||||
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPOL);
|
||||
CTC_CTL1 |= (uint32_t)polarity;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select reference signal source
|
||||
\param[in] refs:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_REFSOURCE_GPIO: GPIO is selected
|
||||
\arg CTC_REFSOURCE_LXTAL: LXTAL is selected
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_refsource_signal_select(uint32_t refs)
|
||||
{
|
||||
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL);
|
||||
CTC_CTL1 |= (uint32_t)refs;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure reference signal source prescaler
|
||||
\param[in] prescaler:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_REFSOURCE_PSC_OFF: reference signal not divided
|
||||
\arg CTC_REFSOURCE_PSC_DIV2: reference signal divided by 2
|
||||
\arg CTC_REFSOURCE_PSC_DIV4: reference signal divided by 4
|
||||
\arg CTC_REFSOURCE_PSC_DIV8: reference signal divided by 8
|
||||
\arg CTC_REFSOURCE_PSC_DIV16: reference signal divided by 16
|
||||
\arg CTC_REFSOURCE_PSC_DIV32: reference signal divided by 32
|
||||
\arg CTC_REFSOURCE_PSC_DIV64: reference signal divided by 64
|
||||
\arg CTC_REFSOURCE_PSC_DIV128: reference signal divided by 128
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_refsource_prescaler_config(uint32_t prescaler)
|
||||
{
|
||||
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPSC);
|
||||
CTC_CTL1 |= (uint32_t)prescaler;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure clock trim base limit value
|
||||
\param[in] limit_value: 8-bit clock trim base limit value
|
||||
\arg 0x00 - 0xFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_clock_limit_value_config(uint8_t limit_value)
|
||||
{
|
||||
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_CKLIM);
|
||||
CTC_CTL1 |= (uint32_t)((uint32_t)limit_value << CTC_LIMIT_VALUE_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure CTC counter reload value
|
||||
\param[in] reload_value: 16-bit CTC counter reload value
|
||||
\arg 0x0000 - 0xFFFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_counter_reload_value_config(uint16_t reload_value)
|
||||
{
|
||||
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_RLVALUE);
|
||||
CTC_CTL1 |= (uint32_t)reload_value;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read CTC counter capture value when reference sync pulse occurred
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the 16-bit CTC counter capture value
|
||||
*/
|
||||
uint16_t ctc_counter_capture_value_read(void)
|
||||
{
|
||||
uint16_t capture_value = 0U;
|
||||
capture_value = (uint16_t)((CTC_STAT & CTC_STAT_REFCAP)>> CTC_REFCAP_OFFSET);
|
||||
return (capture_value);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read CTC trim counter direction when reference sync pulse occurred
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
\arg SET: CTC trim counter direction is down-counting
|
||||
\arg RESET: CTC trim counter direction is up-counting
|
||||
*/
|
||||
FlagStatus ctc_counter_direction_read(void)
|
||||
{
|
||||
if(RESET != (CTC_STAT & CTC_STAT_REFDIR)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read CTC counter reload value
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the 16-bit CTC counter reload value
|
||||
*/
|
||||
uint16_t ctc_counter_reload_value_read(void)
|
||||
{
|
||||
uint16_t reload_value = 0U;
|
||||
reload_value = (uint16_t)(CTC_CTL1 & CTC_CTL1_RLVALUE);
|
||||
return (reload_value);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read the IRC48M trim value
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the 8-bit IRC48M trim value
|
||||
*/
|
||||
uint8_t ctc_irc48m_trim_value_read(void)
|
||||
{
|
||||
uint8_t trim_value = 0U;
|
||||
trim_value = (uint8_t)((CTC_CTL0 & CTC_CTL0_TRIMVALUE) >> CTC_TRIMVALUE_OFFSET);
|
||||
return (trim_value);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable the CTC interrupt
|
||||
\param[in] interrupt: CTC interrupt enable
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg CTC_INT_CKOK: clock trim OK interrupt enable
|
||||
\arg CTC_INT_CKWARN: clock trim warning interrupt enable
|
||||
\arg CTC_INT_ERR: error interrupt enable
|
||||
\arg CTC_INT_EREF: expect reference interrupt enable
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_interrupt_enable(uint32_t interrupt)
|
||||
{
|
||||
CTC_CTL0 |= (uint32_t)interrupt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable the CTC interrupt
|
||||
\param[in] interrupt: CTC interrupt enable source
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg CTC_INT_CKOK: clock trim OK interrupt enable
|
||||
\arg CTC_INT_CKWARN: clock trim warning interrupt enable
|
||||
\arg CTC_INT_ERR: error interrupt enable
|
||||
\arg CTC_INT_EREF: expect reference interrupt enable
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_interrupt_disable(uint32_t interrupt)
|
||||
{
|
||||
CTC_CTL0 &= (uint32_t)(~interrupt);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get CTC interrupt flag
|
||||
\param[in] interrupt: the CTC interrupt flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_INT_FLAG_CKOK: clock trim OK interrupt
|
||||
\arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt
|
||||
\arg CTC_INT_FLAG_ERR: error interrupt
|
||||
\arg CTC_INT_FLAG_EREF: expect reference interrupt
|
||||
\arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt
|
||||
\arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt
|
||||
\arg CTC_INT_FLAG_TRIMERR: trim value error interrupt
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus ctc_interrupt_flag_get(uint32_t interrupt)
|
||||
{
|
||||
uint32_t intflag = 0U, intenable = 0U;
|
||||
|
||||
/* check whether the interrupt is enabled */
|
||||
if(RESET != (interrupt & CTC_FLAG_MASK)){
|
||||
intenable = CTC_CTL0 & CTC_CTL0_ERRIE;
|
||||
}else{
|
||||
intenable = CTC_CTL0 & interrupt;
|
||||
}
|
||||
|
||||
/* get interrupt flag status */
|
||||
intflag = CTC_STAT & interrupt;
|
||||
|
||||
if(intflag && intenable){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear CTC interrupt flag
|
||||
\param[in] interrupt: the CTC interrupt flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_INT_FLAG_CKOK: clock trim OK interrupt
|
||||
\arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt
|
||||
\arg CTC_INT_FLAG_ERR: error interrupt
|
||||
\arg CTC_INT_FLAG_EREF: expect reference interrupt
|
||||
\arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt
|
||||
\arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt
|
||||
\arg CTC_INT_FLAG_TRIMERR: trim value error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_interrupt_flag_clear(uint32_t interrupt)
|
||||
{
|
||||
if(RESET != (interrupt & CTC_FLAG_MASK)){
|
||||
CTC_INTC |= CTC_INTC_ERRIC;
|
||||
}else{
|
||||
CTC_INTC |= interrupt;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get CTC flag
|
||||
\param[in] flag: the CTC flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_FLAG_CKOK: clock trim OK flag
|
||||
\arg CTC_FLAG_CKWARN: clock trim warning flag
|
||||
\arg CTC_FLAG_ERR: error flag
|
||||
\arg CTC_FLAG_EREF: expect reference flag
|
||||
\arg CTC_FLAG_CKERR: clock trim error bit
|
||||
\arg CTC_FLAG_REFMISS: reference sync pulse miss
|
||||
\arg CTC_FLAG_TRIMERR: trim value error bit
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus ctc_flag_get(uint32_t flag)
|
||||
{
|
||||
if(RESET != (CTC_STAT & flag)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear CTC flag
|
||||
\param[in] flag: the CTC flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_FLAG_CKOK: clock trim OK flag
|
||||
\arg CTC_FLAG_CKWARN: clock trim warning flag
|
||||
\arg CTC_FLAG_ERR: error flag
|
||||
\arg CTC_FLAG_EREF: expect reference flag
|
||||
\arg CTC_FLAG_CKERR: clock trim error bit
|
||||
\arg CTC_FLAG_REFMISS: reference sync pulse miss
|
||||
\arg CTC_FLAG_TRIMERR: trim value error bit
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_flag_clear(uint32_t flag)
|
||||
{
|
||||
if(RESET != (flag & CTC_FLAG_MASK)){
|
||||
CTC_INTC |= CTC_INTC_ERRIC;
|
||||
}else{
|
||||
CTC_INTC |= flag;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,388 @@
|
||||
/*!
|
||||
\file gd32c10x_ctc.c
|
||||
\brief CTC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_ctc.h"
|
||||
|
||||
#define CTC_FLAG_MASK ((uint32_t)0x00000700U)
|
||||
|
||||
/* CTC register bit offset */
|
||||
#define CTC_TRIMVALUE_OFFSET ((uint32_t)8U)
|
||||
#define CTC_TRIM_VALUE_OFFSET ((uint32_t)8U)
|
||||
#define CTC_REFCAP_OFFSET ((uint32_t)16U)
|
||||
#define CTC_LIMIT_VALUE_OFFSET ((uint32_t)16U)
|
||||
|
||||
/*!
|
||||
\brief reset CTC clock trim controller
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_deinit(void)
|
||||
{
|
||||
/* reset CTC */
|
||||
rcu_periph_reset_enable(RCU_CTCRST);
|
||||
rcu_periph_reset_disable(RCU_CTCRST);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable CTC trim counter
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_counter_enable(void)
|
||||
{
|
||||
CTC_CTL0 |= (uint32_t)CTC_CTL0_CNTEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable CTC trim counter
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_counter_disable(void)
|
||||
{
|
||||
CTC_CTL0 &= (uint32_t)(~CTC_CTL0_CNTEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the IRC48M trim value
|
||||
\param[in] ctc_trim_value: 8-bit IRC48M trim value
|
||||
\arg 0x00 - 0x3F
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_irc48m_trim_value_config(uint8_t trim_value)
|
||||
{
|
||||
/* clear TRIMVALUE bits */
|
||||
CTC_CTL0 &= (~(uint32_t)CTC_CTL0_TRIMVALUE);
|
||||
/* set TRIMVALUE bits */
|
||||
CTC_CTL0 |= ((uint32_t)trim_value << CTC_TRIM_VALUE_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief generate software reference source sync pulse
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_software_refsource_pulse_generate(void)
|
||||
{
|
||||
CTC_CTL0 |= (uint32_t)CTC_CTL0_SWREFPUL;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure hardware automatically trim mode
|
||||
\param[in] hardmode:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_HARDWARE_TRIM_MODE_ENABLE: hardware automatically trim mode enable
|
||||
\arg CTC_HARDWARE_TRIM_MODE_DISABLE: hardware automatically trim mode disable
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_hardware_trim_mode_config(uint32_t hardmode)
|
||||
{
|
||||
CTC_CTL0 &= (uint32_t)(~CTC_CTL0_AUTOTRIM);
|
||||
CTC_CTL0 |= (uint32_t)hardmode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure reference signal source polarity
|
||||
\param[in] polarity:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_REFSOURCE_POLARITY_FALLING: reference signal source polarity is falling edge
|
||||
\arg CTC_REFSOURCE_POLARITY_RISING: reference signal source polarity is rising edge
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_refsource_polarity_config(uint32_t polarity)
|
||||
{
|
||||
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPOL);
|
||||
CTC_CTL1 |= (uint32_t)polarity;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select reference signal source
|
||||
\param[in] refs:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_REFSOURCE_GPIO: GPIO is selected
|
||||
\arg CTC_REFSOURCE_LXTAL: LXTAL is selected
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_refsource_signal_select(uint32_t refs)
|
||||
{
|
||||
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL);
|
||||
CTC_CTL1 |= (uint32_t)refs;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure reference signal source prescaler
|
||||
\param[in] prescaler:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_REFSOURCE_PSC_OFF: reference signal not divided
|
||||
\arg CTC_REFSOURCE_PSC_DIV2: reference signal divided by 2
|
||||
\arg CTC_REFSOURCE_PSC_DIV4: reference signal divided by 4
|
||||
\arg CTC_REFSOURCE_PSC_DIV8: reference signal divided by 8
|
||||
\arg CTC_REFSOURCE_PSC_DIV16: reference signal divided by 16
|
||||
\arg CTC_REFSOURCE_PSC_DIV32: reference signal divided by 32
|
||||
\arg CTC_REFSOURCE_PSC_DIV64: reference signal divided by 64
|
||||
\arg CTC_REFSOURCE_PSC_DIV128: reference signal divided by 128
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_refsource_prescaler_config(uint32_t prescaler)
|
||||
{
|
||||
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPSC);
|
||||
CTC_CTL1 |= (uint32_t)prescaler;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure clock trim base limit value
|
||||
\param[in] limit_value: 8-bit clock trim base limit value
|
||||
\arg 0x00 - 0xFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_clock_limit_value_config(uint8_t limit_value)
|
||||
{
|
||||
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_CKLIM);
|
||||
CTC_CTL1 |= (uint32_t)((uint32_t)limit_value << CTC_LIMIT_VALUE_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure CTC counter reload value
|
||||
\param[in] reload_value: 16-bit CTC counter reload value
|
||||
\arg 0x0000 - 0xFFFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_counter_reload_value_config(uint16_t reload_value)
|
||||
{
|
||||
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_RLVALUE);
|
||||
CTC_CTL1 |= (uint32_t)reload_value;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read CTC counter capture value when reference sync pulse occurred
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the 16-bit CTC counter capture value
|
||||
*/
|
||||
uint16_t ctc_counter_capture_value_read(void)
|
||||
{
|
||||
uint16_t capture_value = 0U;
|
||||
capture_value = (uint16_t)((CTC_STAT & CTC_STAT_REFCAP)>> CTC_REFCAP_OFFSET);
|
||||
return (capture_value);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read CTC trim counter direction when reference sync pulse occurred
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
\arg SET: CTC trim counter direction is down-counting
|
||||
\arg RESET: CTC trim counter direction is up-counting
|
||||
*/
|
||||
FlagStatus ctc_counter_direction_read(void)
|
||||
{
|
||||
if(RESET != (CTC_STAT & CTC_STAT_REFDIR)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read CTC counter reload value
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the 16-bit CTC counter reload value
|
||||
*/
|
||||
uint16_t ctc_counter_reload_value_read(void)
|
||||
{
|
||||
uint16_t reload_value = 0U;
|
||||
reload_value = (uint16_t)(CTC_CTL1 & CTC_CTL1_RLVALUE);
|
||||
return (reload_value);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief read the IRC48M trim value
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval the 8-bit IRC48M trim value
|
||||
*/
|
||||
uint8_t ctc_irc48m_trim_value_read(void)
|
||||
{
|
||||
uint8_t trim_value = 0U;
|
||||
trim_value = (uint8_t)((CTC_CTL0 & CTC_CTL0_TRIMVALUE) >> CTC_TRIMVALUE_OFFSET);
|
||||
return (trim_value);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable the CTC interrupt
|
||||
\param[in] interrupt: CTC interrupt enable
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg CTC_INT_CKOK: clock trim OK interrupt enable
|
||||
\arg CTC_INT_CKWARN: clock trim warning interrupt enable
|
||||
\arg CTC_INT_ERR: error interrupt enable
|
||||
\arg CTC_INT_EREF: expect reference interrupt enable
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_interrupt_enable(uint32_t interrupt)
|
||||
{
|
||||
CTC_CTL0 |= (uint32_t)interrupt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable the CTC interrupt
|
||||
\param[in] interrupt: CTC interrupt enable source
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg CTC_INT_CKOK: clock trim OK interrupt enable
|
||||
\arg CTC_INT_CKWARN: clock trim warning interrupt enable
|
||||
\arg CTC_INT_ERR: error interrupt enable
|
||||
\arg CTC_INT_EREF: expect reference interrupt enable
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_interrupt_disable(uint32_t interrupt)
|
||||
{
|
||||
CTC_CTL0 &= (uint32_t)(~interrupt);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get CTC interrupt flag
|
||||
\param[in] interrupt: the CTC interrupt flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_INT_FLAG_CKOK: clock trim OK interrupt
|
||||
\arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt
|
||||
\arg CTC_INT_FLAG_ERR: error interrupt
|
||||
\arg CTC_INT_FLAG_EREF: expect reference interrupt
|
||||
\arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt
|
||||
\arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt
|
||||
\arg CTC_INT_FLAG_TRIMERR: trim value error interrupt
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus ctc_interrupt_flag_get(uint32_t interrupt)
|
||||
{
|
||||
uint32_t intflag = 0U, intenable = 0U;
|
||||
|
||||
/* check whether the interrupt is enabled */
|
||||
if(RESET != (interrupt & CTC_FLAG_MASK)){
|
||||
intenable = CTC_CTL0 & CTC_CTL0_ERRIE;
|
||||
}else{
|
||||
intenable = CTC_CTL0 & interrupt;
|
||||
}
|
||||
|
||||
/* get interrupt flag status */
|
||||
intflag = CTC_STAT & interrupt;
|
||||
|
||||
if(intflag && intenable){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear CTC interrupt flag
|
||||
\param[in] interrupt: the CTC interrupt flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_INT_FLAG_CKOK: clock trim OK interrupt
|
||||
\arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt
|
||||
\arg CTC_INT_FLAG_ERR: error interrupt
|
||||
\arg CTC_INT_FLAG_EREF: expect reference interrupt
|
||||
\arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt
|
||||
\arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt
|
||||
\arg CTC_INT_FLAG_TRIMERR: trim value error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_interrupt_flag_clear(uint32_t interrupt)
|
||||
{
|
||||
if(RESET != (interrupt & CTC_FLAG_MASK)){
|
||||
CTC_INTC |= CTC_INTC_ERRIC;
|
||||
}else{
|
||||
CTC_INTC |= interrupt;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get CTC flag
|
||||
\param[in] flag: the CTC flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_FLAG_CKOK: clock trim OK flag
|
||||
\arg CTC_FLAG_CKWARN: clock trim warning flag
|
||||
\arg CTC_FLAG_ERR: error flag
|
||||
\arg CTC_FLAG_EREF: expect reference flag
|
||||
\arg CTC_FLAG_CKERR: clock trim error bit
|
||||
\arg CTC_FLAG_REFMISS: reference sync pulse miss
|
||||
\arg CTC_FLAG_TRIMERR: trim value error bit
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus ctc_flag_get(uint32_t flag)
|
||||
{
|
||||
if(RESET != (CTC_STAT & flag)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear CTC flag
|
||||
\param[in] flag: the CTC flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg CTC_FLAG_CKOK: clock trim OK flag
|
||||
\arg CTC_FLAG_CKWARN: clock trim warning flag
|
||||
\arg CTC_FLAG_ERR: error flag
|
||||
\arg CTC_FLAG_EREF: expect reference flag
|
||||
\arg CTC_FLAG_CKERR: clock trim error bit
|
||||
\arg CTC_FLAG_REFMISS: reference sync pulse miss
|
||||
\arg CTC_FLAG_TRIMERR: trim value error bit
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void ctc_flag_clear(uint32_t flag)
|
||||
{
|
||||
if(RESET != (flag & CTC_FLAG_MASK)){
|
||||
CTC_INTC |= CTC_INTC_ERRIC;
|
||||
}else{
|
||||
CTC_INTC |= flag;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,539 @@
|
||||
/*!
|
||||
\file gd32c10x_dac.c
|
||||
\brief DAC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_dac.h"
|
||||
|
||||
/* DAC register bit offset */
|
||||
#define OUT1_REG_OFFSET ((uint32_t)0x00000010U)
|
||||
#define DH_12BIT_OFFSET ((uint32_t)0x00000010U)
|
||||
#define DH_8BIT_OFFSET ((uint32_t)0x00000008U)
|
||||
|
||||
/*!
|
||||
\brief deinitialize DAC
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_deinit(uint32_t dac_periph)
|
||||
{
|
||||
switch(dac_periph){
|
||||
case DAC0:
|
||||
/* reset DAC0 */
|
||||
rcu_periph_reset_enable(RCU_DACRST);
|
||||
rcu_periph_reset_disable(RCU_DACRST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_enable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DEN0;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DEN1;
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DAC
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_disable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DEN0);
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DEN1);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC DMA function
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_dma_enable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DDMAEN0;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DDMAEN1;
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DAC DMA function
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_dma_disable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DDMAEN0);
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DDMAEN1);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC output buffer
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_output_buffer_enable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DBOFF0);
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DBOFF1);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DAC output buffer
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_output_buffer_disable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DBOFF0;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DBOFF1;
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get DAC output value
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval DAC output data: 0~4095
|
||||
*/
|
||||
uint16_t dac_output_value_get(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
uint16_t data = 0U;
|
||||
|
||||
if(DAC_OUT0 == dac_out){
|
||||
/* store the DACx_OUT0 output value */
|
||||
data = (uint16_t)DAC_OUT0_DO(dac_periph);
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
/* store the DACx_OUT1 output value */
|
||||
data = (uint16_t)DAC_OUT1_DO(dac_periph);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set DAC data holding register value
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[in] dac_align: DAC data alignment mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DAC_ALIGN_12B_R: 12-bit right-aligned data
|
||||
\arg DAC_ALIGN_12B_L: 12-bit left-aligned data
|
||||
\arg DAC_ALIGN_8B_R: 8-bit right-aligned data
|
||||
\param[in] data: data to be loaded(0~4095)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_data_set(uint32_t dac_periph, uint8_t dac_out, uint32_t dac_align, uint16_t data)
|
||||
{
|
||||
/* DAC_OUT0 data alignment */
|
||||
if(DAC_OUT0 == dac_out){
|
||||
switch(dac_align){
|
||||
/* 12-bit right-aligned data */
|
||||
case DAC_ALIGN_12B_R:
|
||||
DAC_OUT0_R12DH(dac_periph) = data;
|
||||
break;
|
||||
/* 12-bit left-aligned data */
|
||||
case DAC_ALIGN_12B_L:
|
||||
DAC_OUT0_L12DH(dac_periph) = data;
|
||||
break;
|
||||
/* 8-bit right-aligned data */
|
||||
case DAC_ALIGN_8B_R:
|
||||
DAC_OUT0_R8DH(dac_periph) = data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
/* DAC_OUT1 data alignment */
|
||||
switch(dac_align){
|
||||
/* 12-bit right-aligned data */
|
||||
case DAC_ALIGN_12B_R:
|
||||
DAC_OUT1_R12DH(dac_periph) = data;
|
||||
break;
|
||||
/* 12-bit left-aligned data */
|
||||
case DAC_ALIGN_12B_L:
|
||||
DAC_OUT1_L12DH(dac_periph) = data;
|
||||
break;
|
||||
/* 8-bit right-aligned data */
|
||||
case DAC_ALIGN_8B_R:
|
||||
DAC_OUT1_R8DH(dac_periph) = data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC trigger
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_trigger_enable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DTEN0;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DTEN1;
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DAC trigger
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_trigger_disable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DTEN0);
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DTEN1);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure DAC trigger source
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[in] triggersource: external trigger of DAC
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DAC_TRIGGER_T5_TRGO: TIMER5 TRGO
|
||||
\arg DAC_TRIGGER_T2_TRGO: TIMER2 TRGO
|
||||
\arg DAC_TRIGGER_T6_TRGO: TIMER6 TRGO
|
||||
\arg DAC_TRIGGER_T4_TRGO: TIMER4 TRGO
|
||||
\arg DAC_TRIGGER_T1_TRGO: TIMER1 TRGO
|
||||
\arg DAC_TRIGGER_T3_TRGO: TIMER3 TRGO
|
||||
\arg DAC_TRIGGER_EXTI_9: EXTI interrupt line9 event
|
||||
\arg DAC_TRIGGER_SOFTWARE: software trigger
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_trigger_source_config(uint32_t dac_periph, uint8_t dac_out, uint32_t triggersource)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
/* configure DACx_OUT0 trigger source */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DTSEL0);
|
||||
DAC_CTL0(dac_periph) |= triggersource;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
/* configure DACx_OUT1 trigger source */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DTSEL1);
|
||||
DAC_CTL0(dac_periph) |= (triggersource << OUT1_REG_OFFSET);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC software trigger
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\retval none
|
||||
*/
|
||||
void dac_software_trigger_enable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_SWT(dac_periph) |= (uint32_t)DAC_SWT_SWTR0;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_SWT(dac_periph) |= (uint32_t)DAC_SWT_SWTR1;
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure DAC wave mode
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[in] wave_mode: DAC wave mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DAC_WAVE_DISABLE: wave mode disable
|
||||
\arg DAC_WAVE_MODE_LFSR: LFSR noise mode
|
||||
\arg DAC_WAVE_MODE_TRIANGLE: triangle noise mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_wave_mode_config(uint32_t dac_periph, uint8_t dac_out, uint32_t wave_mode)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
/* configure DACx_OUT0 wave mode */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWM0);
|
||||
DAC_CTL0(dac_periph) |= wave_mode;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
/* configure DACx_OUT1 wave mode */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWM1);
|
||||
DAC_CTL0(dac_periph) |= (wave_mode << OUT1_REG_OFFSET);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure DAC LFSR noise mode
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[in] unmask_bits: LFSR noise unmask bits
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DAC_LFSR_BIT0: unmask the LFSR bit0
|
||||
\arg DAC_LFSR_BITS1_0: unmask the LFSR bits[1:0]
|
||||
\arg DAC_LFSR_BITS2_0: unmask the LFSR bits[2:0]
|
||||
\arg DAC_LFSR_BITS3_0: unmask the LFSR bits[3:0]
|
||||
\arg DAC_LFSR_BITS4_0: unmask the LFSR bits[4:0]
|
||||
\arg DAC_LFSR_BITS5_0: unmask the LFSR bits[5:0]
|
||||
\arg DAC_LFSR_BITS6_0: unmask the LFSR bits[6:0]
|
||||
\arg DAC_LFSR_BITS7_0: unmask the LFSR bits[7:0]
|
||||
\arg DAC_LFSR_BITS8_0: unmask the LFSR bits[8:0]
|
||||
\arg DAC_LFSR_BITS9_0: unmask the LFSR bits[9:0]
|
||||
\arg DAC_LFSR_BITS10_0: unmask the LFSR bits[10:0]
|
||||
\arg DAC_LFSR_BITS11_0: unmask the LFSR bits[11:0]
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_lfsr_noise_config(uint32_t dac_periph, uint8_t dac_out, uint32_t unmask_bits)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
/* configure DACx_OUT0 LFSR noise mode */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWBW0);
|
||||
DAC_CTL0(dac_periph) |= unmask_bits;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
/* configure DACx_OUT1 LFSR noise mode */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWBW1);
|
||||
DAC_CTL0(dac_periph) |= (unmask_bits << OUT1_REG_OFFSET);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure DAC triangle noise mode
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[in] amplitude: the amplitude of the triangle
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_1: triangle amplitude is 1
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_3: triangle amplitude is 3
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_7: triangle amplitude is 7
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_15: triangle amplitude is 15
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_31: triangle amplitude is 31
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_63: triangle amplitude is 63
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_127: triangle amplitude is 127
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_255: triangle amplitude is 255
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_511: triangle amplitude is 511
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_1023: triangle amplitude is 1023
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_2047: triangle amplitude is 2047
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_4095: triangle amplitude is 4095
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_triangle_noise_config(uint32_t dac_periph, uint8_t dac_out, uint32_t amplitude)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
/* configure DACx_OUT0 triangle noise mode */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWBW0);
|
||||
DAC_CTL0(dac_periph) |= amplitude;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
/* configure DACx_OUT1 triangle noise mode */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWBW1);
|
||||
DAC_CTL0(dac_periph) |= (amplitude << OUT1_REG_OFFSET);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC concurrent mode
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_concurrent_enable(uint32_t dac_periph)
|
||||
{
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = (uint32_t)(DAC_CTL0_DEN0 | DAC_CTL0_DEN1);
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DAC concurrent mode
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_concurrent_disable(uint32_t dac_periph)
|
||||
{
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = (uint32_t)(DAC_CTL0_DEN0 | DAC_CTL0_DEN1);
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~ctl);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC concurrent software trigger
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_concurrent_software_trigger_enable(uint32_t dac_periph)
|
||||
{
|
||||
uint32_t swt = 0U;
|
||||
|
||||
swt = (uint32_t)(DAC_SWT_SWTR0 | DAC_SWT_SWTR1);
|
||||
DAC_SWT(dac_periph) |= (uint32_t)swt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC concurrent buffer function
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_concurrent_output_buffer_enable(uint32_t dac_periph)
|
||||
{
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = (uint32_t)(DAC_CTL0_DBOFF0 | DAC_CTL0_DBOFF1);
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~ctl);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DAC concurrent buffer function
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_concurrent_output_buffer_disable(uint32_t dac_periph)
|
||||
{
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = (uint32_t)(DAC_CTL0_DBOFF0 | DAC_CTL0_DBOFF1);
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set DAC concurrent mode data holding register value
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_align: DAC data alignment mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DAC_ALIGN_12B_R: 12-bit right-aligned data
|
||||
\arg DAC_ALIGN_12B_L: 12-bit left-aligned data
|
||||
\arg DAC_ALIGN_8B_R: 8-bit right-aligned data
|
||||
\param[in] data0: data to be loaded (0~4095)
|
||||
\param[in] data1: data to be loaded (0~4095)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_concurrent_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data0, uint16_t data1)
|
||||
{
|
||||
uint32_t data = 0U;
|
||||
|
||||
switch(dac_align){
|
||||
/* 12-bit right-aligned data */
|
||||
case DAC_ALIGN_12B_R:
|
||||
data = (uint32_t)(((uint32_t)data1 << DH_12BIT_OFFSET) | data0);
|
||||
DACC_R12DH(dac_periph) = (uint32_t)data;
|
||||
break;
|
||||
/* 12-bit left-aligned data */
|
||||
case DAC_ALIGN_12B_L:
|
||||
data = (uint32_t)(((uint32_t)data1 << DH_12BIT_OFFSET) | data0);
|
||||
DACC_L12DH(dac_periph) = (uint32_t)data;
|
||||
break;
|
||||
/* 8-bit right-aligned data */
|
||||
case DAC_ALIGN_8B_R:
|
||||
data = (uint32_t)(((uint32_t)data1 << DH_8BIT_OFFSET) | data0);
|
||||
DACC_R8DH(dac_periph) = (uint32_t)data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,539 @@
|
||||
/*!
|
||||
\file gd32c10x_dac.c
|
||||
\brief DAC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_dac.h"
|
||||
|
||||
/* DAC register bit offset */
|
||||
#define OUT1_REG_OFFSET ((uint32_t)0x00000010U)
|
||||
#define DH_12BIT_OFFSET ((uint32_t)0x00000010U)
|
||||
#define DH_8BIT_OFFSET ((uint32_t)0x00000008U)
|
||||
|
||||
/*!
|
||||
\brief deinitialize DAC
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_deinit(uint32_t dac_periph)
|
||||
{
|
||||
switch(dac_periph){
|
||||
case DAC0:
|
||||
/* reset DAC0 */
|
||||
rcu_periph_reset_enable(RCU_DACRST);
|
||||
rcu_periph_reset_disable(RCU_DACRST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_enable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DEN0;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DEN1;
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DAC
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_disable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DEN0);
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DEN1);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC DMA function
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_dma_enable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DDMAEN0;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DDMAEN1;
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DAC DMA function
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_dma_disable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DDMAEN0);
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DDMAEN1);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC output buffer
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_output_buffer_enable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DBOFF0);
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DBOFF1);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DAC output buffer
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_output_buffer_disable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DBOFF0;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DBOFF1;
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get DAC output value
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval DAC output data: 0~4095
|
||||
*/
|
||||
uint16_t dac_output_value_get(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
uint16_t data = 0U;
|
||||
|
||||
if(DAC_OUT0 == dac_out){
|
||||
/* store the DACx_OUT0 output value */
|
||||
data = (uint16_t)DAC_OUT0_DO(dac_periph);
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
/* store the DACx_OUT1 output value */
|
||||
data = (uint16_t)DAC_OUT1_DO(dac_periph);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set DAC data holding register value
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[in] dac_align: DAC data alignment mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DAC_ALIGN_12B_R: 12-bit right-aligned data
|
||||
\arg DAC_ALIGN_12B_L: 12-bit left-aligned data
|
||||
\arg DAC_ALIGN_8B_R: 8-bit right-aligned data
|
||||
\param[in] data: data to be loaded(0~4095)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_data_set(uint32_t dac_periph, uint8_t dac_out, uint32_t dac_align, uint16_t data)
|
||||
{
|
||||
/* DAC_OUT0 data alignment */
|
||||
if(DAC_OUT0 == dac_out){
|
||||
switch(dac_align){
|
||||
/* 12-bit right-aligned data */
|
||||
case DAC_ALIGN_12B_R:
|
||||
DAC_OUT0_R12DH(dac_periph) = data;
|
||||
break;
|
||||
/* 12-bit left-aligned data */
|
||||
case DAC_ALIGN_12B_L:
|
||||
DAC_OUT0_L12DH(dac_periph) = data;
|
||||
break;
|
||||
/* 8-bit right-aligned data */
|
||||
case DAC_ALIGN_8B_R:
|
||||
DAC_OUT0_R8DH(dac_periph) = data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
/* DAC_OUT1 data alignment */
|
||||
switch(dac_align){
|
||||
/* 12-bit right-aligned data */
|
||||
case DAC_ALIGN_12B_R:
|
||||
DAC_OUT1_R12DH(dac_periph) = data;
|
||||
break;
|
||||
/* 12-bit left-aligned data */
|
||||
case DAC_ALIGN_12B_L:
|
||||
DAC_OUT1_L12DH(dac_periph) = data;
|
||||
break;
|
||||
/* 8-bit right-aligned data */
|
||||
case DAC_ALIGN_8B_R:
|
||||
DAC_OUT1_R8DH(dac_periph) = data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC trigger
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_trigger_enable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DTEN0;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)DAC_CTL0_DTEN1;
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DAC trigger
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_trigger_disable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DTEN0);
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DTEN1);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure DAC trigger source
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[in] triggersource: external trigger of DAC
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DAC_TRIGGER_T5_TRGO: TIMER5 TRGO
|
||||
\arg DAC_TRIGGER_T2_TRGO: TIMER2 TRGO
|
||||
\arg DAC_TRIGGER_T6_TRGO: TIMER6 TRGO
|
||||
\arg DAC_TRIGGER_T4_TRGO: TIMER4 TRGO
|
||||
\arg DAC_TRIGGER_T1_TRGO: TIMER1 TRGO
|
||||
\arg DAC_TRIGGER_T3_TRGO: TIMER3 TRGO
|
||||
\arg DAC_TRIGGER_EXTI_9: EXTI interrupt line9 event
|
||||
\arg DAC_TRIGGER_SOFTWARE: software trigger
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_trigger_source_config(uint32_t dac_periph, uint8_t dac_out, uint32_t triggersource)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
/* configure DACx_OUT0 trigger source */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DTSEL0);
|
||||
DAC_CTL0(dac_periph) |= triggersource;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
/* configure DACx_OUT1 trigger source */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DTSEL1);
|
||||
DAC_CTL0(dac_periph) |= (triggersource << OUT1_REG_OFFSET);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC software trigger
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\retval none
|
||||
*/
|
||||
void dac_software_trigger_enable(uint32_t dac_periph, uint8_t dac_out)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
DAC_SWT(dac_periph) |= (uint32_t)DAC_SWT_SWTR0;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
DAC_SWT(dac_periph) |= (uint32_t)DAC_SWT_SWTR1;
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure DAC wave mode
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[in] wave_mode: DAC wave mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DAC_WAVE_DISABLE: wave mode disable
|
||||
\arg DAC_WAVE_MODE_LFSR: LFSR noise mode
|
||||
\arg DAC_WAVE_MODE_TRIANGLE: triangle noise mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_wave_mode_config(uint32_t dac_periph, uint8_t dac_out, uint32_t wave_mode)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
/* configure DACx_OUT0 wave mode */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWM0);
|
||||
DAC_CTL0(dac_periph) |= wave_mode;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
/* configure DACx_OUT1 wave mode */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWM1);
|
||||
DAC_CTL0(dac_periph) |= (wave_mode << OUT1_REG_OFFSET);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure DAC LFSR noise mode
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[in] unmask_bits: LFSR noise unmask bits
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DAC_LFSR_BIT0: unmask the LFSR bit0
|
||||
\arg DAC_LFSR_BITS1_0: unmask the LFSR bits[1:0]
|
||||
\arg DAC_LFSR_BITS2_0: unmask the LFSR bits[2:0]
|
||||
\arg DAC_LFSR_BITS3_0: unmask the LFSR bits[3:0]
|
||||
\arg DAC_LFSR_BITS4_0: unmask the LFSR bits[4:0]
|
||||
\arg DAC_LFSR_BITS5_0: unmask the LFSR bits[5:0]
|
||||
\arg DAC_LFSR_BITS6_0: unmask the LFSR bits[6:0]
|
||||
\arg DAC_LFSR_BITS7_0: unmask the LFSR bits[7:0]
|
||||
\arg DAC_LFSR_BITS8_0: unmask the LFSR bits[8:0]
|
||||
\arg DAC_LFSR_BITS9_0: unmask the LFSR bits[9:0]
|
||||
\arg DAC_LFSR_BITS10_0: unmask the LFSR bits[10:0]
|
||||
\arg DAC_LFSR_BITS11_0: unmask the LFSR bits[11:0]
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_lfsr_noise_config(uint32_t dac_periph, uint8_t dac_out, uint32_t unmask_bits)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
/* configure DACx_OUT0 LFSR noise mode */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWBW0);
|
||||
DAC_CTL0(dac_periph) |= unmask_bits;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
/* configure DACx_OUT1 LFSR noise mode */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWBW1);
|
||||
DAC_CTL0(dac_periph) |= (unmask_bits << OUT1_REG_OFFSET);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure DAC triangle noise mode
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_out: DAC_OUTx(x=0,1)
|
||||
\param[in] amplitude: the amplitude of the triangle
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_1: triangle amplitude is 1
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_3: triangle amplitude is 3
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_7: triangle amplitude is 7
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_15: triangle amplitude is 15
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_31: triangle amplitude is 31
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_63: triangle amplitude is 63
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_127: triangle amplitude is 127
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_255: triangle amplitude is 255
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_511: triangle amplitude is 511
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_1023: triangle amplitude is 1023
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_2047: triangle amplitude is 2047
|
||||
\arg DAC_TRIANGLE_AMPLITUDE_4095: triangle amplitude is 4095
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_triangle_noise_config(uint32_t dac_periph, uint8_t dac_out, uint32_t amplitude)
|
||||
{
|
||||
if(DAC_OUT0 == dac_out){
|
||||
/* configure DACx_OUT0 triangle noise mode */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWBW0);
|
||||
DAC_CTL0(dac_periph) |= amplitude;
|
||||
}else if(DAC_OUT1 == dac_out){
|
||||
/* configure DACx_OUT1 triangle noise mode */
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~DAC_CTL0_DWBW1);
|
||||
DAC_CTL0(dac_periph) |= (amplitude << OUT1_REG_OFFSET);
|
||||
}else{
|
||||
/* illegal parameters */
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC concurrent mode
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_concurrent_enable(uint32_t dac_periph)
|
||||
{
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = (uint32_t)(DAC_CTL0_DEN0 | DAC_CTL0_DEN1);
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DAC concurrent mode
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_concurrent_disable(uint32_t dac_periph)
|
||||
{
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = (uint32_t)(DAC_CTL0_DEN0 | DAC_CTL0_DEN1);
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~ctl);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC concurrent software trigger
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_concurrent_software_trigger_enable(uint32_t dac_periph)
|
||||
{
|
||||
uint32_t swt = 0U;
|
||||
|
||||
swt = (uint32_t)(DAC_SWT_SWTR0 | DAC_SWT_SWTR1);
|
||||
DAC_SWT(dac_periph) |= (uint32_t)swt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DAC concurrent buffer function
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_concurrent_output_buffer_enable(uint32_t dac_periph)
|
||||
{
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = (uint32_t)(DAC_CTL0_DBOFF0 | DAC_CTL0_DBOFF1);
|
||||
DAC_CTL0(dac_periph) &= (uint32_t)(~ctl);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DAC concurrent buffer function
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_concurrent_output_buffer_disable(uint32_t dac_periph)
|
||||
{
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = (uint32_t)(DAC_CTL0_DBOFF0 | DAC_CTL0_DBOFF1);
|
||||
DAC_CTL0(dac_periph) |= (uint32_t)ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set DAC concurrent mode data holding register value
|
||||
\param[in] dac_periph: DACx(x=0)
|
||||
\param[in] dac_align: DAC data alignment mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DAC_ALIGN_12B_R: 12-bit right-aligned data
|
||||
\arg DAC_ALIGN_12B_L: 12-bit left-aligned data
|
||||
\arg DAC_ALIGN_8B_R: 8-bit right-aligned data
|
||||
\param[in] data0: data to be loaded (0~4095)
|
||||
\param[in] data1: data to be loaded (0~4095)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dac_concurrent_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data0, uint16_t data1)
|
||||
{
|
||||
uint32_t data = 0U;
|
||||
|
||||
switch(dac_align){
|
||||
/* 12-bit right-aligned data */
|
||||
case DAC_ALIGN_12B_R:
|
||||
data = (uint32_t)(((uint32_t)data1 << DH_12BIT_OFFSET) | data0);
|
||||
DACC_R12DH(dac_periph) = (uint32_t)data;
|
||||
break;
|
||||
/* 12-bit left-aligned data */
|
||||
case DAC_ALIGN_12B_L:
|
||||
data = (uint32_t)(((uint32_t)data1 << DH_12BIT_OFFSET) | data0);
|
||||
DACC_L12DH(dac_periph) = (uint32_t)data;
|
||||
break;
|
||||
/* 8-bit right-aligned data */
|
||||
case DAC_ALIGN_8B_R:
|
||||
data = (uint32_t)(((uint32_t)data1 << DH_8BIT_OFFSET) | data0);
|
||||
DACC_R8DH(dac_periph) = (uint32_t)data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*!
|
||||
\file gd32c10x_dbg.c
|
||||
\brief DBG driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_dbg.h"
|
||||
|
||||
/*!
|
||||
\brief read DBG_ID code register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval DBG_ID code
|
||||
*/
|
||||
uint32_t dbg_id_get(void)
|
||||
{
|
||||
return DBG_ID;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable low power behavior when the mcu is in debug mode
|
||||
\param[in] dbg_low_power:
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode
|
||||
\arg DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode
|
||||
\arg DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_low_power_enable(uint32_t dbg_low_power)
|
||||
{
|
||||
DBG_CTL |= dbg_low_power;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable low power behavior when the mcu is in debug mode
|
||||
\param[in] dbg_low_power:
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg DBG_LOW_POWER_SLEEP: donot keep debugger connection during sleep mode
|
||||
\arg DBG_LOW_POWER_DEEPSLEEP: donot keep debugger connection during deepsleep mode
|
||||
\arg DBG_LOW_POWER_STANDBY: donot keep debugger connection during standby mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_low_power_disable(uint32_t dbg_low_power)
|
||||
{
|
||||
DBG_CTL &= ~dbg_low_power;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable peripheral behavior when the mcu is in debug mode
|
||||
\param[in] dbg_periph: refer to dbg_periph_enum
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted
|
||||
\arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted
|
||||
\arg DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CANx counter when core is halted
|
||||
\arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted
|
||||
\arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): hold TIMERx counter when core is halted
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_periph_enable(dbg_periph_enum dbg_periph)
|
||||
{
|
||||
DBG_CTL |= (uint32_t)dbg_periph;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable peripheral behavior when the mcu is in debug mode
|
||||
\param[in] dbg_periph: refer to dbg_periph_enum
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted
|
||||
\arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted
|
||||
\arg DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CAN0 counter when core is halted
|
||||
\arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted
|
||||
\arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): hold TIMERx counter when core is halted
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_periph_disable(dbg_periph_enum dbg_periph)
|
||||
{
|
||||
DBG_CTL &= ~(uint32_t)dbg_periph;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable trace pin assignment
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_trace_pin_enable(void)
|
||||
{
|
||||
DBG_CTL |= DBG_CTL_TRACE_IOEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable trace pin assignment
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_trace_pin_disable(void)
|
||||
{
|
||||
DBG_CTL &= ~DBG_CTL_TRACE_IOEN;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*!
|
||||
\file gd32c10x_dbg.c
|
||||
\brief DBG driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_dbg.h"
|
||||
|
||||
/*!
|
||||
\brief read DBG_ID code register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval DBG_ID code
|
||||
*/
|
||||
uint32_t dbg_id_get(void)
|
||||
{
|
||||
return DBG_ID;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable low power behavior when the mcu is in debug mode
|
||||
\param[in] dbg_low_power:
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode
|
||||
\arg DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode
|
||||
\arg DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_low_power_enable(uint32_t dbg_low_power)
|
||||
{
|
||||
DBG_CTL |= dbg_low_power;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable low power behavior when the mcu is in debug mode
|
||||
\param[in] dbg_low_power:
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg DBG_LOW_POWER_SLEEP: donot keep debugger connection during sleep mode
|
||||
\arg DBG_LOW_POWER_DEEPSLEEP: donot keep debugger connection during deepsleep mode
|
||||
\arg DBG_LOW_POWER_STANDBY: donot keep debugger connection during standby mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_low_power_disable(uint32_t dbg_low_power)
|
||||
{
|
||||
DBG_CTL &= ~dbg_low_power;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable peripheral behavior when the mcu is in debug mode
|
||||
\param[in] dbg_periph: refer to dbg_periph_enum
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted
|
||||
\arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted
|
||||
\arg DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CANx counter when core is halted
|
||||
\arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted
|
||||
\arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): hold TIMERx counter when core is halted
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_periph_enable(dbg_periph_enum dbg_periph)
|
||||
{
|
||||
DBG_CTL |= (uint32_t)dbg_periph;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable peripheral behavior when the mcu is in debug mode
|
||||
\param[in] dbg_periph: refer to dbg_periph_enum
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted
|
||||
\arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted
|
||||
\arg DBG_CANx_HOLD (x=0,1,CAN1 is only available for CL series): hold CAN0 counter when core is halted
|
||||
\arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted
|
||||
\arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): hold TIMERx counter when core is halted
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_periph_disable(dbg_periph_enum dbg_periph)
|
||||
{
|
||||
DBG_CTL &= ~(uint32_t)dbg_periph;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable trace pin assignment
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_trace_pin_enable(void)
|
||||
{
|
||||
DBG_CTL |= DBG_CTL_TRACE_IOEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable trace pin assignment
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dbg_trace_pin_disable(void)
|
||||
{
|
||||
DBG_CTL &= ~DBG_CTL_TRACE_IOEN;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,737 @@
|
||||
/*!
|
||||
\file gd32c10x_dma.c
|
||||
\brief DMA driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_dma.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define DMA_WRONG_HANDLE while(1){}
|
||||
|
||||
/* check whether peripheral matches channels or not */
|
||||
static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx);
|
||||
|
||||
/*!
|
||||
\brief deinitialize DMA a channel registers
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel is deinitialized
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* disable the DMA channel */
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
|
||||
/* reset DMA channel registers */
|
||||
DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE;
|
||||
DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE;
|
||||
DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE;
|
||||
DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE;
|
||||
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize the parameters of DMA struct with the default values
|
||||
\param[in] init_struct: the initialization data needed to initialize DMA channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_struct_para_init(dma_parameter_struct* init_struct)
|
||||
{
|
||||
if(NULL == init_struct){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* set the DMA struct with the default values */
|
||||
init_struct->periph_addr = 0U;
|
||||
init_struct->periph_width = 0U;
|
||||
init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE;
|
||||
init_struct->memory_addr = 0U;
|
||||
init_struct->memory_width = 0U;
|
||||
init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE;
|
||||
init_struct->number = 0U;
|
||||
init_struct->direction = DMA_PERIPHERAL_TO_MEMORY;
|
||||
init_struct->priority = DMA_PRIORITY_LOW;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel is initialized
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] init_struct: the data needed to initialize DMA channel
|
||||
periph_addr: peripheral base address
|
||||
periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT
|
||||
periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE
|
||||
memory_addr: memory base address
|
||||
memory_width: DMA_MEMORY_WIDTH_8BIT, DMA_MEMORY_WIDTH_16BIT, DMA_MEMORY_WIDTH_32BIT
|
||||
memory_inc: DMA_MEMORY_INCREASE_ENABLE, DMA_MEMORY_INCREASE_DISABLE
|
||||
direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL
|
||||
number: the number of remaining data to be transferred by the DMA
|
||||
priority: DMA_PRIORITY_LOW, DMA_PRIORITY_MEDIUM, DMA_PRIORITY_HIGH, DMA_PRIORITY_ULTRA_HIGH
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct* init_struct)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* configure peripheral base address */
|
||||
DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr;
|
||||
|
||||
/* configure memory base address */
|
||||
DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr;
|
||||
|
||||
/* configure the number of remaining data to be transferred */
|
||||
DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK);
|
||||
|
||||
/* configure peripheral transfer width,memory transfer width and priority */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO);
|
||||
ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority);
|
||||
DMA_CHCTL(dma_periph, channelx) = ctl;
|
||||
|
||||
/* configure peripheral increasing mode */
|
||||
if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
|
||||
}else{
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
|
||||
}
|
||||
|
||||
/* configure memory increasing mode */
|
||||
if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
|
||||
}else{
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
|
||||
}
|
||||
|
||||
/* configure the direction of data transfer */
|
||||
if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
|
||||
}else{
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DMA circulation mode
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DMA circulation mode
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable memory to memory mode
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable memory to memory mode
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set DMA peripheral base address
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] address: peripheral base address
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHPADDR(dma_periph, channelx) = address;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set DMA memory base address
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] address: memory base address
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHMADDR(dma_periph, channelx) = address;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set the number of remaining data to be transferred by the DMA
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] number: the number of remaining data to be transferred by the DMA
|
||||
\arg 0x0000-0xFFFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the number of remaining data to be transferred by the DMA
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval uint32_t: the number of remaining data to be transferred by the DMA
|
||||
*/
|
||||
uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
return (uint32_t)DMA_CHCNT(dma_periph, channelx);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure priority level of DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] priority: priority level of this channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_PRIORITY_LOW: low priority
|
||||
\arg DMA_PRIORITY_MEDIUM: medium priority
|
||||
\arg DMA_PRIORITY_HIGH: high priority
|
||||
\arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* acquire DMA_CHxCTL register */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
/* assign register */
|
||||
ctl &= ~DMA_CHXCTL_PRIO;
|
||||
ctl |= priority;
|
||||
DMA_CHCTL(dma_periph, channelx) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure transfer data size of memory
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] mwidth: transfer data width of memory
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit
|
||||
\arg DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit
|
||||
\arg DMA_MEMORY_WIDTH_32BIT: transfer data width of memory is 32-bit
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* acquire DMA_CHxCTL register */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
/* assign register */
|
||||
ctl &= ~DMA_CHXCTL_MWIDTH;
|
||||
ctl |= mwidth;
|
||||
DMA_CHCTL(dma_periph, channelx) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure transfer data size of peripheral
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] pwidth: transfer data width of peripheral
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit
|
||||
\arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit
|
||||
\arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data width of peripheral is 32-bit
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* acquire DMA_CHxCTL register */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
/* assign register */
|
||||
ctl &= ~DMA_CHXCTL_PWIDTH;
|
||||
ctl |= pwidth;
|
||||
DMA_CHCTL(dma_periph, channelx) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable next address increment algorithm of memory
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable next address increment algorithm of memory
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable next address increment algorithm of peripheral
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable next address increment algorithm of peripheral
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the direction of data transfer on the channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] direction: specify the direction of data transfer
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory
|
||||
\arg DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t direction)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
if(DMA_PERIPHERAL_TO_MEMORY == direction){
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
|
||||
} else {
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check DMA flag is set or not
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel to get flag
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_FLAG_G: global interrupt flag of channel
|
||||
\arg DMA_FLAG_FTF: full transfer finish flag of channel
|
||||
\arg DMA_FLAG_HTF: half transfer finish flag of channel
|
||||
\arg DMA_FLAG_ERR: error flag of channel
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
FlagStatus reval;
|
||||
|
||||
/* check whether the flag is set or not */
|
||||
if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){
|
||||
reval = SET;
|
||||
}else{
|
||||
reval = RESET;
|
||||
}
|
||||
|
||||
return reval;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear the flag of a DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel to clear flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_FLAG_G: global interrupt flag of channel
|
||||
\arg DMA_FLAG_FTF: full transfer finish flag of channel
|
||||
\arg DMA_FLAG_HTF: half transfer finish flag of channel
|
||||
\arg DMA_FLAG_ERR: error flag of channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check DMA flag and interrupt enable bit is set or not
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel to get flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_ERR: error interrupt flag of channel
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
|
||||
|
||||
switch(flag){
|
||||
case DMA_INT_FLAG_FTF:
|
||||
/* check whether the full transfer finish interrupt flag is set and enabled */
|
||||
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
|
||||
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE;
|
||||
break;
|
||||
case DMA_INT_FLAG_HTF:
|
||||
/* check whether the half transfer finish interrupt flag is set and enabled */
|
||||
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
|
||||
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE;
|
||||
break;
|
||||
case DMA_INT_FLAG_ERR:
|
||||
/* check whether the error interrupt flag is set and enabled */
|
||||
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
|
||||
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE;
|
||||
break;
|
||||
default:
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* when the interrupt flag is set and enabled, return SET */
|
||||
if((0U != interrupt_flag) && (0U != interrupt_enable)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear the interrupt flag of a DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_INT_FLAG_G: global interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_ERR: error interrupt flag of channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DMA interrupt
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] source: specify which interrupt to enable
|
||||
one or more parameters can be selected which are shown as below
|
||||
\arg DMA_INT_FTF: channel full transfer finish interrupt
|
||||
\arg DMA_INT_HTF: channel half transfer finish interrupt
|
||||
\arg DMA_INT_ERR: channel error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= source;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DMA interrupt
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] source: specify which interrupt to disable
|
||||
one or more parameters can be selected which are shown as below
|
||||
\arg DMA_INT_FTF: channel full transfer finish interrupt
|
||||
\arg DMA_INT_HTF: channel half transfer finish interrupt
|
||||
\arg DMA_INT_ERR: channel error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~source;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check whether peripheral matches channels or not
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_CHx(x=0..6)
|
||||
\param[out] none
|
||||
\retval ErrStatus: SUCCESS or ERROR
|
||||
*/
|
||||
static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
ErrStatus val = SUCCESS;
|
||||
|
||||
if(DMA1 == dma_periph){
|
||||
/* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */
|
||||
if(channelx > DMA_CH4){
|
||||
val = ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
@@ -0,0 +1,737 @@
|
||||
/*!
|
||||
\file gd32c10x_dma.c
|
||||
\brief DMA driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_dma.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define DMA_WRONG_HANDLE while(1){}
|
||||
|
||||
/* check whether peripheral matches channels or not */
|
||||
static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx);
|
||||
|
||||
/*!
|
||||
\brief deinitialize DMA a channel registers
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel is deinitialized
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* disable the DMA channel */
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
|
||||
/* reset DMA channel registers */
|
||||
DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE;
|
||||
DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE;
|
||||
DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE;
|
||||
DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE;
|
||||
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize the parameters of DMA struct with the default values
|
||||
\param[in] init_struct: the initialization data needed to initialize DMA channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_struct_para_init(dma_parameter_struct* init_struct)
|
||||
{
|
||||
if(NULL == init_struct){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* set the DMA struct with the default values */
|
||||
init_struct->periph_addr = 0U;
|
||||
init_struct->periph_width = 0U;
|
||||
init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE;
|
||||
init_struct->memory_addr = 0U;
|
||||
init_struct->memory_width = 0U;
|
||||
init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE;
|
||||
init_struct->number = 0U;
|
||||
init_struct->direction = DMA_PERIPHERAL_TO_MEMORY;
|
||||
init_struct->priority = DMA_PRIORITY_LOW;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel is initialized
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] init_struct: the data needed to initialize DMA channel
|
||||
periph_addr: peripheral base address
|
||||
periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT
|
||||
periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE
|
||||
memory_addr: memory base address
|
||||
memory_width: DMA_MEMORY_WIDTH_8BIT, DMA_MEMORY_WIDTH_16BIT, DMA_MEMORY_WIDTH_32BIT
|
||||
memory_inc: DMA_MEMORY_INCREASE_ENABLE, DMA_MEMORY_INCREASE_DISABLE
|
||||
direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL
|
||||
number: the number of remaining data to be transferred by the DMA
|
||||
priority: DMA_PRIORITY_LOW, DMA_PRIORITY_MEDIUM, DMA_PRIORITY_HIGH, DMA_PRIORITY_ULTRA_HIGH
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct* init_struct)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* configure peripheral base address */
|
||||
DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr;
|
||||
|
||||
/* configure memory base address */
|
||||
DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr;
|
||||
|
||||
/* configure the number of remaining data to be transferred */
|
||||
DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK);
|
||||
|
||||
/* configure peripheral transfer width,memory transfer width and priority */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO);
|
||||
ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority);
|
||||
DMA_CHCTL(dma_periph, channelx) = ctl;
|
||||
|
||||
/* configure peripheral increasing mode */
|
||||
if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
|
||||
}else{
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
|
||||
}
|
||||
|
||||
/* configure memory increasing mode */
|
||||
if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
|
||||
}else{
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
|
||||
}
|
||||
|
||||
/* configure the direction of data transfer */
|
||||
if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
|
||||
}else{
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DMA circulation mode
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DMA circulation mode
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable memory to memory mode
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable memory to memory mode
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set DMA peripheral base address
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] address: peripheral base address
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHPADDR(dma_periph, channelx) = address;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set DMA memory base address
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] address: memory base address
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHMADDR(dma_periph, channelx) = address;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set the number of remaining data to be transferred by the DMA
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] number: the number of remaining data to be transferred by the DMA
|
||||
\arg 0x0000-0xFFFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get the number of remaining data to be transferred by the DMA
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval uint32_t: the number of remaining data to be transferred by the DMA
|
||||
*/
|
||||
uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
return (uint32_t)DMA_CHCNT(dma_periph, channelx);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure priority level of DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] priority: priority level of this channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_PRIORITY_LOW: low priority
|
||||
\arg DMA_PRIORITY_MEDIUM: medium priority
|
||||
\arg DMA_PRIORITY_HIGH: high priority
|
||||
\arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* acquire DMA_CHxCTL register */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
/* assign register */
|
||||
ctl &= ~DMA_CHXCTL_PRIO;
|
||||
ctl |= priority;
|
||||
DMA_CHCTL(dma_periph, channelx) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure transfer data size of memory
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] mwidth: transfer data width of memory
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit
|
||||
\arg DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit
|
||||
\arg DMA_MEMORY_WIDTH_32BIT: transfer data width of memory is 32-bit
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* acquire DMA_CHxCTL register */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
/* assign register */
|
||||
ctl &= ~DMA_CHXCTL_MWIDTH;
|
||||
ctl |= mwidth;
|
||||
DMA_CHCTL(dma_periph, channelx) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure transfer data size of peripheral
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] pwidth: transfer data width of peripheral
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit
|
||||
\arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit
|
||||
\arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data width of peripheral is 32-bit
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth)
|
||||
{
|
||||
uint32_t ctl;
|
||||
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* acquire DMA_CHxCTL register */
|
||||
ctl = DMA_CHCTL(dma_periph, channelx);
|
||||
/* assign register */
|
||||
ctl &= ~DMA_CHXCTL_PWIDTH;
|
||||
ctl |= pwidth;
|
||||
DMA_CHCTL(dma_periph, channelx) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable next address increment algorithm of memory
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable next address increment algorithm of memory
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable next address increment algorithm of peripheral
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable next address increment algorithm of peripheral
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the direction of data transfer on the channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] direction: specify the direction of data transfer
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory
|
||||
\arg DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t direction)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
if(DMA_PERIPHERAL_TO_MEMORY == direction){
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR;
|
||||
} else {
|
||||
DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check DMA flag is set or not
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel to get flag
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_FLAG_G: global interrupt flag of channel
|
||||
\arg DMA_FLAG_FTF: full transfer finish flag of channel
|
||||
\arg DMA_FLAG_HTF: half transfer finish flag of channel
|
||||
\arg DMA_FLAG_ERR: error flag of channel
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
FlagStatus reval;
|
||||
|
||||
/* check whether the flag is set or not */
|
||||
if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){
|
||||
reval = SET;
|
||||
}else{
|
||||
reval = RESET;
|
||||
}
|
||||
|
||||
return reval;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear the flag of a DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel to clear flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_FLAG_G: global interrupt flag of channel
|
||||
\arg DMA_FLAG_FTF: full transfer finish flag of channel
|
||||
\arg DMA_FLAG_HTF: half transfer finish flag of channel
|
||||
\arg DMA_FLAG_ERR: error flag of channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check DMA flag and interrupt enable bit is set or not
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel to get flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_ERR: error interrupt flag of channel
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
uint32_t interrupt_enable = 0U, interrupt_flag = 0U;
|
||||
|
||||
switch(flag){
|
||||
case DMA_INT_FLAG_FTF:
|
||||
/* check whether the full transfer finish interrupt flag is set and enabled */
|
||||
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
|
||||
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE;
|
||||
break;
|
||||
case DMA_INT_FLAG_HTF:
|
||||
/* check whether the half transfer finish interrupt flag is set and enabled */
|
||||
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
|
||||
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE;
|
||||
break;
|
||||
case DMA_INT_FLAG_ERR:
|
||||
/* check whether the error interrupt flag is set and enabled */
|
||||
interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx);
|
||||
interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE;
|
||||
break;
|
||||
default:
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
/* when the interrupt flag is set and enabled, return SET */
|
||||
if((0U != interrupt_flag) && (0U != interrupt_enable)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear the interrupt flag of a DMA channel
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] flag: specify get which flag
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_INT_FLAG_G: global interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel
|
||||
\arg DMA_INT_FLAG_ERR: error interrupt flag of channel
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag)
|
||||
{
|
||||
DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable DMA interrupt
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] source: specify which interrupt to enable
|
||||
one or more parameters can be selected which are shown as below
|
||||
\arg DMA_INT_FTF: channel full transfer finish interrupt
|
||||
\arg DMA_INT_HTF: channel half transfer finish interrupt
|
||||
\arg DMA_INT_ERR: channel error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) |= source;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable DMA interrupt
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4)
|
||||
\param[in] source: specify which interrupt to disable
|
||||
one or more parameters can be selected which are shown as below
|
||||
\arg DMA_INT_FTF: channel full transfer finish interrupt
|
||||
\arg DMA_INT_HTF: channel half transfer finish interrupt
|
||||
\arg DMA_INT_ERR: channel error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source)
|
||||
{
|
||||
if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){
|
||||
DMA_WRONG_HANDLE
|
||||
}
|
||||
|
||||
DMA_CHCTL(dma_periph, channelx) &= ~source;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check whether peripheral matches channels or not
|
||||
\param[in] dma_periph: DMAx(x=0,1)
|
||||
\arg DMAx(x=0,1)
|
||||
\param[in] channelx: specified DMA channel
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg DMA_CHx(x=0..6)
|
||||
\param[out] none
|
||||
\retval ErrStatus: SUCCESS or ERROR
|
||||
*/
|
||||
static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx)
|
||||
{
|
||||
ErrStatus val = SUCCESS;
|
||||
|
||||
if(DMA1 == dma_periph){
|
||||
/* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */
|
||||
if(channelx > DMA_CH4){
|
||||
val = ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
/*!
|
||||
\file gd32c10x_eval.c
|
||||
\brief firmware functions to manage leds, keys, COM ports
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_eval.h"
|
||||
|
||||
/* private variables */
|
||||
static uint32_t GPIO_PORT[LED_MAX] = {LED1_GPIO_PORT, LED2_GPIO_PORT,
|
||||
LED3_GPIO_PORT, LED4_GPIO_PORT};
|
||||
static uint32_t GPIO_PIN[LED_MAX] = {LED1_PIN, LED2_PIN, LED3_PIN, LED4_PIN};
|
||||
|
||||
static rcu_periph_enum COM_CLK[COMn] = {EVAL_COM0_CLK, EVAL_COM1_CLK};
|
||||
static uint32_t COM_TX_PIN[COMn] = {EVAL_COM0_TX_PIN, EVAL_COM1_TX_PIN};
|
||||
static uint32_t COM_RX_PIN[COMn] = {EVAL_COM0_RX_PIN, EVAL_COM1_RX_PIN};
|
||||
static uint32_t COM_GPIO_PORT[COMn] = {EVAL_COM0_GPIO_PORT, EVAL_COM1_GPIO_PORT};
|
||||
static rcu_periph_enum COM_GPIO_CLK[COMn] = {EVAL_COM0_GPIO_CLK, EVAL_COM1_GPIO_CLK};
|
||||
|
||||
static rcu_periph_enum GPIO_CLK[LED_MAX] = {LED1_GPIO_CLK, LED2_GPIO_CLK,
|
||||
LED3_GPIO_CLK, LED4_GPIO_CLK};
|
||||
|
||||
static uint32_t KEY_PORT[KEY_MAX] = {WAKEUP_KEY_GPIO_PORT,
|
||||
TAMPER_KEY_GPIO_PORT,
|
||||
USER_KEY_GPIO_PORT};
|
||||
static uint32_t KEY_PIN[KEY_MAX] = {WAKEUP_KEY_PIN, TAMPER_KEY_PIN,USER_KEY_PIN,};
|
||||
static rcu_periph_enum KEY_CLK[KEY_MAX] = {WAKEUP_KEY_GPIO_CLK,
|
||||
TAMPER_KEY_GPIO_CLK,
|
||||
USER_KEY_GPIO_CLK};
|
||||
static exti_line_enum KEY_EXTI_LINE[KEY_MAX] = {WAKEUP_KEY_EXTI_LINE,
|
||||
TAMPER_KEY_EXTI_LINE,
|
||||
USER_KEY_EXTI_LINE};
|
||||
static uint8_t KEY_PORT_SOURCE[KEY_MAX] = {WAKEUP_KEY_EXTI_PORT_SOURCE,
|
||||
TAMPER_KEY_EXTI_PORT_SOURCE,
|
||||
USER_KEY_EXTI_PORT_SOURCE};
|
||||
static uint8_t KEY_PIN_SOURCE[KEY_MAX] = {WAKEUP_KEY_EXTI_PIN_SOURCE,
|
||||
TAMPER_KEY_EXTI_PIN_SOURCE,
|
||||
USER_KEY_EXTI_PIN_SOURCE};
|
||||
static IRQn_Type KEY_IRQn[KEY_MAX] = {WAKEUP_KEY_EXTI_IRQn,
|
||||
TAMPER_KEY_EXTI_IRQn,
|
||||
USER_KEY_EXTI_IRQn};
|
||||
|
||||
/*!
|
||||
\brief configure led GPIO
|
||||
\param[in] lednum: specify the led to be configured
|
||||
\arg LED1
|
||||
\arg LED2
|
||||
\arg LED3
|
||||
\arg LED4
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gd_eval_led_init (led_typedef_enum lednum)
|
||||
{
|
||||
/* enable the led clock */
|
||||
rcu_periph_clock_enable(GPIO_CLK[lednum]);
|
||||
/* configure led GPIO port */
|
||||
gpio_init(GPIO_PORT[lednum], GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN[lednum]);
|
||||
|
||||
GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum];
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief turn on selected led
|
||||
\param[in] lednum: specify the led to be turned on
|
||||
\arg LED1
|
||||
\arg LED2
|
||||
\arg LED3
|
||||
\arg LED4
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gd_eval_led_on(led_typedef_enum lednum)
|
||||
{
|
||||
GPIO_BOP(GPIO_PORT[lednum]) = GPIO_PIN[lednum];
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief turn off selected led
|
||||
\param[in] lednum: specify the led to be turned off
|
||||
\arg LED1
|
||||
\arg LED2
|
||||
\arg LED3
|
||||
\arg LED4
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gd_eval_led_off(led_typedef_enum lednum)
|
||||
{
|
||||
GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum];
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief toggle selected led
|
||||
\param[in] lednum: specify the led to be toggled
|
||||
\arg LED1
|
||||
\arg LED2
|
||||
\arg LED3
|
||||
\arg LED4
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gd_eval_led_toggle(led_typedef_enum lednum)
|
||||
{
|
||||
gpio_bit_write(GPIO_PORT[lednum], GPIO_PIN[lednum],
|
||||
(bit_status)(1-gpio_input_bit_get(GPIO_PORT[lednum], GPIO_PIN[lednum])));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure key
|
||||
\param[in] key_num: specify the key to be configured
|
||||
\arg KEY_TAMPER: tamper key
|
||||
\arg KEY_WAKEUP: wakeup key
|
||||
\arg KEY_USER: user key
|
||||
\param[in] key_mode: specify button mode
|
||||
\arg KEY_MODE_GPIO: key will be used as simple IO
|
||||
\arg KEY_MODE_EXTI: key will be connected to EXTI line with interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gd_eval_key_init(key_typedef_enum key_num, keymode_typedef_enum key_mode)
|
||||
{
|
||||
/* enable the key clock */
|
||||
rcu_periph_clock_enable(KEY_CLK[key_num]);
|
||||
rcu_periph_clock_enable(RCU_AF);
|
||||
|
||||
/* configure button pin as input */
|
||||
gpio_init(KEY_PORT[key_num], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, KEY_PIN[key_num]);
|
||||
|
||||
if (key_mode == KEY_MODE_EXTI) {
|
||||
/* enable and set key EXTI interrupt to the lowest priority */
|
||||
nvic_irq_enable(KEY_IRQn[key_num], 2U, 0U);
|
||||
|
||||
/* connect key EXTI line to key GPIO pin */
|
||||
gpio_exti_source_select(KEY_PORT_SOURCE[key_num], KEY_PIN_SOURCE[key_num]);
|
||||
|
||||
/* configure key EXTI line */
|
||||
exti_init(KEY_EXTI_LINE[key_num], EXTI_INTERRUPT, EXTI_TRIG_FALLING);
|
||||
exti_interrupt_flag_clear(KEY_EXTI_LINE[key_num]);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief return the selected key state
|
||||
\param[in] key: specify the key to be checked
|
||||
\arg KEY_TAMPER: tamper key
|
||||
\arg KEY_WAKEUP: wakeup key
|
||||
\arg KEY_USER: user key
|
||||
\param[out] none
|
||||
\retval the key's GPIO pin value
|
||||
*/
|
||||
uint8_t gd_eval_key_state_get(key_typedef_enum key)
|
||||
{
|
||||
return gpio_input_bit_get(KEY_PORT[key], KEY_PIN[key]);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure COM port
|
||||
\param[in] com: COM on the board
|
||||
\arg EVAL_COM0: COM0 on the board
|
||||
\arg EVAL_COM1: COM1 on the board
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gd_eval_com_init(uint32_t com)
|
||||
{
|
||||
uint32_t com_id = 0U;
|
||||
if(EVAL_COM0 == com){
|
||||
com_id = 0U;
|
||||
}else if(EVAL_COM1 == com){
|
||||
com_id = 1U;
|
||||
}else{
|
||||
com_id = 2U;
|
||||
}
|
||||
|
||||
/* enable GPIO clock */
|
||||
rcu_periph_clock_enable(COM_GPIO_CLK[com_id]);
|
||||
|
||||
/* enable USART clock */
|
||||
rcu_periph_clock_enable(COM_CLK[com_id]);
|
||||
|
||||
/* connect port to USARTx_Tx */
|
||||
gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, COM_TX_PIN[com_id]);
|
||||
|
||||
/* connect port to USARTx_Rx */
|
||||
gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, COM_RX_PIN[com_id]);
|
||||
|
||||
/* USART configure */
|
||||
usart_deinit(com);
|
||||
usart_baudrate_set(com, 3000000U);
|
||||
usart_receive_config(com, USART_RECEIVE_ENABLE);
|
||||
usart_transmit_config(com, USART_TRANSMIT_ENABLE);
|
||||
usart_enable(com);
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
/*!
|
||||
\file gd32c10x_eval.c
|
||||
\brief firmware functions to manage leds, keys, COM ports
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_eval.h"
|
||||
|
||||
/* private variables */
|
||||
static uint32_t GPIO_PORT[LED_MAX] = {LED1_GPIO_PORT, LED2_GPIO_PORT,
|
||||
LED3_GPIO_PORT, LED4_GPIO_PORT};
|
||||
static uint32_t GPIO_PIN[LED_MAX] = {LED1_PIN, LED2_PIN, LED3_PIN, LED4_PIN};
|
||||
|
||||
static rcu_periph_enum COM_CLK[COMn] = {EVAL_COM0_CLK, EVAL_COM1_CLK};
|
||||
static uint32_t COM_TX_PIN[COMn] = {EVAL_COM0_TX_PIN, EVAL_COM1_TX_PIN};
|
||||
static uint32_t COM_RX_PIN[COMn] = {EVAL_COM0_RX_PIN, EVAL_COM1_RX_PIN};
|
||||
static uint32_t COM_GPIO_PORT[COMn] = {EVAL_COM0_GPIO_PORT, EVAL_COM1_GPIO_PORT};
|
||||
static rcu_periph_enum COM_GPIO_CLK[COMn] = {EVAL_COM0_GPIO_CLK, EVAL_COM1_GPIO_CLK};
|
||||
|
||||
static rcu_periph_enum GPIO_CLK[LED_MAX] = {LED1_GPIO_CLK, LED2_GPIO_CLK,
|
||||
LED3_GPIO_CLK, LED4_GPIO_CLK};
|
||||
|
||||
static uint32_t KEY_PORT[KEY_MAX] = {WAKEUP_KEY_GPIO_PORT,
|
||||
TAMPER_KEY_GPIO_PORT,
|
||||
USER_KEY_GPIO_PORT};
|
||||
static uint32_t KEY_PIN[KEY_MAX] = {WAKEUP_KEY_PIN, TAMPER_KEY_PIN,USER_KEY_PIN,};
|
||||
static rcu_periph_enum KEY_CLK[KEY_MAX] = {WAKEUP_KEY_GPIO_CLK,
|
||||
TAMPER_KEY_GPIO_CLK,
|
||||
USER_KEY_GPIO_CLK};
|
||||
static exti_line_enum KEY_EXTI_LINE[KEY_MAX] = {WAKEUP_KEY_EXTI_LINE,
|
||||
TAMPER_KEY_EXTI_LINE,
|
||||
USER_KEY_EXTI_LINE};
|
||||
static uint8_t KEY_PORT_SOURCE[KEY_MAX] = {WAKEUP_KEY_EXTI_PORT_SOURCE,
|
||||
TAMPER_KEY_EXTI_PORT_SOURCE,
|
||||
USER_KEY_EXTI_PORT_SOURCE};
|
||||
static uint8_t KEY_PIN_SOURCE[KEY_MAX] = {WAKEUP_KEY_EXTI_PIN_SOURCE,
|
||||
TAMPER_KEY_EXTI_PIN_SOURCE,
|
||||
USER_KEY_EXTI_PIN_SOURCE};
|
||||
static IRQn_Type KEY_IRQn[KEY_MAX] = {WAKEUP_KEY_EXTI_IRQn,
|
||||
TAMPER_KEY_EXTI_IRQn,
|
||||
USER_KEY_EXTI_IRQn};
|
||||
|
||||
/*!
|
||||
\brief configure led GPIO
|
||||
\param[in] lednum: specify the led to be configured
|
||||
\arg LED1
|
||||
\arg LED2
|
||||
\arg LED3
|
||||
\arg LED4
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gd_eval_led_init (led_typedef_enum lednum)
|
||||
{
|
||||
/* enable the led clock */
|
||||
rcu_periph_clock_enable(GPIO_CLK[lednum]);
|
||||
/* configure led GPIO port */
|
||||
gpio_init(GPIO_PORT[lednum], GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN[lednum]);
|
||||
|
||||
GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum];
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief turn on selected led
|
||||
\param[in] lednum: specify the led to be turned on
|
||||
\arg LED1
|
||||
\arg LED2
|
||||
\arg LED3
|
||||
\arg LED4
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gd_eval_led_on(led_typedef_enum lednum)
|
||||
{
|
||||
GPIO_BOP(GPIO_PORT[lednum]) = GPIO_PIN[lednum];
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief turn off selected led
|
||||
\param[in] lednum: specify the led to be turned off
|
||||
\arg LED1
|
||||
\arg LED2
|
||||
\arg LED3
|
||||
\arg LED4
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gd_eval_led_off(led_typedef_enum lednum)
|
||||
{
|
||||
GPIO_BC(GPIO_PORT[lednum]) = GPIO_PIN[lednum];
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief toggle selected led
|
||||
\param[in] lednum: specify the led to be toggled
|
||||
\arg LED1
|
||||
\arg LED2
|
||||
\arg LED3
|
||||
\arg LED4
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gd_eval_led_toggle(led_typedef_enum lednum)
|
||||
{
|
||||
gpio_bit_write(GPIO_PORT[lednum], GPIO_PIN[lednum],
|
||||
(bit_status)(1-gpio_input_bit_get(GPIO_PORT[lednum], GPIO_PIN[lednum])));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure key
|
||||
\param[in] key_num: specify the key to be configured
|
||||
\arg KEY_TAMPER: tamper key
|
||||
\arg KEY_WAKEUP: wakeup key
|
||||
\arg KEY_USER: user key
|
||||
\param[in] key_mode: specify button mode
|
||||
\arg KEY_MODE_GPIO: key will be used as simple IO
|
||||
\arg KEY_MODE_EXTI: key will be connected to EXTI line with interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gd_eval_key_init(key_typedef_enum key_num, keymode_typedef_enum key_mode)
|
||||
{
|
||||
/* enable the key clock */
|
||||
rcu_periph_clock_enable(KEY_CLK[key_num]);
|
||||
rcu_periph_clock_enable(RCU_AF);
|
||||
|
||||
/* configure button pin as input */
|
||||
gpio_init(KEY_PORT[key_num], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, KEY_PIN[key_num]);
|
||||
|
||||
if (key_mode == KEY_MODE_EXTI) {
|
||||
/* enable and set key EXTI interrupt to the lowest priority */
|
||||
nvic_irq_enable(KEY_IRQn[key_num], 2U, 0U);
|
||||
|
||||
/* connect key EXTI line to key GPIO pin */
|
||||
gpio_exti_source_select(KEY_PORT_SOURCE[key_num], KEY_PIN_SOURCE[key_num]);
|
||||
|
||||
/* configure key EXTI line */
|
||||
exti_init(KEY_EXTI_LINE[key_num], EXTI_INTERRUPT, EXTI_TRIG_FALLING);
|
||||
exti_interrupt_flag_clear(KEY_EXTI_LINE[key_num]);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief return the selected key state
|
||||
\param[in] key: specify the key to be checked
|
||||
\arg KEY_TAMPER: tamper key
|
||||
\arg KEY_WAKEUP: wakeup key
|
||||
\arg KEY_USER: user key
|
||||
\param[out] none
|
||||
\retval the key's GPIO pin value
|
||||
*/
|
||||
uint8_t gd_eval_key_state_get(key_typedef_enum key)
|
||||
{
|
||||
return gpio_input_bit_get(KEY_PORT[key], KEY_PIN[key]);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure COM port
|
||||
\param[in] com: COM on the board
|
||||
\arg EVAL_COM0: COM0 on the board
|
||||
\arg EVAL_COM1: COM1 on the board
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gd_eval_com_init(uint32_t com)
|
||||
{
|
||||
uint32_t com_id = 0U;
|
||||
if(EVAL_COM0 == com){
|
||||
com_id = 0U;
|
||||
}else if(EVAL_COM1 == com){
|
||||
com_id = 1U;
|
||||
}else{
|
||||
com_id = 2U;
|
||||
}
|
||||
|
||||
/* enable GPIO clock */
|
||||
rcu_periph_clock_enable(COM_GPIO_CLK[com_id]);
|
||||
|
||||
/* enable USART clock */
|
||||
rcu_periph_clock_enable(COM_CLK[com_id]);
|
||||
|
||||
/* connect port to USARTx_Tx */
|
||||
gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, COM_TX_PIN[com_id]);
|
||||
|
||||
/* connect port to USARTx_Rx */
|
||||
gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, COM_RX_PIN[com_id]);
|
||||
|
||||
/* USART configure */
|
||||
usart_deinit(com);
|
||||
usart_baudrate_set(com, 115200U);
|
||||
usart_receive_config(com, USART_RECEIVE_ENABLE);
|
||||
usart_transmit_config(com, USART_TRANSMIT_ENABLE);
|
||||
usart_enable(com);
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/*!
|
||||
\file gd32c10x_exmc.c
|
||||
\brief EXMC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_exmc.h"
|
||||
|
||||
/* EXMC bank0 register reset value */
|
||||
#define BANK0_SNCTL_RESET ((uint32_t)0x000030DBU)
|
||||
#define BANK0_SNTCFG_RESET ((uint32_t)0x0FFFFFFFU)
|
||||
#define BANK0_SNWTCFG_RESET ((uint32_t)0x0FFFFFFFU)
|
||||
|
||||
/* EXMC register bit offset */
|
||||
#define SNCTL_NRMUX_OFFSET ((uint32_t)1U)
|
||||
#define SNCTL_SBRSTEN_OFFSET ((uint32_t)8U)
|
||||
#define SNCTL_WRAPEN_OFFSET ((uint32_t)10U)
|
||||
#define SNCTL_WREN_OFFSET ((uint32_t)12U)
|
||||
#define SNCTL_NRWTEN_OFFSET ((uint32_t)13U)
|
||||
#define SNCTL_EXMODEN_OFFSET ((uint32_t)14U)
|
||||
#define SNCTL_ASYNCWAIT_OFFSET ((uint32_t)15U)
|
||||
|
||||
#define SNTCFG_AHLD_OFFSET ((uint32_t)4U)
|
||||
#define SNTCFG_DSET_OFFSET ((uint32_t)8U)
|
||||
#define SNTCFG_BUSLAT_OFFSET ((uint32_t)16U)
|
||||
|
||||
#define SNWTCFG_WAHLD_OFFSET ((uint32_t)4U)
|
||||
#define SNWTCFG_WDSET_OFFSET ((uint32_t)8U)
|
||||
#define SNWTCFG_WBUSLAT_OFFSET ((uint32_t)16U)
|
||||
|
||||
/*!
|
||||
\brief deinitialize EXMC NOR/SRAM bank
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exmc_norsram_deinit(void)
|
||||
{
|
||||
/* reset the registers */
|
||||
EXMC_SNCTL = BANK0_SNCTL_RESET;
|
||||
|
||||
EXMC_SNTCFG = BANK0_SNTCFG_RESET;
|
||||
EXMC_SNWTCFG = BANK0_SNWTCFG_RESET;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize the struct exmc_norsram_parameter_struct
|
||||
\param[in] none
|
||||
\param[out] exmc_norsram_init_struct: the initialized struct exmc_norsram_parameter_struct pointer
|
||||
\retval none
|
||||
*/
|
||||
void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
|
||||
{
|
||||
/* configure the structure with default value */
|
||||
exmc_norsram_init_struct->address_data_mux = ENABLE;
|
||||
exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_NOR;
|
||||
exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
|
||||
exmc_norsram_init_struct->burst_mode = DISABLE;
|
||||
exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
|
||||
exmc_norsram_init_struct->wrap_burst_mode = DISABLE;
|
||||
exmc_norsram_init_struct->nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
|
||||
exmc_norsram_init_struct->memory_write = ENABLE;
|
||||
exmc_norsram_init_struct->nwait_signal = ENABLE;
|
||||
exmc_norsram_init_struct->extended_mode = DISABLE;
|
||||
exmc_norsram_init_struct->asyn_wait = DISABLE;
|
||||
exmc_norsram_init_struct->write_mode = EXMC_ASYN_WRITE;
|
||||
|
||||
/* read/write timing configure */
|
||||
exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU;
|
||||
exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU;
|
||||
exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU;
|
||||
exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU;
|
||||
exmc_norsram_init_struct->read_write_timing->syn_clk_division = EXMC_SYN_CLOCK_RATIO_16_CLK;
|
||||
exmc_norsram_init_struct->read_write_timing->syn_data_latency = EXMC_DATALAT_17_CLK;
|
||||
exmc_norsram_init_struct->read_write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A;
|
||||
|
||||
/* write timing configure, when extended mode is used */
|
||||
exmc_norsram_init_struct->write_timing->asyn_address_setuptime = 0xFU;
|
||||
exmc_norsram_init_struct->write_timing->asyn_address_holdtime = 0xFU;
|
||||
exmc_norsram_init_struct->write_timing->asyn_data_setuptime = 0xFFU;
|
||||
exmc_norsram_init_struct->write_timing->bus_latency = 0xFU;
|
||||
exmc_norsram_init_struct->write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize EXMC NOR/SRAM bank
|
||||
\param[in] exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter
|
||||
write_mode: EXMC_ASYN_WRITE,EXMC_SYN_WRITE
|
||||
extended_mode: ENABLE or DISABLE
|
||||
asyn_wait: ENABLE or DISABLE
|
||||
nwait_signal: ENABLE or DISABLE
|
||||
memory_write: ENABLE or DISABLE
|
||||
nwait_config: EXMC_NWAIT_CONFIG_BEFORE,EXMC_NWAIT_CONFIG_DURING
|
||||
wrap_burst_mode: ENABLE or DISABLE
|
||||
nwait_polarity: EXMC_NWAIT_POLARITY_LOW,EXMC_NWAIT_POLARITY_HIGH
|
||||
burst_mode: ENABLE or DISABLE
|
||||
databus_width: EXMC_NOR_DATABUS_WIDTH_8B,EXMC_NOR_DATABUS_WIDTH_16B
|
||||
memory_type: EXMC_MEMORY_TYPE_SRAM,EXMC_MEMORY_TYPE_PSRAM,EXMC_MEMORY_TYPE_NOR
|
||||
address_data_mux: ENABLE or DISABLE
|
||||
read_write_timing: struct exmc_norsram_timing_parameter_struct set the time
|
||||
write_timing: struct exmc_norsram_timing_parameter_struct set the time
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
|
||||
{
|
||||
uint32_t snctl = 0x00000000U, sntcfg = 0x00000000U, snwtcfg = 0x00000000U;
|
||||
|
||||
/* get the register value */
|
||||
snctl = EXMC_SNCTL;
|
||||
|
||||
/* clear relative bits */
|
||||
snctl &= ((uint32_t)~(EXMC_SNCTL_NRMUX | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN |
|
||||
EXMC_SNCTL_NREN | EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG |
|
||||
EXMC_SNCTL_WREN | EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT |
|
||||
EXMC_SNCTL_SYNCWR ));
|
||||
|
||||
snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) |
|
||||
exmc_norsram_init_struct->memory_type |
|
||||
exmc_norsram_init_struct->databus_width |
|
||||
(exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) |
|
||||
exmc_norsram_init_struct->nwait_polarity |
|
||||
(exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) |
|
||||
exmc_norsram_init_struct->nwait_config |
|
||||
(exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) |
|
||||
(exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) |
|
||||
(exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) |
|
||||
(exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) |
|
||||
exmc_norsram_init_struct->write_mode;
|
||||
|
||||
sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U ) & EXMC_SNTCFG_ASET )|
|
||||
(((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U ) << SNTCFG_AHLD_OFFSET ) & EXMC_SNTCFG_AHLD ) |
|
||||
(((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U ) << SNTCFG_DSET_OFFSET ) & EXMC_SNTCFG_DSET ) |
|
||||
(((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U ) << SNTCFG_BUSLAT_OFFSET ) & EXMC_SNTCFG_BUSLAT )|
|
||||
exmc_norsram_init_struct->read_write_timing->syn_clk_division |
|
||||
exmc_norsram_init_struct->read_write_timing->syn_data_latency |
|
||||
exmc_norsram_init_struct->read_write_timing->asyn_access_mode;
|
||||
|
||||
/* nor flash access enable */
|
||||
if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){
|
||||
snctl |= (uint32_t)EXMC_SNCTL_NREN;
|
||||
}
|
||||
|
||||
/* extended mode configure */
|
||||
if(ENABLE == exmc_norsram_init_struct->extended_mode){
|
||||
snwtcfg = (uint32_t)((exmc_norsram_init_struct->write_timing->asyn_address_setuptime - 1U) & EXMC_SNWTCFG_WASET ) |
|
||||
(((exmc_norsram_init_struct->write_timing->asyn_address_holdtime -1U ) << SNWTCFG_WAHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD )|
|
||||
(((exmc_norsram_init_struct->write_timing->asyn_data_setuptime -1U ) << SNWTCFG_WDSET_OFFSET ) & EXMC_SNWTCFG_WDSET )|
|
||||
(((exmc_norsram_init_struct->write_timing->bus_latency - 1U ) << SNWTCFG_WBUSLAT_OFFSET ) & EXMC_SNWTCFG_WBUSLAT ) |
|
||||
exmc_norsram_init_struct->write_timing->asyn_access_mode;
|
||||
}else{
|
||||
snwtcfg = BANK0_SNWTCFG_RESET;
|
||||
}
|
||||
|
||||
/* configure the registers */
|
||||
EXMC_SNCTL = snctl;
|
||||
EXMC_SNTCFG = sntcfg;
|
||||
EXMC_SNWTCFG = snwtcfg;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable EXMC NOR/PSRAM bank
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exmc_norsram_enable(void)
|
||||
{
|
||||
EXMC_SNCTL |= (uint32_t)EXMC_SNCTL_NRBKEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable EXMC NOR/PSRAM bank
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exmc_norsram_disable(void)
|
||||
{
|
||||
EXMC_SNCTL &= ~(uint32_t)EXMC_SNCTL_NRBKEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure CRAM page size
|
||||
\param[in] page_size: CRAM page size
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXMC_CRAM_AUTO_SPLIT: the clock is generated only during synchronous access
|
||||
\arg EXMC_CRAM_PAGE_SIZE_128_BYTES: page size is 128 bytes
|
||||
\arg EXMC_CRAM_PAGE_SIZE_256_BYTES: page size is 256 bytes
|
||||
\arg EXMC_CRAM_PAGE_SIZE_512_BYTES: page size is 512 bytes
|
||||
\arg EXMC_CRAM_PAGE_SIZE_1024_BYTES: page size is 1024 bytes
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exmc_norsram_page_size_config(uint32_t page_size)
|
||||
{
|
||||
/* reset the bits */
|
||||
EXMC_SNCTL &= ~EXMC_SNCTL_CPS;
|
||||
/* set the CPS bits */
|
||||
EXMC_SNCTL |= page_size;
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/*!
|
||||
\file gd32c10x_exmc.c
|
||||
\brief EXMC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_exmc.h"
|
||||
|
||||
/* EXMC bank0 register reset value */
|
||||
#define BANK0_SNCTL_RESET ((uint32_t)0x000030DBU)
|
||||
#define BANK0_SNTCFG_RESET ((uint32_t)0x0FFFFFFFU)
|
||||
#define BANK0_SNWTCFG_RESET ((uint32_t)0x0FFFFFFFU)
|
||||
|
||||
/* EXMC register bit offset */
|
||||
#define SNCTL_NRMUX_OFFSET ((uint32_t)1U)
|
||||
#define SNCTL_SBRSTEN_OFFSET ((uint32_t)8U)
|
||||
#define SNCTL_WRAPEN_OFFSET ((uint32_t)10U)
|
||||
#define SNCTL_WREN_OFFSET ((uint32_t)12U)
|
||||
#define SNCTL_NRWTEN_OFFSET ((uint32_t)13U)
|
||||
#define SNCTL_EXMODEN_OFFSET ((uint32_t)14U)
|
||||
#define SNCTL_ASYNCWAIT_OFFSET ((uint32_t)15U)
|
||||
|
||||
#define SNTCFG_AHLD_OFFSET ((uint32_t)4U)
|
||||
#define SNTCFG_DSET_OFFSET ((uint32_t)8U)
|
||||
#define SNTCFG_BUSLAT_OFFSET ((uint32_t)16U)
|
||||
|
||||
#define SNWTCFG_WAHLD_OFFSET ((uint32_t)4U)
|
||||
#define SNWTCFG_WDSET_OFFSET ((uint32_t)8U)
|
||||
#define SNWTCFG_WBUSLAT_OFFSET ((uint32_t)16U)
|
||||
|
||||
/*!
|
||||
\brief deinitialize EXMC NOR/SRAM bank
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exmc_norsram_deinit(void)
|
||||
{
|
||||
/* reset the registers */
|
||||
EXMC_SNCTL = BANK0_SNCTL_RESET;
|
||||
|
||||
EXMC_SNTCFG = BANK0_SNTCFG_RESET;
|
||||
EXMC_SNWTCFG = BANK0_SNWTCFG_RESET;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize the struct exmc_norsram_parameter_struct
|
||||
\param[in] none
|
||||
\param[out] exmc_norsram_init_struct: the initialized struct exmc_norsram_parameter_struct pointer
|
||||
\retval none
|
||||
*/
|
||||
void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
|
||||
{
|
||||
/* configure the structure with default value */
|
||||
exmc_norsram_init_struct->address_data_mux = ENABLE;
|
||||
exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_NOR;
|
||||
exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
|
||||
exmc_norsram_init_struct->burst_mode = DISABLE;
|
||||
exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
|
||||
exmc_norsram_init_struct->wrap_burst_mode = DISABLE;
|
||||
exmc_norsram_init_struct->nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
|
||||
exmc_norsram_init_struct->memory_write = ENABLE;
|
||||
exmc_norsram_init_struct->nwait_signal = ENABLE;
|
||||
exmc_norsram_init_struct->extended_mode = DISABLE;
|
||||
exmc_norsram_init_struct->asyn_wait = DISABLE;
|
||||
exmc_norsram_init_struct->write_mode = EXMC_ASYN_WRITE;
|
||||
|
||||
/* read/write timing configure */
|
||||
exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU;
|
||||
exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU;
|
||||
exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU;
|
||||
exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU;
|
||||
exmc_norsram_init_struct->read_write_timing->syn_clk_division = EXMC_SYN_CLOCK_RATIO_16_CLK;
|
||||
exmc_norsram_init_struct->read_write_timing->syn_data_latency = EXMC_DATALAT_17_CLK;
|
||||
exmc_norsram_init_struct->read_write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A;
|
||||
|
||||
/* write timing configure, when extended mode is used */
|
||||
exmc_norsram_init_struct->write_timing->asyn_address_setuptime = 0xFU;
|
||||
exmc_norsram_init_struct->write_timing->asyn_address_holdtime = 0xFU;
|
||||
exmc_norsram_init_struct->write_timing->asyn_data_setuptime = 0xFFU;
|
||||
exmc_norsram_init_struct->write_timing->bus_latency = 0xFU;
|
||||
exmc_norsram_init_struct->write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize EXMC NOR/SRAM bank
|
||||
\param[in] exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter
|
||||
write_mode: EXMC_ASYN_WRITE,EXMC_SYN_WRITE
|
||||
extended_mode: ENABLE or DISABLE
|
||||
asyn_wait: ENABLE or DISABLE
|
||||
nwait_signal: ENABLE or DISABLE
|
||||
memory_write: ENABLE or DISABLE
|
||||
nwait_config: EXMC_NWAIT_CONFIG_BEFORE,EXMC_NWAIT_CONFIG_DURING
|
||||
wrap_burst_mode: ENABLE or DISABLE
|
||||
nwait_polarity: EXMC_NWAIT_POLARITY_LOW,EXMC_NWAIT_POLARITY_HIGH
|
||||
burst_mode: ENABLE or DISABLE
|
||||
databus_width: EXMC_NOR_DATABUS_WIDTH_8B,EXMC_NOR_DATABUS_WIDTH_16B
|
||||
memory_type: EXMC_MEMORY_TYPE_SRAM,EXMC_MEMORY_TYPE_PSRAM,EXMC_MEMORY_TYPE_NOR
|
||||
address_data_mux: ENABLE or DISABLE
|
||||
read_write_timing: struct exmc_norsram_timing_parameter_struct set the time
|
||||
write_timing: struct exmc_norsram_timing_parameter_struct set the time
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
|
||||
{
|
||||
uint32_t snctl = 0x00000000U, sntcfg = 0x00000000U, snwtcfg = 0x00000000U;
|
||||
|
||||
/* get the register value */
|
||||
snctl = EXMC_SNCTL;
|
||||
|
||||
/* clear relative bits */
|
||||
snctl &= ((uint32_t)~(EXMC_SNCTL_NRMUX | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN |
|
||||
EXMC_SNCTL_NREN | EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG |
|
||||
EXMC_SNCTL_WREN | EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT |
|
||||
EXMC_SNCTL_SYNCWR ));
|
||||
|
||||
snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) |
|
||||
exmc_norsram_init_struct->memory_type |
|
||||
exmc_norsram_init_struct->databus_width |
|
||||
(exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) |
|
||||
exmc_norsram_init_struct->nwait_polarity |
|
||||
(exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) |
|
||||
exmc_norsram_init_struct->nwait_config |
|
||||
(exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) |
|
||||
(exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) |
|
||||
(exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) |
|
||||
(exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) |
|
||||
exmc_norsram_init_struct->write_mode;
|
||||
|
||||
sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U ) & EXMC_SNTCFG_ASET )|
|
||||
(((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U ) << SNTCFG_AHLD_OFFSET ) & EXMC_SNTCFG_AHLD ) |
|
||||
(((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U ) << SNTCFG_DSET_OFFSET ) & EXMC_SNTCFG_DSET ) |
|
||||
(((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U ) << SNTCFG_BUSLAT_OFFSET ) & EXMC_SNTCFG_BUSLAT )|
|
||||
exmc_norsram_init_struct->read_write_timing->syn_clk_division |
|
||||
exmc_norsram_init_struct->read_write_timing->syn_data_latency |
|
||||
exmc_norsram_init_struct->read_write_timing->asyn_access_mode;
|
||||
|
||||
/* nor flash access enable */
|
||||
if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){
|
||||
snctl |= (uint32_t)EXMC_SNCTL_NREN;
|
||||
}
|
||||
|
||||
/* extended mode configure */
|
||||
if(ENABLE == exmc_norsram_init_struct->extended_mode){
|
||||
snwtcfg = (uint32_t)((exmc_norsram_init_struct->write_timing->asyn_address_setuptime - 1U) & EXMC_SNWTCFG_WASET ) |
|
||||
(((exmc_norsram_init_struct->write_timing->asyn_address_holdtime -1U ) << SNWTCFG_WAHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD )|
|
||||
(((exmc_norsram_init_struct->write_timing->asyn_data_setuptime -1U ) << SNWTCFG_WDSET_OFFSET ) & EXMC_SNWTCFG_WDSET )|
|
||||
(((exmc_norsram_init_struct->write_timing->bus_latency - 1U ) << SNWTCFG_WBUSLAT_OFFSET ) & EXMC_SNWTCFG_WBUSLAT ) |
|
||||
exmc_norsram_init_struct->write_timing->asyn_access_mode;
|
||||
}else{
|
||||
snwtcfg = BANK0_SNWTCFG_RESET;
|
||||
}
|
||||
|
||||
/* configure the registers */
|
||||
EXMC_SNCTL = snctl;
|
||||
EXMC_SNTCFG = sntcfg;
|
||||
EXMC_SNWTCFG = snwtcfg;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable EXMC NOR/PSRAM bank
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exmc_norsram_enable(void)
|
||||
{
|
||||
EXMC_SNCTL |= (uint32_t)EXMC_SNCTL_NRBKEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable EXMC NOR/PSRAM bank
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exmc_norsram_disable(void)
|
||||
{
|
||||
EXMC_SNCTL &= ~(uint32_t)EXMC_SNCTL_NRBKEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure CRAM page size
|
||||
\param[in] page_size: CRAM page size
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXMC_CRAM_AUTO_SPLIT: the clock is generated only during synchronous access
|
||||
\arg EXMC_CRAM_PAGE_SIZE_128_BYTES: page size is 128 bytes
|
||||
\arg EXMC_CRAM_PAGE_SIZE_256_BYTES: page size is 256 bytes
|
||||
\arg EXMC_CRAM_PAGE_SIZE_512_BYTES: page size is 512 bytes
|
||||
\arg EXMC_CRAM_PAGE_SIZE_1024_BYTES: page size is 1024 bytes
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exmc_norsram_page_size_config(uint32_t page_size)
|
||||
{
|
||||
/* reset the bits */
|
||||
EXMC_SNCTL &= ~EXMC_SNCTL_CPS;
|
||||
/* set the CPS bits */
|
||||
EXMC_SNCTL |= page_size;
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
/*!
|
||||
\file gd32c10x_exti.c
|
||||
\brief EXTI driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_exti.h"
|
||||
|
||||
#define EXTI_REG_RESET_VALUE ((uint32_t)0x00000000U)
|
||||
|
||||
/*!
|
||||
\brief deinitialize the EXTI
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_deinit(void)
|
||||
{
|
||||
/* reset the value of all the EXTI registers */
|
||||
EXTI_INTEN = EXTI_REG_RESET_VALUE;
|
||||
EXTI_EVEN = EXTI_REG_RESET_VALUE;
|
||||
EXTI_RTEN = EXTI_REG_RESET_VALUE;
|
||||
EXTI_FTEN = EXTI_REG_RESET_VALUE;
|
||||
EXTI_SWIEV = EXTI_REG_RESET_VALUE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize the EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[in] mode: interrupt or event mode, refer to exti_mode_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_INTERRUPT: interrupt mode
|
||||
\arg EXTI_EVENT: event mode
|
||||
\param[in] trig_type: interrupt trigger type, refer to exti_trig_type_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_TRIG_RISING: rising edge trigger
|
||||
\arg EXTI_TRIG_FALLING: falling trigger
|
||||
\arg EXTI_TRIG_BOTH: rising and falling trigger
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type)
|
||||
{
|
||||
/* reset the EXTI line x */
|
||||
EXTI_INTEN &= ~(uint32_t)linex;
|
||||
EXTI_EVEN &= ~(uint32_t)linex;
|
||||
EXTI_RTEN &= ~(uint32_t)linex;
|
||||
EXTI_FTEN &= ~(uint32_t)linex;
|
||||
|
||||
/* set the EXTI mode and enable the interrupts or events from EXTI line x */
|
||||
switch(mode) {
|
||||
case EXTI_INTERRUPT:
|
||||
EXTI_INTEN |= (uint32_t)linex;
|
||||
break;
|
||||
case EXTI_EVENT:
|
||||
EXTI_EVEN |= (uint32_t)linex;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* set the EXTI trigger type */
|
||||
switch(trig_type) {
|
||||
case EXTI_TRIG_RISING:
|
||||
EXTI_RTEN |= (uint32_t)linex;
|
||||
EXTI_FTEN &= ~(uint32_t)linex;
|
||||
break;
|
||||
case EXTI_TRIG_FALLING:
|
||||
EXTI_RTEN &= ~(uint32_t)linex;
|
||||
EXTI_FTEN |= (uint32_t)linex;
|
||||
break;
|
||||
case EXTI_TRIG_BOTH:
|
||||
EXTI_RTEN |= (uint32_t)linex;
|
||||
EXTI_FTEN |= (uint32_t)linex;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable the interrupts from EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_interrupt_enable(exti_line_enum linex)
|
||||
{
|
||||
EXTI_INTEN |= (uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable the interrupt from EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_interrupt_disable(exti_line_enum linex)
|
||||
{
|
||||
EXTI_INTEN &= ~(uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable the events from EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_event_enable(exti_line_enum linex)
|
||||
{
|
||||
EXTI_EVEN |= (uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable the events from EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_event_disable(exti_line_enum linex)
|
||||
{
|
||||
EXTI_EVEN &= ~(uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable the software interrupt event from EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_software_interrupt_enable(exti_line_enum linex)
|
||||
{
|
||||
EXTI_SWIEV |= (uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable the software interrupt event from EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_software_interrupt_disable(exti_line_enum linex)
|
||||
{
|
||||
EXTI_SWIEV &= ~(uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get EXTI line x interrupt pending flag
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus exti_flag_get(exti_line_enum linex)
|
||||
{
|
||||
if(RESET != (EXTI_PD & (uint32_t)linex)) {
|
||||
return SET;
|
||||
} else {
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear EXTI line x interrupt pending flag
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_flag_clear(exti_line_enum linex)
|
||||
{
|
||||
EXTI_PD = (uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get EXTI line x interrupt pending flag
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus exti_interrupt_flag_get(exti_line_enum linex)
|
||||
{
|
||||
if(RESET != (EXTI_PD & (uint32_t)linex)) {
|
||||
return SET;
|
||||
} else {
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear EXTI line x interrupt pending flag
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_interrupt_flag_clear(exti_line_enum linex)
|
||||
{
|
||||
EXTI_PD = (uint32_t)linex;
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
/*!
|
||||
\file gd32c10x_exti.c
|
||||
\brief EXTI driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_exti.h"
|
||||
|
||||
#define EXTI_REG_RESET_VALUE ((uint32_t)0x00000000U)
|
||||
|
||||
/*!
|
||||
\brief deinitialize the EXTI
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_deinit(void)
|
||||
{
|
||||
/* reset the value of all the EXTI registers */
|
||||
EXTI_INTEN = EXTI_REG_RESET_VALUE;
|
||||
EXTI_EVEN = EXTI_REG_RESET_VALUE;
|
||||
EXTI_RTEN = EXTI_REG_RESET_VALUE;
|
||||
EXTI_FTEN = EXTI_REG_RESET_VALUE;
|
||||
EXTI_SWIEV = EXTI_REG_RESET_VALUE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize the EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[in] mode: interrupt or event mode, refer to exti_mode_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_INTERRUPT: interrupt mode
|
||||
\arg EXTI_EVENT: event mode
|
||||
\param[in] trig_type: interrupt trigger type, refer to exti_trig_type_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_TRIG_RISING: rising edge trigger
|
||||
\arg EXTI_TRIG_FALLING: falling trigger
|
||||
\arg EXTI_TRIG_BOTH: rising and falling trigger
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type)
|
||||
{
|
||||
/* reset the EXTI line x */
|
||||
EXTI_INTEN &= ~(uint32_t)linex;
|
||||
EXTI_EVEN &= ~(uint32_t)linex;
|
||||
EXTI_RTEN &= ~(uint32_t)linex;
|
||||
EXTI_FTEN &= ~(uint32_t)linex;
|
||||
|
||||
/* set the EXTI mode and enable the interrupts or events from EXTI line x */
|
||||
switch(mode) {
|
||||
case EXTI_INTERRUPT:
|
||||
EXTI_INTEN |= (uint32_t)linex;
|
||||
break;
|
||||
case EXTI_EVENT:
|
||||
EXTI_EVEN |= (uint32_t)linex;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* set the EXTI trigger type */
|
||||
switch(trig_type) {
|
||||
case EXTI_TRIG_RISING:
|
||||
EXTI_RTEN |= (uint32_t)linex;
|
||||
EXTI_FTEN &= ~(uint32_t)linex;
|
||||
break;
|
||||
case EXTI_TRIG_FALLING:
|
||||
EXTI_RTEN &= ~(uint32_t)linex;
|
||||
EXTI_FTEN |= (uint32_t)linex;
|
||||
break;
|
||||
case EXTI_TRIG_BOTH:
|
||||
EXTI_RTEN |= (uint32_t)linex;
|
||||
EXTI_FTEN |= (uint32_t)linex;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable the interrupts from EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_interrupt_enable(exti_line_enum linex)
|
||||
{
|
||||
EXTI_INTEN |= (uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable the interrupt from EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_interrupt_disable(exti_line_enum linex)
|
||||
{
|
||||
EXTI_INTEN &= ~(uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable the events from EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_event_enable(exti_line_enum linex)
|
||||
{
|
||||
EXTI_EVEN |= (uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable the events from EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_event_disable(exti_line_enum linex)
|
||||
{
|
||||
EXTI_EVEN &= ~(uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable the software interrupt event from EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_software_interrupt_enable(exti_line_enum linex)
|
||||
{
|
||||
EXTI_SWIEV |= (uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable the software interrupt event from EXTI line x
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_software_interrupt_disable(exti_line_enum linex)
|
||||
{
|
||||
EXTI_SWIEV &= ~(uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get EXTI line x interrupt pending flag
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus exti_flag_get(exti_line_enum linex)
|
||||
{
|
||||
if(RESET != (EXTI_PD & (uint32_t)linex)) {
|
||||
return SET;
|
||||
} else {
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear EXTI line x interrupt pending flag
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_flag_clear(exti_line_enum linex)
|
||||
{
|
||||
EXTI_PD = (uint32_t)linex;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get EXTI line x interrupt pending flag
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus exti_interrupt_flag_get(exti_line_enum linex)
|
||||
{
|
||||
if(RESET != (EXTI_PD & (uint32_t)linex)) {
|
||||
return SET;
|
||||
} else {
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear EXTI line x interrupt pending flag
|
||||
\param[in] linex: EXTI line number, refer to exti_line_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg EXTI_x (x=0..18): EXTI line x
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void exti_interrupt_flag_clear(exti_line_enum linex)
|
||||
{
|
||||
EXTI_PD = (uint32_t)linex;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,215 @@
|
||||
/*!
|
||||
\file gd32c10x_fwdgt.c
|
||||
\brief FWDGT driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_fwdgt.h"
|
||||
|
||||
/*!
|
||||
\brief enable write access to FWDGT_PSC and FWDGT_RLD
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fwdgt_write_enable(void)
|
||||
{
|
||||
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable write access to FWDGT_PSC and FWDGT_RLD
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fwdgt_write_disable(void)
|
||||
{
|
||||
FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief start the free watchdog timer counter
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fwdgt_enable(void)
|
||||
{
|
||||
FWDGT_CTL = FWDGT_KEY_ENABLE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the free watchdog timer counter prescaler value
|
||||
\param[in] prescaler_value: specify 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
|
||||
\arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16
|
||||
\arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32
|
||||
\arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64
|
||||
\arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128
|
||||
\arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256
|
||||
\param[out] none
|
||||
\retval ErrStatus: ERROR or SUCCESS
|
||||
*/
|
||||
ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value)
|
||||
{
|
||||
uint32_t timeout = FWDGT_PSC_TIMEOUT;
|
||||
uint32_t flag_status = RESET;
|
||||
|
||||
/* enable write access to FWDGT_PSC */
|
||||
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
|
||||
|
||||
/* wait until the PUD flag to be reset */
|
||||
do {
|
||||
flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
|
||||
} while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
|
||||
|
||||
if((uint32_t)RESET != flag_status) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* configure FWDGT */
|
||||
FWDGT_PSC = (uint32_t)prescaler_value;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the free watchdog timer counter reload value
|
||||
\param[in] reload_value: specify reload value(0x0000 - 0x0FFF)
|
||||
\param[out] none
|
||||
\retval ErrStatus: ERROR or SUCCESS
|
||||
*/
|
||||
ErrStatus fwdgt_reload_value_config(uint16_t reload_value)
|
||||
{
|
||||
uint32_t timeout = FWDGT_RLD_TIMEOUT;
|
||||
uint32_t flag_status = RESET;
|
||||
|
||||
/* enable write access to FWDGT_RLD */
|
||||
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
FWDGT_RLD = RLD_RLD(reload_value);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reload the counter of FWDGT
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fwdgt_counter_reload(void)
|
||||
{
|
||||
FWDGT_CTL = FWDGT_KEY_RELOAD;
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
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
|
||||
\arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16
|
||||
\arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32
|
||||
\arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64
|
||||
\arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128
|
||||
\arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256
|
||||
\param[out] none
|
||||
\retval ErrStatus: ERROR or SUCCESS
|
||||
*/
|
||||
ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div)
|
||||
{
|
||||
uint32_t timeout = FWDGT_PSC_TIMEOUT;
|
||||
uint32_t flag_status = RESET;
|
||||
|
||||
/* enable write access to FWDGT_PSC,and FWDGT_RLD */
|
||||
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
|
||||
|
||||
/* wait until the PUD flag to be reset */
|
||||
do {
|
||||
flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
|
||||
} while((--timeout > 0U) && ((uint32_t)RESET != 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;
|
||||
}
|
||||
|
||||
FWDGT_RLD = RLD_RLD(reload_value);
|
||||
|
||||
/* reload the counter */
|
||||
FWDGT_CTL = FWDGT_KEY_RELOAD;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get flag state of FWDGT
|
||||
\param[in] flag: flag to get
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going
|
||||
\arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus fwdgt_flag_get(uint16_t flag)
|
||||
{
|
||||
if(FWDGT_STAT & flag) {
|
||||
return SET;
|
||||
}
|
||||
|
||||
return RESET;
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/*!
|
||||
\file gd32c10x_fwdgt.c
|
||||
\brief FWDGT driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_fwdgt.h"
|
||||
|
||||
/*!
|
||||
\brief enable write access to FWDGT_PSC and FWDGT_RLD
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fwdgt_write_enable(void)
|
||||
{
|
||||
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable write access to FWDGT_PSC and FWDGT_RLD
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fwdgt_write_disable(void)
|
||||
{
|
||||
FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief start the free watchdog timer counter
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fwdgt_enable(void)
|
||||
{
|
||||
FWDGT_CTL = FWDGT_KEY_ENABLE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the free watchdog timer counter prescaler value
|
||||
\param[in] prescaler_value: specify 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
|
||||
\arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16
|
||||
\arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32
|
||||
\arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64
|
||||
\arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128
|
||||
\arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256
|
||||
\param[out] none
|
||||
\retval ErrStatus: ERROR or SUCCESS
|
||||
*/
|
||||
ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value)
|
||||
{
|
||||
uint32_t timeout = FWDGT_PSC_TIMEOUT;
|
||||
uint32_t flag_status = RESET;
|
||||
|
||||
/* enable write access to FWDGT_PSC */
|
||||
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
|
||||
|
||||
/* wait until the PUD flag to be reset */
|
||||
do {
|
||||
flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
|
||||
} while((--timeout > 0U) && ((uint32_t)RESET != flag_status));
|
||||
|
||||
if((uint32_t)RESET != flag_status) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* configure FWDGT */
|
||||
FWDGT_PSC = (uint32_t)prescaler_value;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the free watchdog timer counter reload value
|
||||
\param[in] reload_value: specify reload value(0x0000 - 0x0FFF)
|
||||
\param[out] none
|
||||
\retval ErrStatus: ERROR or SUCCESS
|
||||
*/
|
||||
ErrStatus fwdgt_reload_value_config(uint16_t reload_value)
|
||||
{
|
||||
uint32_t timeout = FWDGT_RLD_TIMEOUT;
|
||||
uint32_t flag_status = RESET;
|
||||
|
||||
/* enable write access to FWDGT_RLD */
|
||||
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
FWDGT_RLD = RLD_RLD(reload_value);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reload the counter of FWDGT
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void fwdgt_counter_reload(void)
|
||||
{
|
||||
FWDGT_CTL = FWDGT_KEY_RELOAD;
|
||||
}
|
||||
|
||||
/*!
|
||||
\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
|
||||
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
|
||||
\arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16
|
||||
\arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32
|
||||
\arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64
|
||||
\arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128
|
||||
\arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256
|
||||
\param[out] none
|
||||
\retval ErrStatus: ERROR or SUCCESS
|
||||
*/
|
||||
ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div)
|
||||
{
|
||||
uint32_t timeout = FWDGT_PSC_TIMEOUT;
|
||||
uint32_t flag_status = RESET;
|
||||
|
||||
/* enable write access to FWDGT_PSC,and FWDGT_RLD */
|
||||
FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE;
|
||||
|
||||
/* wait until the PUD flag to be reset */
|
||||
do {
|
||||
flag_status = FWDGT_STAT & FWDGT_STAT_PUD;
|
||||
} while((--timeout > 0U) && ((uint32_t)RESET != 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;
|
||||
}
|
||||
|
||||
FWDGT_RLD = RLD_RLD(reload_value);
|
||||
|
||||
/* reload the counter */
|
||||
FWDGT_CTL = FWDGT_KEY_RELOAD;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get flag state of FWDGT
|
||||
\param[in] flag: flag to get
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going
|
||||
\arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus fwdgt_flag_get(uint16_t flag)
|
||||
{
|
||||
if(FWDGT_STAT & flag) {
|
||||
return SET;
|
||||
}
|
||||
|
||||
return RESET;
|
||||
}
|
||||
@@ -0,0 +1,538 @@
|
||||
/*!
|
||||
\file gd32c10x_gpio.c
|
||||
\brief GPIO driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_gpio.h"
|
||||
|
||||
#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/
|
||||
#define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */
|
||||
#define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */
|
||||
#define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */
|
||||
#define PCF_SWJCFG_MASK ((uint32_t)0xF8FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */
|
||||
#define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */
|
||||
#define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */
|
||||
#define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */
|
||||
#define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/
|
||||
|
||||
/*!
|
||||
\brief reset GPIO port
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_deinit(uint32_t gpio_periph)
|
||||
{
|
||||
switch(gpio_periph){
|
||||
case GPIOA:
|
||||
/* reset GPIOA */
|
||||
rcu_periph_reset_enable(RCU_GPIOARST);
|
||||
rcu_periph_reset_disable(RCU_GPIOARST);
|
||||
break;
|
||||
case GPIOB:
|
||||
/* reset GPIOB */
|
||||
rcu_periph_reset_enable(RCU_GPIOBRST);
|
||||
rcu_periph_reset_disable(RCU_GPIOBRST);
|
||||
break;
|
||||
case GPIOC:
|
||||
/* reset GPIOC */
|
||||
rcu_periph_reset_enable(RCU_GPIOCRST);
|
||||
rcu_periph_reset_disable(RCU_GPIOCRST);
|
||||
break;
|
||||
case GPIOD:
|
||||
/* reset GPIOD */
|
||||
rcu_periph_reset_enable(RCU_GPIODRST);
|
||||
rcu_periph_reset_disable(RCU_GPIODRST);
|
||||
break;
|
||||
case GPIOE:
|
||||
/* reset GPIOE */
|
||||
rcu_periph_reset_enable(RCU_GPIOERST);
|
||||
rcu_periph_reset_disable(RCU_GPIOERST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset alternate function I/O(AFIO)
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_afio_deinit(void)
|
||||
{
|
||||
rcu_periph_reset_enable(RCU_AFRST);
|
||||
rcu_periph_reset_disable(RCU_AFRST);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief GPIO parameter initialization
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] mode: gpio pin mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg GPIO_MODE_AIN: analog input mode
|
||||
\arg GPIO_MODE_IN_FLOATING: floating input mode
|
||||
\arg GPIO_MODE_IPD: pull-down input mode
|
||||
\arg GPIO_MODE_IPU: pull-up input mode
|
||||
\arg GPIO_MODE_OUT_OD: GPIO output with open-drain
|
||||
\arg GPIO_MODE_OUT_PP: GPIO output with push-pull
|
||||
\arg GPIO_MODE_AF_OD: AFIO output with open-drain
|
||||
\arg GPIO_MODE_AF_PP: AFIO output with push-pull
|
||||
\param[in] speed: gpio output max speed value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg GPIO_OSPEED_10MHZ: output max speed 10MHz
|
||||
\arg GPIO_OSPEED_2MHZ: output max speed 2MHz
|
||||
\arg GPIO_OSPEED_50MHZ: output max speed 50MHz
|
||||
\arg GPIO_OSPEED_MAX: output max speed more than 50MHz
|
||||
\param[in] pin: GPIO pin
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin)
|
||||
{
|
||||
uint16_t i;
|
||||
uint32_t temp_mode = 0U;
|
||||
uint32_t reg = 0U;
|
||||
|
||||
/* GPIO mode configuration */
|
||||
temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU));
|
||||
|
||||
/* GPIO speed configuration */
|
||||
if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))){
|
||||
/* output mode max speed */
|
||||
if(GPIO_OSPEED_MAX == (uint32_t)speed){
|
||||
temp_mode |= (uint32_t)0x03U;
|
||||
/* set the corresponding SPD bit */
|
||||
GPIOx_SPD(gpio_periph) |= (uint32_t)pin ;
|
||||
}else{
|
||||
/* output mode max speed:10MHz,2MHz,50MHz */
|
||||
temp_mode |= (uint32_t)speed;
|
||||
}
|
||||
}
|
||||
|
||||
/* configure the eight low port pins with GPIO_CTL0 */
|
||||
for(i = 0U;i < 8U;i++){
|
||||
if((1U << i) & pin){
|
||||
reg = GPIO_CTL0(gpio_periph);
|
||||
|
||||
/* clear the specified pin mode bits */
|
||||
reg &= ~GPIO_MODE_MASK(i);
|
||||
/* set the specified pin mode bits */
|
||||
reg |= GPIO_MODE_SET(i, temp_mode);
|
||||
|
||||
/* set IPD or IPU */
|
||||
if(GPIO_MODE_IPD == mode){
|
||||
/* reset the corresponding OCTL bit */
|
||||
GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}else{
|
||||
/* set the corresponding OCTL bit */
|
||||
if(GPIO_MODE_IPU == mode){
|
||||
GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}
|
||||
}
|
||||
/* set GPIO_CTL0 register */
|
||||
GPIO_CTL0(gpio_periph) = reg;
|
||||
}
|
||||
}
|
||||
/* configure the eight high port pins with GPIO_CTL1 */
|
||||
for(i = 8U;i < 16U;i++){
|
||||
if((1U << i) & pin){
|
||||
reg = GPIO_CTL1(gpio_periph);
|
||||
|
||||
/* clear the specified pin mode bits */
|
||||
reg &= ~GPIO_MODE_MASK(i - 8U);
|
||||
/* set the specified pin mode bits */
|
||||
reg |= GPIO_MODE_SET(i - 8U, temp_mode);
|
||||
|
||||
/* set IPD or IPU */
|
||||
if(GPIO_MODE_IPD == mode){
|
||||
/* reset the corresponding OCTL bit */
|
||||
GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}else{
|
||||
/* set the corresponding OCTL bit */
|
||||
if(GPIO_MODE_IPU == mode){
|
||||
GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}
|
||||
}
|
||||
/* set GPIO_CTL1 register */
|
||||
GPIO_CTL1(gpio_periph) = reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set GPIO pin
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] pin: GPIO pin
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_bit_set(uint32_t gpio_periph, uint32_t pin)
|
||||
{
|
||||
GPIO_BOP(gpio_periph) = (uint32_t)pin;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset GPIO pin
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] pin: GPIO pin
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin)
|
||||
{
|
||||
GPIO_BC(gpio_periph) = (uint32_t)pin;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief write data to the specified GPIO pin
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] pin: GPIO pin
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[in] bit_value: SET or RESET
|
||||
\arg RESET: clear the port pin
|
||||
\arg SET: set the port pin
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value)
|
||||
{
|
||||
if(RESET != bit_value){
|
||||
GPIO_BOP(gpio_periph) = (uint32_t)pin;
|
||||
}else{
|
||||
GPIO_BC(gpio_periph) = (uint32_t)pin;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief write data to the specified GPIO port
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] data: specify the value to be written to the port output data register
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_port_write(uint32_t gpio_periph,uint16_t data)
|
||||
{
|
||||
GPIO_OCTL(gpio_periph) = (uint32_t)data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get GPIO pin input status
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] pin: GPIO pin
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[out] none
|
||||
\retval input status of gpio pin: SET or RESET
|
||||
*/
|
||||
FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin)
|
||||
{
|
||||
if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get GPIO port input status
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[out] none
|
||||
\retval input status of gpio all pins
|
||||
*/
|
||||
uint16_t gpio_input_port_get(uint32_t gpio_periph)
|
||||
{
|
||||
return (uint16_t)(GPIO_ISTAT(gpio_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get GPIO pin output status
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] pin: GPIO pin
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[out] none
|
||||
\retval output status of gpio pin: SET or RESET
|
||||
*/
|
||||
FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin)
|
||||
{
|
||||
if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get GPIO port output status
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[out] none
|
||||
\retval output status of gpio all pins
|
||||
*/
|
||||
uint16_t gpio_output_port_get(uint32_t gpio_periph)
|
||||
{
|
||||
return ((uint16_t)GPIO_OCTL(gpio_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure GPIO pin remap
|
||||
\param[in] gpio_remap: select the pin to remap
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_SPI0_REMAP: SPI0 remapping
|
||||
\arg GPIO_I2C0_REMAP: I2C0 remapping
|
||||
\arg GPIO_USART0_REMAP: USART0 remapping
|
||||
\arg GPIO_USART1_REMAP: USART1 remapping
|
||||
\arg GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping
|
||||
\arg GPIO_USART2_FULL_REMAP: USART2 full remapping
|
||||
\arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping
|
||||
\arg GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping
|
||||
\arg GPIO_TIMER1_PARTIAL_REMAP0: TIMER1 partial remapping
|
||||
\arg GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping
|
||||
\arg GPIO_TIMER1_FULL_REMAP: TIMER1 full remapping
|
||||
\arg GPIO_TIMER2_PARTIAL_REMAP: TIMER2 partial remapping
|
||||
\arg GPIO_TIMER2_FULL_REMAP: TIMER2 full remapping
|
||||
\arg GPIO_TIMER3_REMAP: TIMER3 remapping
|
||||
\arg GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping
|
||||
\arg GPIO_CAN0_FULL_REMAP: CAN0 full remapping
|
||||
\arg GPIO_PD01_REMAP: PD01 remapping
|
||||
\arg GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping
|
||||
\arg GPIO_ADC0_ETRGRT_REMAP: ADC0 external trigger routine conversion remapping
|
||||
\arg GPIO_ADC1_ETRGRT_REMAP: ADC1 external trigger routine conversion remapping
|
||||
\arg GPIO_CAN1_REMAP: CAN1 remapping
|
||||
\arg GPIO_SWJ_NONJTRST_REMAP: full SWJ(JTAG-DP + SW-DP),but without NJTRST
|
||||
\arg GPIO_SWJ_SWDPENABLE_REMAP: JTAG-DP disabled and SW-DP enabled
|
||||
\arg GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled and SW-DP disabled
|
||||
\arg GPIO_SPI2_REMAP: SPI2 remapping
|
||||
\arg GPIO_TIMER1ITI1_REMAP: TIMER1 internal trigger 1 remapping
|
||||
\arg GPIO_TIMER8_REMAP: TIMER8 remapping
|
||||
\arg GPIO_EXMC_NADV_REMAP: EXMC_NADV connect/disconnect
|
||||
\arg GPIO_CTC_REMAP0: CTC remapping(PD15)
|
||||
\param[in] newvalue: ENABLE or DISABLE
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue)
|
||||
{
|
||||
uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U;
|
||||
|
||||
if(((uint32_t)0x80000000U) == (remap & 0x80000000U)){
|
||||
/* get AFIO_PCF1 register value */
|
||||
temp_reg = AFIO_PCF1;
|
||||
}else{
|
||||
/* get AFIO_PCF0 register value */
|
||||
temp_reg = AFIO_PCF0;
|
||||
}
|
||||
|
||||
temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U;
|
||||
remap1 = remap & LSB_16BIT_MASK;
|
||||
|
||||
/* judge pin remap type */
|
||||
if((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))){
|
||||
temp_reg &= PCF_SWJCFG_MASK;
|
||||
AFIO_PCF0 &= PCF_SWJCFG_MASK;
|
||||
}else if(PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)){
|
||||
remap2 = ((uint32_t)0x03U) << temp_mask;
|
||||
temp_reg &= ~remap2;
|
||||
temp_reg |= ~PCF_SWJCFG_MASK;
|
||||
}else{
|
||||
temp_reg &= ~(remap1 << ((remap >> 0x15U)*0x10U));
|
||||
temp_reg |= ~PCF_SWJCFG_MASK;
|
||||
}
|
||||
|
||||
/* set pin remap value */
|
||||
if(DISABLE != newvalue){
|
||||
temp_reg |= (remap1 << ((remap >> 0x15U)*0x10U));
|
||||
}
|
||||
|
||||
if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)){
|
||||
/* set AFIO_PCF1 register value */
|
||||
AFIO_PCF1 = temp_reg;
|
||||
}else{
|
||||
/* set AFIO_PCF0 register value */
|
||||
AFIO_PCF0 = temp_reg;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select GPIO pin exti sources
|
||||
\param[in] output_port: gpio event output port
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_PORT_SOURCE_GPIOA: output port source A
|
||||
\arg GPIO_PORT_SOURCE_GPIOB: output port source B
|
||||
\arg GPIO_PORT_SOURCE_GPIOC: output port source C
|
||||
\arg GPIO_PORT_SOURCE_GPIOD: output port source D
|
||||
\arg GPIO_PORT_SOURCE_GPIOE: output port source E
|
||||
\param[in] output_pin:
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_PIN_SOURCE_x(x=0..15)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin)
|
||||
{
|
||||
uint32_t source = 0U;
|
||||
source = ((uint32_t)0x0FU) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK));
|
||||
|
||||
/* select EXTI sources */
|
||||
if(GPIO_PIN_SOURCE_4 > output_pin){
|
||||
/* select EXTI0/EXTI1/EXTI2/EXTI3 */
|
||||
AFIO_EXTISS0 &= ~source;
|
||||
AFIO_EXTISS0 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}else if(GPIO_PIN_SOURCE_8 > output_pin){
|
||||
/* select EXTI4/EXTI5/EXTI6/EXTI7 */
|
||||
AFIO_EXTISS1 &= ~source;
|
||||
AFIO_EXTISS1 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}else if(GPIO_PIN_SOURCE_12 > output_pin){
|
||||
/* select EXTI8/EXTI9/EXTI10/EXTI11 */
|
||||
AFIO_EXTISS2 &= ~source;
|
||||
AFIO_EXTISS2 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}else{
|
||||
/* select EXTI12/EXTI13/EXTI14/EXTI15 */
|
||||
AFIO_EXTISS3 &= ~source;
|
||||
AFIO_EXTISS3 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure GPIO pin event output
|
||||
\param[in] output_port: gpio event output port
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_EVENT_PORT_GPIOA: event output port A
|
||||
\arg GPIO_EVENT_PORT_GPIOB: event output port B
|
||||
\arg GPIO_EVENT_PORT_GPIOC: event output port C
|
||||
\arg GPIO_EVENT_PORT_GPIOD: event output port D
|
||||
\arg GPIO_EVENT_PORT_GPIOE: event output port E
|
||||
\param[in] output_pin:
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_EVENT_PIN_x(x=0..15)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_event_output_config(uint8_t output_port, uint8_t output_pin)
|
||||
{
|
||||
uint32_t reg = 0U;
|
||||
reg = AFIO_EC;
|
||||
|
||||
/* clear AFIO_EC_PORT and AFIO_EC_PIN bits */
|
||||
reg &= (uint32_t)(~(AFIO_EC_PORT|AFIO_EC_PIN));
|
||||
|
||||
reg |= (uint32_t)((uint32_t)output_port << GPIO_OUTPUT_PORT_OFFSET);
|
||||
reg |= (uint32_t)output_pin;
|
||||
|
||||
AFIO_EC = reg;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable GPIO pin event output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_event_output_enable(void)
|
||||
{
|
||||
AFIO_EC |= AFIO_EC_EOE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable GPIO pin event output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_event_output_disable(void)
|
||||
{
|
||||
AFIO_EC &= (uint32_t)(~AFIO_EC_EOE);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief lock GPIO pin
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] pin: GPIO pin
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin)
|
||||
{
|
||||
uint32_t lock = 0x00010000U;
|
||||
lock |= pin;
|
||||
|
||||
/* lock key writing sequence: write 1 -> write 0 -> write 1 -> read 0 -> read 1 */
|
||||
GPIO_LOCK(gpio_periph) = (uint32_t)lock;
|
||||
GPIO_LOCK(gpio_periph) = (uint32_t)pin;
|
||||
GPIO_LOCK(gpio_periph) = (uint32_t)lock;
|
||||
lock = GPIO_LOCK(gpio_periph);
|
||||
lock = GPIO_LOCK(gpio_periph);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the I/O compensation cell
|
||||
\param[in] compensation: specifies the I/O compensation cell mode
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_COMPENSATION_ENABLE: I/O compensation cell is enabled
|
||||
\arg GPIO_COMPENSATION_DISABLE: I/O compensation cell is disabled
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_compensation_config(uint32_t compensation)
|
||||
{
|
||||
uint32_t reg;
|
||||
reg = AFIO_CPSCTL;
|
||||
|
||||
/* reset the AFIO_CPSCTL_CPS_EN bit and set according to gpio_compensation */
|
||||
reg &= ~AFIO_CPSCTL_CPS_EN;
|
||||
AFIO_CPSCTL = (reg | compensation);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check the I/O compensation cell is ready or not
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus gpio_compensation_flag_get(void)
|
||||
{
|
||||
if(((uint32_t)RESET) != (AFIO_CPSCTL & AFIO_CPSCTL_CPS_RDY)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,538 @@
|
||||
/*!
|
||||
\file gd32c10x_gpio.c
|
||||
\brief GPIO driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_gpio.h"
|
||||
|
||||
#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/
|
||||
#define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */
|
||||
#define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */
|
||||
#define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */
|
||||
#define PCF_SWJCFG_MASK ((uint32_t)0xF8FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */
|
||||
#define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */
|
||||
#define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */
|
||||
#define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */
|
||||
#define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/
|
||||
|
||||
/*!
|
||||
\brief reset GPIO port
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_deinit(uint32_t gpio_periph)
|
||||
{
|
||||
switch(gpio_periph){
|
||||
case GPIOA:
|
||||
/* reset GPIOA */
|
||||
rcu_periph_reset_enable(RCU_GPIOARST);
|
||||
rcu_periph_reset_disable(RCU_GPIOARST);
|
||||
break;
|
||||
case GPIOB:
|
||||
/* reset GPIOB */
|
||||
rcu_periph_reset_enable(RCU_GPIOBRST);
|
||||
rcu_periph_reset_disable(RCU_GPIOBRST);
|
||||
break;
|
||||
case GPIOC:
|
||||
/* reset GPIOC */
|
||||
rcu_periph_reset_enable(RCU_GPIOCRST);
|
||||
rcu_periph_reset_disable(RCU_GPIOCRST);
|
||||
break;
|
||||
case GPIOD:
|
||||
/* reset GPIOD */
|
||||
rcu_periph_reset_enable(RCU_GPIODRST);
|
||||
rcu_periph_reset_disable(RCU_GPIODRST);
|
||||
break;
|
||||
case GPIOE:
|
||||
/* reset GPIOE */
|
||||
rcu_periph_reset_enable(RCU_GPIOERST);
|
||||
rcu_periph_reset_disable(RCU_GPIOERST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset alternate function I/O(AFIO)
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_afio_deinit(void)
|
||||
{
|
||||
rcu_periph_reset_enable(RCU_AFRST);
|
||||
rcu_periph_reset_disable(RCU_AFRST);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief GPIO parameter initialization
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] mode: gpio pin mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg GPIO_MODE_AIN: analog input mode
|
||||
\arg GPIO_MODE_IN_FLOATING: floating input mode
|
||||
\arg GPIO_MODE_IPD: pull-down input mode
|
||||
\arg GPIO_MODE_IPU: pull-up input mode
|
||||
\arg GPIO_MODE_OUT_OD: GPIO output with open-drain
|
||||
\arg GPIO_MODE_OUT_PP: GPIO output with push-pull
|
||||
\arg GPIO_MODE_AF_OD: AFIO output with open-drain
|
||||
\arg GPIO_MODE_AF_PP: AFIO output with push-pull
|
||||
\param[in] speed: gpio output max speed value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg GPIO_OSPEED_10MHZ: output max speed 10MHz
|
||||
\arg GPIO_OSPEED_2MHZ: output max speed 2MHz
|
||||
\arg GPIO_OSPEED_50MHZ: output max speed 50MHz
|
||||
\arg GPIO_OSPEED_MAX: output max speed more than 50MHz
|
||||
\param[in] pin: GPIO pin
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin)
|
||||
{
|
||||
uint16_t i;
|
||||
uint32_t temp_mode = 0U;
|
||||
uint32_t reg = 0U;
|
||||
|
||||
/* GPIO mode configuration */
|
||||
temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU));
|
||||
|
||||
/* GPIO speed configuration */
|
||||
if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))){
|
||||
/* output mode max speed */
|
||||
if(GPIO_OSPEED_MAX == (uint32_t)speed){
|
||||
temp_mode |= (uint32_t)0x03U;
|
||||
/* set the corresponding SPD bit */
|
||||
GPIOx_SPD(gpio_periph) |= (uint32_t)pin ;
|
||||
}else{
|
||||
/* output mode max speed:10MHz,2MHz,50MHz */
|
||||
temp_mode |= (uint32_t)speed;
|
||||
}
|
||||
}
|
||||
|
||||
/* configure the eight low port pins with GPIO_CTL0 */
|
||||
for(i = 0U;i < 8U;i++){
|
||||
if((1U << i) & pin){
|
||||
reg = GPIO_CTL0(gpio_periph);
|
||||
|
||||
/* clear the specified pin mode bits */
|
||||
reg &= ~GPIO_MODE_MASK(i);
|
||||
/* set the specified pin mode bits */
|
||||
reg |= GPIO_MODE_SET(i, temp_mode);
|
||||
|
||||
/* set IPD or IPU */
|
||||
if(GPIO_MODE_IPD == mode){
|
||||
/* reset the corresponding OCTL bit */
|
||||
GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}else{
|
||||
/* set the corresponding OCTL bit */
|
||||
if(GPIO_MODE_IPU == mode){
|
||||
GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}
|
||||
}
|
||||
/* set GPIO_CTL0 register */
|
||||
GPIO_CTL0(gpio_periph) = reg;
|
||||
}
|
||||
}
|
||||
/* configure the eight high port pins with GPIO_CTL1 */
|
||||
for(i = 8U;i < 16U;i++){
|
||||
if((1U << i) & pin){
|
||||
reg = GPIO_CTL1(gpio_periph);
|
||||
|
||||
/* clear the specified pin mode bits */
|
||||
reg &= ~GPIO_MODE_MASK(i - 8U);
|
||||
/* set the specified pin mode bits */
|
||||
reg |= GPIO_MODE_SET(i - 8U, temp_mode);
|
||||
|
||||
/* set IPD or IPU */
|
||||
if(GPIO_MODE_IPD == mode){
|
||||
/* reset the corresponding OCTL bit */
|
||||
GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}else{
|
||||
/* set the corresponding OCTL bit */
|
||||
if(GPIO_MODE_IPU == mode){
|
||||
GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin);
|
||||
}
|
||||
}
|
||||
/* set GPIO_CTL1 register */
|
||||
GPIO_CTL1(gpio_periph) = reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set GPIO pin
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] pin: GPIO pin
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_bit_set(uint32_t gpio_periph, uint32_t pin)
|
||||
{
|
||||
GPIO_BOP(gpio_periph) = (uint32_t)pin;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset GPIO pin
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] pin: GPIO pin
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin)
|
||||
{
|
||||
GPIO_BC(gpio_periph) = (uint32_t)pin;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief write data to the specified GPIO pin
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] pin: GPIO pin
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[in] bit_value: SET or RESET
|
||||
\arg RESET: clear the port pin
|
||||
\arg SET: set the port pin
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value)
|
||||
{
|
||||
if(RESET != bit_value){
|
||||
GPIO_BOP(gpio_periph) = (uint32_t)pin;
|
||||
}else{
|
||||
GPIO_BC(gpio_periph) = (uint32_t)pin;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief write data to the specified GPIO port
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] data: specify the value to be written to the port output data register
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_port_write(uint32_t gpio_periph,uint16_t data)
|
||||
{
|
||||
GPIO_OCTL(gpio_periph) = (uint32_t)data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get GPIO pin input status
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] pin: GPIO pin
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[out] none
|
||||
\retval input status of gpio pin: SET or RESET
|
||||
*/
|
||||
FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin)
|
||||
{
|
||||
if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get GPIO port input status
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[out] none
|
||||
\retval input status of gpio all pins
|
||||
*/
|
||||
uint16_t gpio_input_port_get(uint32_t gpio_periph)
|
||||
{
|
||||
return (uint16_t)(GPIO_ISTAT(gpio_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get GPIO pin output status
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] pin: GPIO pin
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[out] none
|
||||
\retval output status of gpio pin: SET or RESET
|
||||
*/
|
||||
FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin)
|
||||
{
|
||||
if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get GPIO port output status
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[out] none
|
||||
\retval output status of gpio all pins
|
||||
*/
|
||||
uint16_t gpio_output_port_get(uint32_t gpio_periph)
|
||||
{
|
||||
return ((uint16_t)GPIO_OCTL(gpio_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure GPIO pin remap
|
||||
\param[in] gpio_remap: select the pin to remap
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_SPI0_REMAP: SPI0 remapping
|
||||
\arg GPIO_I2C0_REMAP: I2C0 remapping
|
||||
\arg GPIO_USART0_REMAP: USART0 remapping
|
||||
\arg GPIO_USART1_REMAP: USART1 remapping
|
||||
\arg GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping
|
||||
\arg GPIO_USART2_FULL_REMAP: USART2 full remapping
|
||||
\arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping
|
||||
\arg GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping
|
||||
\arg GPIO_TIMER1_PARTIAL_REMAP0: TIMER1 partial remapping
|
||||
\arg GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping
|
||||
\arg GPIO_TIMER1_FULL_REMAP: TIMER1 full remapping
|
||||
\arg GPIO_TIMER2_PARTIAL_REMAP: TIMER2 partial remapping
|
||||
\arg GPIO_TIMER2_FULL_REMAP: TIMER2 full remapping
|
||||
\arg GPIO_TIMER3_REMAP: TIMER3 remapping
|
||||
\arg GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping
|
||||
\arg GPIO_CAN0_FULL_REMAP: CAN0 full remapping
|
||||
\arg GPIO_PD01_REMAP: PD01 remapping
|
||||
\arg GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping
|
||||
\arg GPIO_ADC0_ETRGRT_REMAP: ADC0 external trigger routine conversion remapping
|
||||
\arg GPIO_ADC1_ETRGRT_REMAP: ADC1 external trigger routine conversion remapping
|
||||
\arg GPIO_CAN1_REMAP: CAN1 remapping
|
||||
\arg GPIO_SWJ_NONJTRST_REMAP: full SWJ(JTAG-DP + SW-DP),but without NJTRST
|
||||
\arg GPIO_SWJ_SWDPENABLE_REMAP: JTAG-DP disabled and SW-DP enabled
|
||||
\arg GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled and SW-DP disabled
|
||||
\arg GPIO_SPI2_REMAP: SPI2 remapping
|
||||
\arg GPIO_TIMER1ITI1_REMAP: TIMER1 internal trigger 1 remapping
|
||||
\arg GPIO_TIMER8_REMAP: TIMER8 remapping
|
||||
\arg GPIO_EXMC_NADV_REMAP: EXMC_NADV connect/disconnect
|
||||
\arg GPIO_CTC_REMAP0: CTC remapping(PD15)
|
||||
\param[in] newvalue: ENABLE or DISABLE
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue)
|
||||
{
|
||||
uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U;
|
||||
|
||||
if(((uint32_t)0x80000000U) == (remap & 0x80000000U)){
|
||||
/* get AFIO_PCF1 register value */
|
||||
temp_reg = AFIO_PCF1;
|
||||
}else{
|
||||
/* get AFIO_PCF0 register value */
|
||||
temp_reg = AFIO_PCF0;
|
||||
}
|
||||
|
||||
temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U;
|
||||
remap1 = remap & LSB_16BIT_MASK;
|
||||
|
||||
/* judge pin remap type */
|
||||
if((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))){
|
||||
temp_reg &= PCF_SWJCFG_MASK;
|
||||
AFIO_PCF0 &= PCF_SWJCFG_MASK;
|
||||
}else if(PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)){
|
||||
remap2 = ((uint32_t)0x03U) << temp_mask;
|
||||
temp_reg &= ~remap2;
|
||||
temp_reg |= ~PCF_SWJCFG_MASK;
|
||||
}else{
|
||||
temp_reg &= ~(remap1 << ((remap >> 0x15U)*0x10U));
|
||||
temp_reg |= ~PCF_SWJCFG_MASK;
|
||||
}
|
||||
|
||||
/* set pin remap value */
|
||||
if(DISABLE != newvalue){
|
||||
temp_reg |= (remap1 << ((remap >> 0x15U)*0x10U));
|
||||
}
|
||||
|
||||
if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)){
|
||||
/* set AFIO_PCF1 register value */
|
||||
AFIO_PCF1 = temp_reg;
|
||||
}else{
|
||||
/* set AFIO_PCF0 register value */
|
||||
AFIO_PCF0 = temp_reg;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select GPIO pin exti sources
|
||||
\param[in] output_port: gpio event output port
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_PORT_SOURCE_GPIOA: output port source A
|
||||
\arg GPIO_PORT_SOURCE_GPIOB: output port source B
|
||||
\arg GPIO_PORT_SOURCE_GPIOC: output port source C
|
||||
\arg GPIO_PORT_SOURCE_GPIOD: output port source D
|
||||
\arg GPIO_PORT_SOURCE_GPIOE: output port source E
|
||||
\param[in] output_pin:
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_PIN_SOURCE_x(x=0..15)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin)
|
||||
{
|
||||
uint32_t source = 0U;
|
||||
source = ((uint32_t)0x0FU) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK));
|
||||
|
||||
/* select EXTI sources */
|
||||
if(GPIO_PIN_SOURCE_4 > output_pin){
|
||||
/* select EXTI0/EXTI1/EXTI2/EXTI3 */
|
||||
AFIO_EXTISS0 &= ~source;
|
||||
AFIO_EXTISS0 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}else if(GPIO_PIN_SOURCE_8 > output_pin){
|
||||
/* select EXTI4/EXTI5/EXTI6/EXTI7 */
|
||||
AFIO_EXTISS1 &= ~source;
|
||||
AFIO_EXTISS1 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}else if(GPIO_PIN_SOURCE_12 > output_pin){
|
||||
/* select EXTI8/EXTI9/EXTI10/EXTI11 */
|
||||
AFIO_EXTISS2 &= ~source;
|
||||
AFIO_EXTISS2 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}else{
|
||||
/* select EXTI12/EXTI13/EXTI14/EXTI15 */
|
||||
AFIO_EXTISS3 &= ~source;
|
||||
AFIO_EXTISS3 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure GPIO pin event output
|
||||
\param[in] output_port: gpio event output port
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_EVENT_PORT_GPIOA: event output port A
|
||||
\arg GPIO_EVENT_PORT_GPIOB: event output port B
|
||||
\arg GPIO_EVENT_PORT_GPIOC: event output port C
|
||||
\arg GPIO_EVENT_PORT_GPIOD: event output port D
|
||||
\arg GPIO_EVENT_PORT_GPIOE: event output port E
|
||||
\param[in] output_pin:
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_EVENT_PIN_x(x=0..15)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_event_output_config(uint8_t output_port, uint8_t output_pin)
|
||||
{
|
||||
uint32_t reg = 0U;
|
||||
reg = AFIO_EC;
|
||||
|
||||
/* clear AFIO_EC_PORT and AFIO_EC_PIN bits */
|
||||
reg &= (uint32_t)(~(AFIO_EC_PORT|AFIO_EC_PIN));
|
||||
|
||||
reg |= (uint32_t)((uint32_t)output_port << GPIO_OUTPUT_PORT_OFFSET);
|
||||
reg |= (uint32_t)output_pin;
|
||||
|
||||
AFIO_EC = reg;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable GPIO pin event output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_event_output_enable(void)
|
||||
{
|
||||
AFIO_EC |= AFIO_EC_EOE;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable GPIO pin event output
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_event_output_disable(void)
|
||||
{
|
||||
AFIO_EC &= (uint32_t)(~AFIO_EC_EOE);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief lock GPIO pin
|
||||
\param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
|
||||
\param[in] pin: GPIO pin
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin)
|
||||
{
|
||||
uint32_t lock = 0x00010000U;
|
||||
lock |= pin;
|
||||
|
||||
/* lock key writing sequence: write 1 -> write 0 -> write 1 -> read 0 -> read 1 */
|
||||
GPIO_LOCK(gpio_periph) = (uint32_t)lock;
|
||||
GPIO_LOCK(gpio_periph) = (uint32_t)pin;
|
||||
GPIO_LOCK(gpio_periph) = (uint32_t)lock;
|
||||
lock = GPIO_LOCK(gpio_periph);
|
||||
lock = GPIO_LOCK(gpio_periph);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the I/O compensation cell
|
||||
\param[in] compensation: specifies the I/O compensation cell mode
|
||||
only one parameter can be selected which are shown as below:
|
||||
\arg GPIO_COMPENSATION_ENABLE: I/O compensation cell is enabled
|
||||
\arg GPIO_COMPENSATION_DISABLE: I/O compensation cell is disabled
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void gpio_compensation_config(uint32_t compensation)
|
||||
{
|
||||
uint32_t reg;
|
||||
reg = AFIO_CPSCTL;
|
||||
|
||||
/* reset the AFIO_CPSCTL_CPS_EN bit and set according to gpio_compensation */
|
||||
reg &= ~AFIO_CPSCTL_CPS_EN;
|
||||
AFIO_CPSCTL = (reg | compensation);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check the I/O compensation cell is ready or not
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus gpio_compensation_flag_get(void)
|
||||
{
|
||||
if(((uint32_t)RESET) != (AFIO_CPSCTL & AFIO_CPSCTL_CPS_RDY)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,797 @@
|
||||
/*!
|
||||
\file gd32c10x_i2c.c
|
||||
\brief I2C driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_i2c.h"
|
||||
|
||||
/* I2C register bit mask */
|
||||
#define I2CCLK_MAX ((uint32_t)0x0000003FU) /*!< i2cclk maximum value */
|
||||
#define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */
|
||||
#define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */
|
||||
#define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */
|
||||
#define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */
|
||||
|
||||
/* I2C register bit offset */
|
||||
#define STAT1_PECV_OFFSET ((uint32_t)0x00000008U) /*!< bit offset of PECV in I2C_STAT1 */
|
||||
|
||||
/*!
|
||||
\brief reset I2C
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_deinit(uint32_t i2c_periph)
|
||||
{
|
||||
switch(i2c_periph){
|
||||
case I2C0:
|
||||
/* reset I2C0 */
|
||||
rcu_periph_reset_enable(RCU_I2C0RST);
|
||||
rcu_periph_reset_disable(RCU_I2C0RST);
|
||||
break;
|
||||
case I2C1:
|
||||
/* reset I2C1 */
|
||||
rcu_periph_reset_enable(RCU_I2C1RST);
|
||||
rcu_periph_reset_disable(RCU_I2C1RST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C clock
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz)
|
||||
and fast mode plus (up to 1MHz)
|
||||
\param[in] dutycyc: duty cycle in fast mode or fast mode plus, and only I2C_DTCY_2 can be selected in standard mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_DTCY_2: T_low/T_high=2
|
||||
\arg I2C_DTCY_16_9: T_low/T_high=16/9
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc)
|
||||
{
|
||||
uint32_t pclk1, clkc, freq, risetime;
|
||||
uint32_t temp;
|
||||
|
||||
pclk1 = rcu_clock_freq_get(CK_APB1);
|
||||
/* I2C peripheral clock frequency */
|
||||
freq = (uint32_t)(pclk1 / 1000000U);
|
||||
if(freq >= I2CCLK_MAX) {
|
||||
freq = I2CCLK_MAX;
|
||||
}
|
||||
temp = I2C_CTL1(i2c_periph);
|
||||
temp &= ~I2C_CTL1_I2CCLK;
|
||||
temp |= freq;
|
||||
|
||||
I2C_CTL1(i2c_periph) = temp;
|
||||
|
||||
if(100000U >= clkspeed) {
|
||||
/* the maximum SCL rise time is 1000ns in standard mode */
|
||||
risetime = (uint32_t)((pclk1 / 1000000U) + 1U);
|
||||
if(risetime >= I2CCLK_MAX) {
|
||||
I2C_RT(i2c_periph) = I2CCLK_MAX;
|
||||
} else if(risetime <= I2CCLK_MIN) {
|
||||
I2C_RT(i2c_periph) = I2CCLK_MIN;
|
||||
}else{
|
||||
I2C_RT(i2c_periph) = risetime;
|
||||
}
|
||||
clkc = (uint32_t)(pclk1 / (clkspeed * 2U));
|
||||
if(clkc < 0x04U) {
|
||||
/* the CLKC in standard mode minimum value is 4 */
|
||||
clkc = 0x04U;
|
||||
}
|
||||
|
||||
I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc);
|
||||
} else if(400000U >= clkspeed) {
|
||||
/* the maximum SCL rise time is 300ns in fast mode */
|
||||
I2C_RT(i2c_periph) = (uint32_t)(((freq * (uint32_t)300U) / (uint32_t)1000U) + (uint32_t)1U);
|
||||
if(I2C_DTCY_2 == dutycyc) {
|
||||
/* I2C duty cycle is 2 */
|
||||
clkc = (uint32_t)(pclk1 / (clkspeed * 3U));
|
||||
I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY;
|
||||
} else {
|
||||
/* I2C duty cycle is 16/9 */
|
||||
clkc = (uint32_t)(pclk1 / (clkspeed * 25U));
|
||||
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY;
|
||||
}
|
||||
if(0U == (clkc & I2C_CKCFG_CLKC)) {
|
||||
/* the CLKC in fast mode minimum value is 1 */
|
||||
clkc |= 0x0001U;
|
||||
}
|
||||
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
|
||||
I2C_CKCFG(i2c_periph) |= clkc;
|
||||
}else{
|
||||
/* fast mode plus, the maximum SCL rise time is 120ns */
|
||||
I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)120U)/(uint32_t)1000U)+(uint32_t)1U);
|
||||
if(I2C_DTCY_2 == dutycyc){
|
||||
/* I2C duty cycle is 2 */
|
||||
clkc = (uint32_t)(pclk1/(clkspeed*3U));
|
||||
I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY;
|
||||
}else{
|
||||
/* I2C duty cycle is 16/9 */
|
||||
clkc = (uint32_t)(pclk1/(clkspeed*25U));
|
||||
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY;
|
||||
}
|
||||
/* enable fast mode */
|
||||
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
|
||||
I2C_CKCFG(i2c_periph) |= clkc;
|
||||
/* enable I2C fast mode plus */
|
||||
I2C_FMPCFG(i2c_periph) = I2C_FMPCFG_FMPEN;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C address
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] mode:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_I2CMODE_ENABLE: I2C mode
|
||||
\arg I2C_SMBUSMODE_ENABLE: SMBus mode
|
||||
\param[in] addformat: 7bits or 10bits
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_ADDFORMAT_7BITS: address format is 7 bits
|
||||
\arg I2C_ADDFORMAT_10BITS: address format is 10 bits
|
||||
\param[in] addr: I2C address
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr)
|
||||
{
|
||||
/* SMBus/I2C mode selected */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_SMBEN);
|
||||
ctl |= mode;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
/* configure address */
|
||||
addr = addr & I2C_ADDRESS_MASK;
|
||||
I2C_SADDR0(i2c_periph) = (addformat | addr);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select SMBus type
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] type:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_SMBUS_DEVICE: SMBus mode device type
|
||||
\arg I2C_SMBUS_HOST: SMBus mode host type
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type)
|
||||
{
|
||||
if(I2C_SMBUS_HOST == type){
|
||||
I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL;
|
||||
}else{
|
||||
I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief whether or not to send an ACK
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] ack:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_ACK_ENABLE: ACK will be sent
|
||||
\arg I2C_ACK_DISABLE: ACK will not be sent
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_ack_config(uint32_t i2c_periph, uint32_t ack)
|
||||
{
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_ACKEN);
|
||||
ctl |= ack;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C POAP position
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] pos:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_ACKPOS_CURRENT: ACKEN bit decides whether or not to send ACK or not for the current byte
|
||||
\arg I2C_ACKPOS_NEXT: ACKEN bit decides whether or not to send ACK for the next byte
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos)
|
||||
{
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
/* configure I2C POAP position */
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_POAP);
|
||||
ctl |= pos;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief master sends slave address
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] addr: slave address
|
||||
\param[in] trandirection: transmitter or receiver
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_TRANSMITTER: transmitter
|
||||
\arg I2C_RECEIVER: receiver
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection)
|
||||
{
|
||||
/* master is a transmitter or a receiver */
|
||||
if(I2C_TRANSMITTER == trandirection){
|
||||
addr = addr & I2C_TRANSMITTER;
|
||||
}else{
|
||||
addr = addr | I2C_RECEIVER;
|
||||
}
|
||||
/* send slave address */
|
||||
I2C_DATA(i2c_periph) = addr;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable dual-address mode
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] addr: the second address in dual-address mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr)
|
||||
{
|
||||
/* configure address */
|
||||
addr = addr & I2C_ADDRESS2_MASK;
|
||||
I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable dual-address mode
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_dualaddr_disable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable I2C
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_enable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable I2C
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_disable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief generate a START condition on I2C bus
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_start_on_bus(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_CTL0(i2c_periph) |= I2C_CTL0_START;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief generate a STOP condition on I2C bus
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_stop_on_bus(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief I2C transmit data function
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] data: data of transmission
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_data_transmit(uint32_t i2c_periph, uint8_t data)
|
||||
{
|
||||
I2C_DATA(i2c_periph) = DATA_TRANS(data);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief I2C receive data function
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval data of received
|
||||
*/
|
||||
uint8_t i2c_data_receive(uint32_t i2c_periph)
|
||||
{
|
||||
return (uint8_t)DATA_RECV(I2C_DATA(i2c_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C DMA mode
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] dmastate:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_DMA_ON: enable DMA mode
|
||||
\arg I2C_DMA_OFF: disable DMA mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_dma_config(uint32_t i2c_periph, uint32_t dmastate)
|
||||
{
|
||||
/* configure I2C DMA function */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL1(i2c_periph);
|
||||
ctl &= ~(I2C_CTL1_DMAON);
|
||||
ctl |= dmastate;
|
||||
I2C_CTL1(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure whether next DMA EOT is DMA last transfer or not
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] dmalast:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_DMALST_ON: next DMA EOT is the last transfer
|
||||
\arg I2C_DMALST_OFF: next DMA EOT is not the last transfer
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast)
|
||||
{
|
||||
/* configure DMA last transfer */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL1(i2c_periph);
|
||||
ctl &= ~(I2C_CTL1_DMALST);
|
||||
ctl |= dmalast;
|
||||
I2C_CTL1(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief whether to stretch SCL low when data is not ready in slave mode
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] stretchpara:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_SCLSTRETCH_ENABLE: enable SCL stretching
|
||||
\arg I2C_SCLSTRETCH_DISABLE: disable SCL stretching
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara)
|
||||
{
|
||||
/* configure I2C SCL stretching */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_SS);
|
||||
ctl |= stretchpara;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief whether or not to response to a general call
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] gcallpara:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_GCEN_ENABLE: slave will response to a general call
|
||||
\arg I2C_GCEN_DISABLE: slave will not response to a general call
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara)
|
||||
{
|
||||
/* configure slave response to a general call enable or disable */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_GCEN);
|
||||
ctl |= gcallpara;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure software reset of I2C
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] sreset:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_SRESET_SET: I2C is under reset
|
||||
\arg I2C_SRESET_RESET: I2C is not under reset
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset)
|
||||
{
|
||||
/* modify CTL0 and configure software reset I2C state */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_SRESET);
|
||||
ctl |= sreset;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C PEC calculation
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] pecstate:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_PEC_ENABLE: PEC calculation on
|
||||
\arg I2C_PEC_DISABLE: PEC calculation off
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_pec_config(uint32_t i2c_periph, uint32_t pecstate)
|
||||
{
|
||||
/* on/off PEC calculation */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_PECEN);
|
||||
ctl |= pecstate;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure whether to transfer PEC value
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] pecpara:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_PECTRANS_ENABLE: transfer PEC value
|
||||
\arg I2C_PECTRANS_DISABLE: not transfer PEC value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_pec_transfer_config(uint32_t i2c_periph, uint32_t pecpara)
|
||||
{
|
||||
/* whether to transfer PEC */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_PECTRANS);
|
||||
ctl |= pecpara;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get packet error checking value
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval PEC value
|
||||
*/
|
||||
uint8_t i2c_pec_value_get(uint32_t i2c_periph)
|
||||
{
|
||||
return (uint8_t)((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV) >> STAT1_PECV_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C alert through SMBA pin
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] smbuspara:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin
|
||||
\arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_smbus_alert_config(uint32_t i2c_periph, uint32_t smbuspara)
|
||||
{
|
||||
/* configure smbus alert through SMBA pin */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_SALT);
|
||||
ctl |= smbuspara;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C ARP protocol in SMBus
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] arpstate:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_ARP_ENABLE: enable ARP
|
||||
\arg I2C_ARP_DISABLE: disable ARP
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_smbus_arp_config(uint32_t i2c_periph, uint32_t arpstate)
|
||||
{
|
||||
/* enable or disable I2C ARP protocol*/
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_ARPEN);
|
||||
ctl |= arpstate;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SAM_V interface
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_sam_enable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_SAMCS(i2c_periph) |= I2C_SAMCS_SAMEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SAM_V interface
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_sam_disable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_SAMEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SAM_V interface timeout detect
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_sam_timeout_enable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_SAMCS(i2c_periph) |= I2C_SAMCS_STOEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SAM_V interface timeout detect
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_sam_timeout_disable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_STOEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check I2C flag is set or not
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] flag: I2C flags, refer to i2c_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_FLAG_SBSEND: start condition sent out in master mode
|
||||
\arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode
|
||||
\arg I2C_FLAG_BTC: byte transmission finishes
|
||||
\arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode
|
||||
\arg I2C_FLAG_STPDET: stop condition detected in slave mode
|
||||
\arg I2C_FLAG_RBNE: I2C_DATA is not empty during receiving
|
||||
\arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting
|
||||
\arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus
|
||||
\arg I2C_FLAG_LOSTARB: arbitration lost in master mode
|
||||
\arg I2C_FLAG_AERR: acknowledge error
|
||||
\arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode
|
||||
\arg I2C_FLAG_PECERR: PEC error when receiving data
|
||||
\arg I2C_FLAG_SMBTO: timeout signal in SMBus mode
|
||||
\arg I2C_FLAG_SMBALT: SMBus alert status
|
||||
\arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode
|
||||
\arg I2C_FLAG_I2CBSY: busy flag
|
||||
\arg I2C_FLAG_TR: whether the I2C is a transmitter or a receiver
|
||||
\arg I2C_FLAG_RXGC: general call address (00h) received
|
||||
\arg I2C_FLAG_DEFSMB: default address of SMBus device
|
||||
\arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode
|
||||
\arg I2C_FLAG_DUMOD: dual flag in slave mode indicating which address is matched in dual-address mode
|
||||
\arg I2C_FLAG_TFF: txframe fall flag
|
||||
\arg I2C_FLAG_TFR: txframe rise flag
|
||||
\arg I2C_FLAG_RFF: rxframe fall flag
|
||||
\arg I2C_FLAG_RFR: rxframe rise flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag)
|
||||
{
|
||||
if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear I2C flag status
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] flag: I2C flags, refer to i2c_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_FLAG_SMBALT: SMBus alert status
|
||||
\arg I2C_FLAG_SMBTO: timeout signal in SMBus mode
|
||||
\arg I2C_FLAG_PECERR: PEC error when receiving data
|
||||
\arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode
|
||||
\arg I2C_FLAG_AERR: acknowledge error
|
||||
\arg I2C_FLAG_LOSTARB: arbitration lost in master mode
|
||||
\arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus
|
||||
\arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode
|
||||
\arg I2C_FLAG_TFF: txframe fall flag
|
||||
\arg I2C_FLAG_TFR: txframe rise flag
|
||||
\arg I2C_FLAG_RFF: rxframe fall flag
|
||||
\arg I2C_FLAG_RFR: rxframe rise flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag)
|
||||
{
|
||||
if(I2C_FLAG_ADDSEND == flag){
|
||||
/* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
|
||||
I2C_STAT0(i2c_periph);
|
||||
I2C_STAT1(i2c_periph);
|
||||
}else{
|
||||
I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable I2C interrupt
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_INT_ERR: error interrupt
|
||||
\arg I2C_INT_EV: event interrupt
|
||||
\arg I2C_INT_BUF: buffer interrupt
|
||||
\arg I2C_INT_TFF: txframe fall interrupt
|
||||
\arg I2C_INT_TFR: txframe rise interrupt
|
||||
\arg I2C_INT_RFF: rxframe fall interrupt
|
||||
\arg I2C_INT_RFR: rxframe rise interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
|
||||
{
|
||||
I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable I2C interrupt
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_INT_ERR: error interrupt
|
||||
\arg I2C_INT_EV: event interrupt
|
||||
\arg I2C_INT_BUF: buffer interrupt
|
||||
\arg I2C_INT_TFF: txframe fall interrupt
|
||||
\arg I2C_INT_TFR: txframe rise interrupt
|
||||
\arg I2C_INT_RFF: rxframe fall interrupt
|
||||
\arg I2C_INT_RFR: rxframe rise interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
|
||||
{
|
||||
I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get I2C interrupt flag status
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag
|
||||
\arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag
|
||||
\arg I2C_INT_FLAG_BTC: byte transmission finishes interrupt flag
|
||||
\arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag
|
||||
\arg I2C_INT_FLAG_STPDET: stop condition detected in slave mode interrupt flag
|
||||
\arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag
|
||||
\arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag
|
||||
\arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag
|
||||
\arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag
|
||||
\arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag
|
||||
\arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag
|
||||
\arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag
|
||||
\arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag
|
||||
\arg I2C_INT_FLAG_SMBALT: SMBus alert status interrupt flag
|
||||
\arg I2C_INT_FLAG_TFF: txframe fall interrupt flag
|
||||
\arg I2C_INT_FLAG_TFR: txframe rise interrupt flag
|
||||
\arg I2C_INT_FLAG_RFF: rxframe fall interrupt flag
|
||||
\arg I2C_INT_FLAG_RFR: rxframe rise interrupt flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag)
|
||||
{
|
||||
uint32_t intenable = 0U, flagstatus = 0U, bufie;
|
||||
|
||||
/* check BUFIE */
|
||||
bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE;
|
||||
|
||||
/* get the interrupt enable bit status */
|
||||
intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag)));
|
||||
/* get the corresponding flag bit status */
|
||||
flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag)));
|
||||
|
||||
if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)){
|
||||
if(intenable && bufie){
|
||||
intenable = 1U;
|
||||
}else{
|
||||
intenable = 0U;
|
||||
}
|
||||
}
|
||||
if((0U != flagstatus) && (0U != intenable)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear I2C interrupt flag status
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag
|
||||
\arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag
|
||||
\arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag
|
||||
\arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag
|
||||
\arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag
|
||||
\arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag
|
||||
\arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag
|
||||
\arg I2C_INT_FLAG_SMBALT: SMBus alert status interrupt flag
|
||||
\arg I2C_INT_FLAG_TFF: txframe fall interrupt flag
|
||||
\arg I2C_INT_FLAG_TFR: txframe rise interrupt flag
|
||||
\arg I2C_INT_FLAG_RFF: rxframe fall interrupt flag
|
||||
\arg I2C_INT_FLAG_RFR: rxframe rise interrupt flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag)
|
||||
{
|
||||
if(I2C_INT_FLAG_ADDSEND == int_flag){
|
||||
/* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
|
||||
I2C_STAT0(i2c_periph);
|
||||
I2C_STAT1(i2c_periph);
|
||||
}else{
|
||||
I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,797 @@
|
||||
/*!
|
||||
\file gd32c10x_i2c.c
|
||||
\brief I2C driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_i2c.h"
|
||||
|
||||
/* I2C register bit mask */
|
||||
#define I2CCLK_MAX ((uint32_t)0x0000003FU) /*!< i2cclk maximum value */
|
||||
#define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */
|
||||
#define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */
|
||||
#define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */
|
||||
#define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */
|
||||
|
||||
/* I2C register bit offset */
|
||||
#define STAT1_PECV_OFFSET ((uint32_t)0x00000008U) /*!< bit offset of PECV in I2C_STAT1 */
|
||||
|
||||
/*!
|
||||
\brief reset I2C
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_deinit(uint32_t i2c_periph)
|
||||
{
|
||||
switch(i2c_periph){
|
||||
case I2C0:
|
||||
/* reset I2C0 */
|
||||
rcu_periph_reset_enable(RCU_I2C0RST);
|
||||
rcu_periph_reset_disable(RCU_I2C0RST);
|
||||
break;
|
||||
case I2C1:
|
||||
/* reset I2C1 */
|
||||
rcu_periph_reset_enable(RCU_I2C1RST);
|
||||
rcu_periph_reset_disable(RCU_I2C1RST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C clock
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz)
|
||||
and fast mode plus (up to 1MHz)
|
||||
\param[in] dutycyc: duty cycle in fast mode or fast mode plus, and only I2C_DTCY_2 can be selected in standard mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_DTCY_2: T_low/T_high=2
|
||||
\arg I2C_DTCY_16_9: T_low/T_high=16/9
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc)
|
||||
{
|
||||
uint32_t pclk1, clkc, freq, risetime;
|
||||
uint32_t temp;
|
||||
|
||||
pclk1 = rcu_clock_freq_get(CK_APB1);
|
||||
/* I2C peripheral clock frequency */
|
||||
freq = (uint32_t)(pclk1 / 1000000U);
|
||||
if(freq >= I2CCLK_MAX) {
|
||||
freq = I2CCLK_MAX;
|
||||
}
|
||||
temp = I2C_CTL1(i2c_periph);
|
||||
temp &= ~I2C_CTL1_I2CCLK;
|
||||
temp |= freq;
|
||||
|
||||
I2C_CTL1(i2c_periph) = temp;
|
||||
|
||||
if(100000U >= clkspeed) {
|
||||
/* the maximum SCL rise time is 1000ns in standard mode */
|
||||
risetime = (uint32_t)((pclk1 / 1000000U) + 1U);
|
||||
if(risetime >= I2CCLK_MAX) {
|
||||
I2C_RT(i2c_periph) = I2CCLK_MAX;
|
||||
} else if(risetime <= I2CCLK_MIN) {
|
||||
I2C_RT(i2c_periph) = I2CCLK_MIN;
|
||||
}else{
|
||||
I2C_RT(i2c_periph) = risetime;
|
||||
}
|
||||
clkc = (uint32_t)(pclk1 / (clkspeed * 2U));
|
||||
if(clkc < 0x04U) {
|
||||
/* the CLKC in standard mode minimum value is 4 */
|
||||
clkc = 0x04U;
|
||||
}
|
||||
|
||||
I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc);
|
||||
} else if(400000U >= clkspeed) {
|
||||
/* the maximum SCL rise time is 300ns in fast mode */
|
||||
I2C_RT(i2c_periph) = (uint32_t)(((freq * (uint32_t)300U) / (uint32_t)1000U) + (uint32_t)1U);
|
||||
if(I2C_DTCY_2 == dutycyc) {
|
||||
/* I2C duty cycle is 2 */
|
||||
clkc = (uint32_t)(pclk1 / (clkspeed * 3U));
|
||||
I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY;
|
||||
} else {
|
||||
/* I2C duty cycle is 16/9 */
|
||||
clkc = (uint32_t)(pclk1 / (clkspeed * 25U));
|
||||
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY;
|
||||
}
|
||||
if(0U == (clkc & I2C_CKCFG_CLKC)) {
|
||||
/* the CLKC in fast mode minimum value is 1 */
|
||||
clkc |= 0x0001U;
|
||||
}
|
||||
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
|
||||
I2C_CKCFG(i2c_periph) |= clkc;
|
||||
}else{
|
||||
/* fast mode plus, the maximum SCL rise time is 120ns */
|
||||
I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)120U)/(uint32_t)1000U)+(uint32_t)1U);
|
||||
if(I2C_DTCY_2 == dutycyc){
|
||||
/* I2C duty cycle is 2 */
|
||||
clkc = (uint32_t)(pclk1/(clkspeed*3U));
|
||||
I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY;
|
||||
}else{
|
||||
/* I2C duty cycle is 16/9 */
|
||||
clkc = (uint32_t)(pclk1/(clkspeed*25U));
|
||||
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY;
|
||||
}
|
||||
/* enable fast mode */
|
||||
I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST;
|
||||
I2C_CKCFG(i2c_periph) |= clkc;
|
||||
/* enable I2C fast mode plus */
|
||||
I2C_FMPCFG(i2c_periph) = I2C_FMPCFG_FMPEN;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C address
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] mode:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_I2CMODE_ENABLE: I2C mode
|
||||
\arg I2C_SMBUSMODE_ENABLE: SMBus mode
|
||||
\param[in] addformat: 7bits or 10bits
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_ADDFORMAT_7BITS: address format is 7 bits
|
||||
\arg I2C_ADDFORMAT_10BITS: address format is 10 bits
|
||||
\param[in] addr: I2C address
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr)
|
||||
{
|
||||
/* SMBus/I2C mode selected */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_SMBEN);
|
||||
ctl |= mode;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
/* configure address */
|
||||
addr = addr & I2C_ADDRESS_MASK;
|
||||
I2C_SADDR0(i2c_periph) = (addformat | addr);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select SMBus type
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] type:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_SMBUS_DEVICE: SMBus mode device type
|
||||
\arg I2C_SMBUS_HOST: SMBus mode host type
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type)
|
||||
{
|
||||
if(I2C_SMBUS_HOST == type){
|
||||
I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL;
|
||||
}else{
|
||||
I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief whether or not to send an ACK
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] ack:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_ACK_ENABLE: ACK will be sent
|
||||
\arg I2C_ACK_DISABLE: ACK will not be sent
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_ack_config(uint32_t i2c_periph, uint32_t ack)
|
||||
{
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_ACKEN);
|
||||
ctl |= ack;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C POAP position
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] pos:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_ACKPOS_CURRENT: ACKEN bit decides whether or not to send ACK or not for the current byte
|
||||
\arg I2C_ACKPOS_NEXT: ACKEN bit decides whether or not to send ACK for the next byte
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos)
|
||||
{
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
/* configure I2C POAP position */
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_POAP);
|
||||
ctl |= pos;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief master sends slave address
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] addr: slave address
|
||||
\param[in] trandirection: transmitter or receiver
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_TRANSMITTER: transmitter
|
||||
\arg I2C_RECEIVER: receiver
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection)
|
||||
{
|
||||
/* master is a transmitter or a receiver */
|
||||
if(I2C_TRANSMITTER == trandirection){
|
||||
addr = addr & I2C_TRANSMITTER;
|
||||
}else{
|
||||
addr = addr | I2C_RECEIVER;
|
||||
}
|
||||
/* send slave address */
|
||||
I2C_DATA(i2c_periph) = addr;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable dual-address mode
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] addr: the second address in dual-address mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr)
|
||||
{
|
||||
/* configure address */
|
||||
addr = addr & I2C_ADDRESS2_MASK;
|
||||
I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable dual-address mode
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_dualaddr_disable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable I2C
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_enable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable I2C
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_disable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief generate a START condition on I2C bus
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_start_on_bus(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_CTL0(i2c_periph) |= I2C_CTL0_START;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief generate a STOP condition on I2C bus
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_stop_on_bus(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief I2C transmit data function
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] data: data of transmission
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_data_transmit(uint32_t i2c_periph, uint8_t data)
|
||||
{
|
||||
I2C_DATA(i2c_periph) = DATA_TRANS(data);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief I2C receive data function
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval data of received
|
||||
*/
|
||||
uint8_t i2c_data_receive(uint32_t i2c_periph)
|
||||
{
|
||||
return (uint8_t)DATA_RECV(I2C_DATA(i2c_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C DMA mode
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] dmastate:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_DMA_ON: enable DMA mode
|
||||
\arg I2C_DMA_OFF: disable DMA mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_dma_config(uint32_t i2c_periph, uint32_t dmastate)
|
||||
{
|
||||
/* configure I2C DMA function */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL1(i2c_periph);
|
||||
ctl &= ~(I2C_CTL1_DMAON);
|
||||
ctl |= dmastate;
|
||||
I2C_CTL1(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure whether next DMA EOT is DMA last transfer or not
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] dmalast:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_DMALST_ON: next DMA EOT is the last transfer
|
||||
\arg I2C_DMALST_OFF: next DMA EOT is not the last transfer
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast)
|
||||
{
|
||||
/* configure DMA last transfer */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL1(i2c_periph);
|
||||
ctl &= ~(I2C_CTL1_DMALST);
|
||||
ctl |= dmalast;
|
||||
I2C_CTL1(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief whether to stretch SCL low when data is not ready in slave mode
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] stretchpara:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_SCLSTRETCH_ENABLE: enable SCL stretching
|
||||
\arg I2C_SCLSTRETCH_DISABLE: disable SCL stretching
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara)
|
||||
{
|
||||
/* configure I2C SCL stretching */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_SS);
|
||||
ctl |= stretchpara;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief whether or not to response to a general call
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] gcallpara:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_GCEN_ENABLE: slave will response to a general call
|
||||
\arg I2C_GCEN_DISABLE: slave will not response to a general call
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara)
|
||||
{
|
||||
/* configure slave response to a general call enable or disable */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_GCEN);
|
||||
ctl |= gcallpara;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure software reset of I2C
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] sreset:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_SRESET_SET: I2C is under reset
|
||||
\arg I2C_SRESET_RESET: I2C is not under reset
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset)
|
||||
{
|
||||
/* modify CTL0 and configure software reset I2C state */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_SRESET);
|
||||
ctl |= sreset;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C PEC calculation
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] pecstate:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_PEC_ENABLE: PEC calculation on
|
||||
\arg I2C_PEC_DISABLE: PEC calculation off
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_pec_config(uint32_t i2c_periph, uint32_t pecstate)
|
||||
{
|
||||
/* on/off PEC calculation */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_PECEN);
|
||||
ctl |= pecstate;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure whether to transfer PEC value
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] pecpara:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_PECTRANS_ENABLE: transfer PEC value
|
||||
\arg I2C_PECTRANS_DISABLE: not transfer PEC value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_pec_transfer_config(uint32_t i2c_periph, uint32_t pecpara)
|
||||
{
|
||||
/* whether to transfer PEC */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_PECTRANS);
|
||||
ctl |= pecpara;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get packet error checking value
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval PEC value
|
||||
*/
|
||||
uint8_t i2c_pec_value_get(uint32_t i2c_periph)
|
||||
{
|
||||
return (uint8_t)((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV) >> STAT1_PECV_OFFSET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C alert through SMBA pin
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] smbuspara:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin
|
||||
\arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_smbus_alert_config(uint32_t i2c_periph, uint32_t smbuspara)
|
||||
{
|
||||
/* configure smbus alert through SMBA pin */
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_SALT);
|
||||
ctl |= smbuspara;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2C ARP protocol in SMBus
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] arpstate:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_ARP_ENABLE: enable ARP
|
||||
\arg I2C_ARP_DISABLE: disable ARP
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_smbus_arp_config(uint32_t i2c_periph, uint32_t arpstate)
|
||||
{
|
||||
/* enable or disable I2C ARP protocol*/
|
||||
uint32_t ctl = 0U;
|
||||
|
||||
ctl = I2C_CTL0(i2c_periph);
|
||||
ctl &= ~(I2C_CTL0_ARPEN);
|
||||
ctl |= arpstate;
|
||||
I2C_CTL0(i2c_periph) = ctl;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SAM_V interface
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_sam_enable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_SAMCS(i2c_periph) |= I2C_SAMCS_SAMEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SAM_V interface
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_sam_disable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_SAMEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SAM_V interface timeout detect
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_sam_timeout_enable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_SAMCS(i2c_periph) |= I2C_SAMCS_STOEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SAM_V interface timeout detect
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_sam_timeout_disable(uint32_t i2c_periph)
|
||||
{
|
||||
I2C_SAMCS(i2c_periph) &= ~(I2C_SAMCS_STOEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check I2C flag is set or not
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] flag: I2C flags, refer to i2c_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_FLAG_SBSEND: start condition sent out in master mode
|
||||
\arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode
|
||||
\arg I2C_FLAG_BTC: byte transmission finishes
|
||||
\arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode
|
||||
\arg I2C_FLAG_STPDET: stop condition detected in slave mode
|
||||
\arg I2C_FLAG_RBNE: I2C_DATA is not empty during receiving
|
||||
\arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting
|
||||
\arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus
|
||||
\arg I2C_FLAG_LOSTARB: arbitration lost in master mode
|
||||
\arg I2C_FLAG_AERR: acknowledge error
|
||||
\arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode
|
||||
\arg I2C_FLAG_PECERR: PEC error when receiving data
|
||||
\arg I2C_FLAG_SMBTO: timeout signal in SMBus mode
|
||||
\arg I2C_FLAG_SMBALT: SMBus alert status
|
||||
\arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode
|
||||
\arg I2C_FLAG_I2CBSY: busy flag
|
||||
\arg I2C_FLAG_TR: whether the I2C is a transmitter or a receiver
|
||||
\arg I2C_FLAG_RXGC: general call address (00h) received
|
||||
\arg I2C_FLAG_DEFSMB: default address of SMBus device
|
||||
\arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode
|
||||
\arg I2C_FLAG_DUMOD: dual flag in slave mode indicating which address is matched in dual-address mode
|
||||
\arg I2C_FLAG_TFF: txframe fall flag
|
||||
\arg I2C_FLAG_TFR: txframe rise flag
|
||||
\arg I2C_FLAG_RFF: rxframe fall flag
|
||||
\arg I2C_FLAG_RFR: rxframe rise flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag)
|
||||
{
|
||||
if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear I2C flag status
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] flag: I2C flags, refer to i2c_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_FLAG_SMBALT: SMBus alert status
|
||||
\arg I2C_FLAG_SMBTO: timeout signal in SMBus mode
|
||||
\arg I2C_FLAG_PECERR: PEC error when receiving data
|
||||
\arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode
|
||||
\arg I2C_FLAG_AERR: acknowledge error
|
||||
\arg I2C_FLAG_LOSTARB: arbitration lost in master mode
|
||||
\arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus
|
||||
\arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode
|
||||
\arg I2C_FLAG_TFF: txframe fall flag
|
||||
\arg I2C_FLAG_TFR: txframe rise flag
|
||||
\arg I2C_FLAG_RFF: rxframe fall flag
|
||||
\arg I2C_FLAG_RFR: rxframe rise flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag)
|
||||
{
|
||||
if(I2C_FLAG_ADDSEND == flag){
|
||||
/* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
|
||||
I2C_STAT0(i2c_periph);
|
||||
I2C_STAT1(i2c_periph);
|
||||
}else{
|
||||
I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable I2C interrupt
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_INT_ERR: error interrupt
|
||||
\arg I2C_INT_EV: event interrupt
|
||||
\arg I2C_INT_BUF: buffer interrupt
|
||||
\arg I2C_INT_TFF: txframe fall interrupt
|
||||
\arg I2C_INT_TFR: txframe rise interrupt
|
||||
\arg I2C_INT_RFF: rxframe fall interrupt
|
||||
\arg I2C_INT_RFR: rxframe rise interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
|
||||
{
|
||||
I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable I2C interrupt
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_INT_ERR: error interrupt
|
||||
\arg I2C_INT_EV: event interrupt
|
||||
\arg I2C_INT_BUF: buffer interrupt
|
||||
\arg I2C_INT_TFF: txframe fall interrupt
|
||||
\arg I2C_INT_TFR: txframe rise interrupt
|
||||
\arg I2C_INT_RFF: rxframe fall interrupt
|
||||
\arg I2C_INT_RFR: rxframe rise interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt)
|
||||
{
|
||||
I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get I2C interrupt flag status
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag
|
||||
\arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag
|
||||
\arg I2C_INT_FLAG_BTC: byte transmission finishes interrupt flag
|
||||
\arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag
|
||||
\arg I2C_INT_FLAG_STPDET: stop condition detected in slave mode interrupt flag
|
||||
\arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag
|
||||
\arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag
|
||||
\arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag
|
||||
\arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag
|
||||
\arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag
|
||||
\arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag
|
||||
\arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag
|
||||
\arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag
|
||||
\arg I2C_INT_FLAG_SMBALT: SMBus alert status interrupt flag
|
||||
\arg I2C_INT_FLAG_TFF: txframe fall interrupt flag
|
||||
\arg I2C_INT_FLAG_TFR: txframe rise interrupt flag
|
||||
\arg I2C_INT_FLAG_RFF: rxframe fall interrupt flag
|
||||
\arg I2C_INT_FLAG_RFR: rxframe rise interrupt flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag)
|
||||
{
|
||||
uint32_t intenable = 0U, flagstatus = 0U, bufie;
|
||||
|
||||
/* check BUFIE */
|
||||
bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE;
|
||||
|
||||
/* get the interrupt enable bit status */
|
||||
intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag)));
|
||||
/* get the corresponding flag bit status */
|
||||
flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag)));
|
||||
|
||||
if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)){
|
||||
if(intenable && bufie){
|
||||
intenable = 1U;
|
||||
}else{
|
||||
intenable = 0U;
|
||||
}
|
||||
}
|
||||
if((0U != flagstatus) && (0U != intenable)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear I2C interrupt flag status
|
||||
\param[in] i2c_periph: I2Cx(x=0,1)
|
||||
\param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag
|
||||
\arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag
|
||||
\arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag
|
||||
\arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag
|
||||
\arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag
|
||||
\arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag
|
||||
\arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag
|
||||
\arg I2C_INT_FLAG_SMBALT: SMBus alert status interrupt flag
|
||||
\arg I2C_INT_FLAG_TFF: txframe fall interrupt flag
|
||||
\arg I2C_INT_FLAG_TFR: txframe rise interrupt flag
|
||||
\arg I2C_INT_FLAG_RFF: rxframe fall interrupt flag
|
||||
\arg I2C_INT_FLAG_RFR: rxframe rise interrupt flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag)
|
||||
{
|
||||
if(I2C_INT_FLAG_ADDSEND == int_flag){
|
||||
/* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */
|
||||
I2C_STAT0(i2c_periph);
|
||||
I2C_STAT1(i2c_periph);
|
||||
}else{
|
||||
I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*!
|
||||
\file gd32c10x_it.c
|
||||
\brief interrupt service routines
|
||||
|
||||
\version 2025-09-30, V1.0.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x.h"
|
||||
#include "systick.h"
|
||||
|
||||
/*!
|
||||
\brief this function handles NMI exception
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void NMI_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this function handles HardFault exception
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
/* if Hard Fault exception occurs, go to infinite loop */
|
||||
while (1){
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this function handles MemManage exception
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void MemManage_Handler(void)
|
||||
{
|
||||
/* if Memory Manage exception occurs, go to infinite loop */
|
||||
while (1){
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this function handles BusFault exception
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void BusFault_Handler(void)
|
||||
{
|
||||
/* if Bus Fault exception occurs, go to infinite loop */
|
||||
while (1){
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this function handles UsageFault exception
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void UsageFault_Handler(void)
|
||||
{
|
||||
/* if Usage Fault exception occurs, go to infinite loop */
|
||||
while (1){
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this function handles SVC exception
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void SVC_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this function handles DebugMon exception
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void DebugMon_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this function handles PendSV exception
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void PendSV_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this function handles SysTick exception
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
delay_decrement();
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*!
|
||||
\file gd32c10x_misc.c
|
||||
\brief MISC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_misc.h"
|
||||
|
||||
/*!
|
||||
\brief set the priority group
|
||||
\param[in] nvic_prigroup: the NVIC priority group
|
||||
\arg NVIC_PRIGROUP_PRE0_SUB4: 0 bits for pre-emption priority, 4 bits for subpriority
|
||||
\arg NVIC_PRIGROUP_PRE1_SUB3: 1 bits for pre-emption priority, 3 bits for subpriority
|
||||
\arg NVIC_PRIGROUP_PRE2_SUB2: 2 bits for pre-emption priority, 2 bits for subpriority
|
||||
\arg NVIC_PRIGROUP_PRE3_SUB1: 3 bits for pre-emption priority, 1 bits for subpriority
|
||||
\arg NVIC_PRIGROUP_PRE4_SUB0: 4 bits for pre-emption priority, 0 bits for subpriority
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void nvic_priority_group_set(uint32_t nvic_prigroup)
|
||||
{
|
||||
/* set the priority group value */
|
||||
SCB->AIRCR = NVIC_AIRCR_VECTKEY_MASK | nvic_prigroup;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable NVIC interrupt request
|
||||
\param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type
|
||||
\param[in] nvic_irq_pre_priority: the pre-emption priority needed to set
|
||||
\param[in] nvic_irq_sub_priority: the subpriority needed to set
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
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;
|
||||
|
||||
/* use the priority group value to get the temp_pre and the temp_sub */
|
||||
switch((SCB->AIRCR) & (uint32_t)0x700U) {
|
||||
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;
|
||||
|
||||
/* enable the selected IRQ */
|
||||
NVIC->ISER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable NVIC interrupt request
|
||||
\param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set the NVIC vector table base address
|
||||
\param[in] nvic_vict_tab: the RAM or FLASH base address
|
||||
\arg NVIC_VECTTAB_RAM: RAM base address
|
||||
\are NVIC_VECTTAB_FLASH: Flash base address
|
||||
\param[in] offset: vector table offset
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset)
|
||||
{
|
||||
SCB->VTOR = nvic_vict_tab | (offset & NVIC_VECTTAB_OFFSET_MASK);
|
||||
__DSB();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set the state of the low power mode
|
||||
\param[in] lowpower_mode: the low power mode state
|
||||
\arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power
|
||||
mode by exiting from ISR
|
||||
\arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the DEEPSLEEP mode
|
||||
\arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the low power mode can be woke up
|
||||
by all the enable and disable interrupts
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void system_lowpower_set(uint8_t lowpower_mode)
|
||||
{
|
||||
SCB->SCR |= (uint32_t)lowpower_mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset the state of the low power mode
|
||||
\param[in] lowpower_mode: the low power mode state
|
||||
\arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power
|
||||
mode by exiting from ISR
|
||||
\arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the SLEEP mode
|
||||
\arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the low power mode only can be
|
||||
woke up by the enable interrupts
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void system_lowpower_reset(uint8_t lowpower_mode)
|
||||
{
|
||||
SCB->SCR &= (~(uint32_t)lowpower_mode);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set the systick clock source
|
||||
\param[in] systick_clksource: the systick clock source needed to choose
|
||||
\arg SYSTICK_CLKSOURCE_HCLK: systick clock source is from HCLK
|
||||
\arg SYSTICK_CLKSOURCE_HCLK_DIV8: systick clock source is from HCLK/8
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
|
||||
void systick_clksource_set(uint32_t systick_clksource)
|
||||
{
|
||||
if(SYSTICK_CLKSOURCE_HCLK == systick_clksource) {
|
||||
/* set the systick clock source from HCLK */
|
||||
SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK;
|
||||
} else {
|
||||
/* set the systick clock source from HCLK/8 */
|
||||
SysTick->CTRL &= SYSTICK_CLKSOURCE_HCLK_DIV8;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*!
|
||||
\file gd32c10x_misc.c
|
||||
\brief MISC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_misc.h"
|
||||
|
||||
/*!
|
||||
\brief set the priority group
|
||||
\param[in] nvic_prigroup: the NVIC priority group
|
||||
\arg NVIC_PRIGROUP_PRE0_SUB4: 0 bits for pre-emption priority, 4 bits for subpriority
|
||||
\arg NVIC_PRIGROUP_PRE1_SUB3: 1 bits for pre-emption priority, 3 bits for subpriority
|
||||
\arg NVIC_PRIGROUP_PRE2_SUB2: 2 bits for pre-emption priority, 2 bits for subpriority
|
||||
\arg NVIC_PRIGROUP_PRE3_SUB1: 3 bits for pre-emption priority, 1 bits for subpriority
|
||||
\arg NVIC_PRIGROUP_PRE4_SUB0: 4 bits for pre-emption priority, 0 bits for subpriority
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void nvic_priority_group_set(uint32_t nvic_prigroup)
|
||||
{
|
||||
/* set the priority group value */
|
||||
SCB->AIRCR = NVIC_AIRCR_VECTKEY_MASK | nvic_prigroup;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable NVIC interrupt request
|
||||
\param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type
|
||||
\param[in] nvic_irq_pre_priority: the pre-emption priority needed to set
|
||||
\param[in] nvic_irq_sub_priority: the subpriority needed to set
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
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;
|
||||
|
||||
/* use the priority group value to get the temp_pre and the temp_sub */
|
||||
switch((SCB->AIRCR) & (uint32_t)0x700U) {
|
||||
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;
|
||||
|
||||
/* enable the selected IRQ */
|
||||
NVIC->ISER[nvic_irq >> 0x05U] = (uint32_t)0x01U << (nvic_irq & (uint8_t)0x1FU);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable NVIC interrupt request
|
||||
\param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set the NVIC vector table base address
|
||||
\param[in] nvic_vict_tab: the RAM or FLASH base address
|
||||
\arg NVIC_VECTTAB_RAM: RAM base address
|
||||
\are NVIC_VECTTAB_FLASH: Flash base address
|
||||
\param[in] offset: vector table offset
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset)
|
||||
{
|
||||
SCB->VTOR = nvic_vict_tab | (offset & NVIC_VECTTAB_OFFSET_MASK);
|
||||
__DSB();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set the state of the low power mode
|
||||
\param[in] lowpower_mode: the low power mode state
|
||||
\arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power
|
||||
mode by exiting from ISR
|
||||
\arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the DEEPSLEEP mode
|
||||
\arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the low power mode can be woke up
|
||||
by all the enable and disable interrupts
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void system_lowpower_set(uint8_t lowpower_mode)
|
||||
{
|
||||
SCB->SCR |= (uint32_t)lowpower_mode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief reset the state of the low power mode
|
||||
\param[in] lowpower_mode: the low power mode state
|
||||
\arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power
|
||||
mode by exiting from ISR
|
||||
\arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the SLEEP mode
|
||||
\arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the low power mode only can be
|
||||
woke up by the enable interrupts
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void system_lowpower_reset(uint8_t lowpower_mode)
|
||||
{
|
||||
SCB->SCR &= (~(uint32_t)lowpower_mode);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set the systick clock source
|
||||
\param[in] systick_clksource: the systick clock source needed to choose
|
||||
\arg SYSTICK_CLKSOURCE_HCLK: systick clock source is from HCLK
|
||||
\arg SYSTICK_CLKSOURCE_HCLK_DIV8: systick clock source is from HCLK/8
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
|
||||
void systick_clksource_set(uint32_t systick_clksource)
|
||||
{
|
||||
if(SYSTICK_CLKSOURCE_HCLK == systick_clksource) {
|
||||
/* set the systick clock source from HCLK */
|
||||
SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK;
|
||||
} else {
|
||||
/* set the systick clock source from HCLK/8 */
|
||||
SysTick->CTRL &= SYSTICK_CLKSOURCE_HCLK_DIV8;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
/*!
|
||||
\file gd32c10x_pmu.c
|
||||
\brief PMU driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_pmu.h"
|
||||
|
||||
/*!
|
||||
\brief reset PMU register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_deinit(void)
|
||||
{
|
||||
/* reset PMU */
|
||||
rcu_periph_reset_enable(RCU_PMURST);
|
||||
rcu_periph_reset_disable(RCU_PMURST);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select low voltage detector threshold
|
||||
\param[in] lvdt_n:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LVDT_0: voltage threshold is 2.1V
|
||||
\arg PMU_LVDT_1: voltage threshold is 2.3V
|
||||
\arg PMU_LVDT_2: voltage threshold is 2.4V
|
||||
\arg PMU_LVDT_3: voltage threshold is 2.6V
|
||||
\arg PMU_LVDT_4: voltage threshold is 2.7V
|
||||
\arg PMU_LVDT_5: voltage threshold is 2.9V
|
||||
\arg PMU_LVDT_6: voltage threshold is 3.0V
|
||||
\arg PMU_LVDT_7: voltage threshold is 3.1V
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_lvd_select(uint32_t lvdt_n)
|
||||
{
|
||||
/* disable LVD */
|
||||
PMU_CTL &= ~PMU_CTL_LVDEN;
|
||||
/* clear LVDT bits */
|
||||
PMU_CTL &= ~PMU_CTL_LVDT;
|
||||
/* set LVDT bits according to lvdt_n */
|
||||
PMU_CTL |= lvdt_n;
|
||||
/* enable LVD */
|
||||
PMU_CTL |= PMU_CTL_LVDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select LDO output voltage
|
||||
this bit set by software when the main PLL closed, before closing PLL, change the system clock to IRC16M or HXTAL
|
||||
\param[in] ldo_output:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LDOVS_LOW: LDO output voltage select low mode
|
||||
\arg PMU_LDOVS_NORMAL: LDO output voltage select normal mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_ldo_output_select(uint32_t ldo_output)
|
||||
{
|
||||
PMU_CTL &= ~PMU_CTL_LDOVS;
|
||||
PMU_CTL |= ldo_output;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable PMU lvd
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_lvd_disable(void)
|
||||
{
|
||||
/* disable LVD */
|
||||
PMU_CTL &= ~PMU_CTL_LVDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief PMU work at sleep mode
|
||||
\param[in] sleepmodecmd:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WFI_CMD: use WFI command
|
||||
\arg WFE_CMD: use WFE command
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_sleepmode(uint8_t sleepmodecmd)
|
||||
{
|
||||
/* clear sleepdeep bit of Cortex-M4 system control register */
|
||||
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
|
||||
/* select WFI or WFE command to enter sleep mode */
|
||||
if(WFI_CMD == sleepmodecmd){
|
||||
__WFI();
|
||||
}else{
|
||||
__SEV();
|
||||
__WFE();
|
||||
__WFE();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief PMU work at deepsleep mode
|
||||
\param[in] ldo:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LDO_NORMAL: LDO work at normal power mode when pmu enter deepsleep mode
|
||||
\arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode
|
||||
\param[in] deepsleepmodecmd:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WFI_CMD: use WFI command
|
||||
\arg WFE_CMD: use WFE command
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd)
|
||||
{
|
||||
static uint32_t reg_snap[4];
|
||||
/* clear stbmod and ldolp bits */
|
||||
PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP));
|
||||
|
||||
/* set ldolp bit according to pmu_ldo */
|
||||
PMU_CTL |= ldo;
|
||||
|
||||
/* set sleepdeep bit of Cortex-M4 system control register */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
reg_snap[0] = REG32(0xE000E010U);
|
||||
reg_snap[1] = REG32(0xE000E100U);
|
||||
reg_snap[2] = REG32(0xE000E104U);
|
||||
reg_snap[3] = REG32(0xE000E108U);
|
||||
|
||||
REG32(0xE000E010U) &= 0x00010004U;
|
||||
REG32(0xE000E180U) = 0XFF7FF83DU;
|
||||
REG32(0xE000E184U) = 0XFFFFF8FFU;
|
||||
REG32(0xE000E188U) = 0xFFFFFFFFU;
|
||||
|
||||
/* select WFI or WFE command to enter deepsleep mode */
|
||||
if(WFI_CMD == deepsleepmodecmd){
|
||||
__WFI();
|
||||
}else{
|
||||
__SEV();
|
||||
__WFE();
|
||||
__WFE();
|
||||
}
|
||||
|
||||
REG32(0xE000E010U) = reg_snap[0];
|
||||
REG32(0xE000E100U) = reg_snap[1];
|
||||
REG32(0xE000E104U) = reg_snap[2];
|
||||
REG32(0xE000E108U) = reg_snap[3];
|
||||
|
||||
/* reset sleepdeep bit of Cortex-M4 system control register */
|
||||
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief pmu work at standby mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_standbymode(void)
|
||||
{
|
||||
/* set stbmod bit */
|
||||
PMU_CTL |= PMU_CTL_STBMOD;
|
||||
|
||||
/* reset wakeup flag */
|
||||
PMU_CTL |= PMU_CTL_WURST;
|
||||
|
||||
/* set sleepdeep bit of Cortex-M4 system control register */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
REG32(0xE000E010U) &= 0x00010004U;
|
||||
REG32(0xE000E180U) = 0XFFFFFFF7U;
|
||||
REG32(0xE000E184U) = 0XFFFFFDFFU;
|
||||
REG32(0xE000E188U) = 0xFFFFFFFFU;
|
||||
|
||||
/* select WFI or WFE command to enter standby mode */
|
||||
__WFI();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable wakeup pin
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_wakeup_pin_enable(void)
|
||||
{
|
||||
PMU_CS |= PMU_CS_WUPEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable wakeup pin
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_wakeup_pin_disable(void)
|
||||
{
|
||||
PMU_CS &= ~PMU_CS_WUPEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable write access to the registers in backup domain
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_backup_write_enable(void)
|
||||
{
|
||||
PMU_CTL |= PMU_CTL_BKPWEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable write access to the registers in backup domain
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_backup_write_disable(void)
|
||||
{
|
||||
PMU_CTL &= ~PMU_CTL_BKPWEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get flag state
|
||||
\param[in] flag:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_FLAG_WAKEUP: wakeup flag
|
||||
\arg PMU_FLAG_STANDBY: standby flag
|
||||
\arg PMU_FLAG_LVD: lvd flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus pmu_flag_get(uint32_t flag)
|
||||
{
|
||||
if(RESET != (PMU_CS & flag)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear flag bit
|
||||
\param[in] flag:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag
|
||||
\arg PMU_FLAG_RESET_STANDBY: reset standby flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_flag_clear(uint32_t flag)
|
||||
{
|
||||
switch(flag){
|
||||
case PMU_FLAG_RESET_WAKEUP:
|
||||
/* reset wakeup flag */
|
||||
PMU_CTL |= PMU_CTL_WURST;
|
||||
break;
|
||||
case PMU_FLAG_RESET_STANDBY:
|
||||
/* reset standby flag */
|
||||
PMU_CTL |= PMU_CTL_STBRST;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
/*!
|
||||
\file gd32c10x_pmu.c
|
||||
\brief PMU driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_pmu.h"
|
||||
|
||||
/*!
|
||||
\brief reset PMU register
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_deinit(void)
|
||||
{
|
||||
/* reset PMU */
|
||||
rcu_periph_reset_enable(RCU_PMURST);
|
||||
rcu_periph_reset_disable(RCU_PMURST);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select low voltage detector threshold
|
||||
\param[in] lvdt_n:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LVDT_0: voltage threshold is 2.1V
|
||||
\arg PMU_LVDT_1: voltage threshold is 2.3V
|
||||
\arg PMU_LVDT_2: voltage threshold is 2.4V
|
||||
\arg PMU_LVDT_3: voltage threshold is 2.6V
|
||||
\arg PMU_LVDT_4: voltage threshold is 2.7V
|
||||
\arg PMU_LVDT_5: voltage threshold is 2.9V
|
||||
\arg PMU_LVDT_6: voltage threshold is 3.0V
|
||||
\arg PMU_LVDT_7: voltage threshold is 3.1V
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_lvd_select(uint32_t lvdt_n)
|
||||
{
|
||||
/* disable LVD */
|
||||
PMU_CTL &= ~PMU_CTL_LVDEN;
|
||||
/* clear LVDT bits */
|
||||
PMU_CTL &= ~PMU_CTL_LVDT;
|
||||
/* set LVDT bits according to lvdt_n */
|
||||
PMU_CTL |= lvdt_n;
|
||||
/* enable LVD */
|
||||
PMU_CTL |= PMU_CTL_LVDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief select LDO output voltage
|
||||
this bit set by software when the main PLL closed, before closing PLL, change the system clock to IRC16M or HXTAL
|
||||
\param[in] ldo_output:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LDOVS_LOW: LDO output voltage select low mode
|
||||
\arg PMU_LDOVS_NORMAL: LDO output voltage select normal mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_ldo_output_select(uint32_t ldo_output)
|
||||
{
|
||||
PMU_CTL &= ~PMU_CTL_LDOVS;
|
||||
PMU_CTL |= ldo_output;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable PMU lvd
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_lvd_disable(void)
|
||||
{
|
||||
/* disable LVD */
|
||||
PMU_CTL &= ~PMU_CTL_LVDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief PMU work at sleep mode
|
||||
\param[in] sleepmodecmd:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WFI_CMD: use WFI command
|
||||
\arg WFE_CMD: use WFE command
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_sleepmode(uint8_t sleepmodecmd)
|
||||
{
|
||||
/* clear sleepdeep bit of Cortex-M4 system control register */
|
||||
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
|
||||
/* select WFI or WFE command to enter sleep mode */
|
||||
if(WFI_CMD == sleepmodecmd){
|
||||
__WFI();
|
||||
}else{
|
||||
__SEV();
|
||||
__WFE();
|
||||
__WFE();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief PMU work at deepsleep mode
|
||||
\param[in] ldo:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_LDO_NORMAL: LDO work at normal power mode when pmu enter deepsleep mode
|
||||
\arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode
|
||||
\param[in] deepsleepmodecmd:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WFI_CMD: use WFI command
|
||||
\arg WFE_CMD: use WFE command
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd)
|
||||
{
|
||||
static uint32_t reg_snap[4];
|
||||
/* clear stbmod and ldolp bits */
|
||||
PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP));
|
||||
|
||||
/* set ldolp bit according to pmu_ldo */
|
||||
PMU_CTL |= ldo;
|
||||
|
||||
/* set sleepdeep bit of Cortex-M4 system control register */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
reg_snap[0] = REG32(0xE000E010U);
|
||||
reg_snap[1] = REG32(0xE000E100U);
|
||||
reg_snap[2] = REG32(0xE000E104U);
|
||||
reg_snap[3] = REG32(0xE000E108U);
|
||||
|
||||
REG32(0xE000E010U) &= 0x00010004U;
|
||||
REG32(0xE000E180U) = 0XFF7FF83DU;
|
||||
REG32(0xE000E184U) = 0XFFFFF8FFU;
|
||||
REG32(0xE000E188U) = 0xFFFFFFFFU;
|
||||
|
||||
/* select WFI or WFE command to enter deepsleep mode */
|
||||
if(WFI_CMD == deepsleepmodecmd){
|
||||
__WFI();
|
||||
}else{
|
||||
__SEV();
|
||||
__WFE();
|
||||
__WFE();
|
||||
}
|
||||
|
||||
REG32(0xE000E010U) = reg_snap[0];
|
||||
REG32(0xE000E100U) = reg_snap[1];
|
||||
REG32(0xE000E104U) = reg_snap[2];
|
||||
REG32(0xE000E108U) = reg_snap[3];
|
||||
|
||||
/* reset sleepdeep bit of Cortex-M4 system control register */
|
||||
SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief pmu work at standby mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_to_standbymode(void)
|
||||
{
|
||||
/* set stbmod bit */
|
||||
PMU_CTL |= PMU_CTL_STBMOD;
|
||||
|
||||
/* reset wakeup flag */
|
||||
PMU_CTL |= PMU_CTL_WURST;
|
||||
|
||||
/* set sleepdeep bit of Cortex-M4 system control register */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
|
||||
REG32(0xE000E010U) &= 0x00010004U;
|
||||
REG32(0xE000E180U) = 0XFFFFFFF7U;
|
||||
REG32(0xE000E184U) = 0XFFFFFDFFU;
|
||||
REG32(0xE000E188U) = 0xFFFFFFFFU;
|
||||
|
||||
/* select WFI or WFE command to enter standby mode */
|
||||
__WFI();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable wakeup pin
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_wakeup_pin_enable(void)
|
||||
{
|
||||
PMU_CS |= PMU_CS_WUPEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable wakeup pin
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_wakeup_pin_disable(void)
|
||||
{
|
||||
PMU_CS &= ~PMU_CS_WUPEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable write access to the registers in backup domain
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_backup_write_enable(void)
|
||||
{
|
||||
PMU_CTL |= PMU_CTL_BKPWEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable write access to the registers in backup domain
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_backup_write_disable(void)
|
||||
{
|
||||
PMU_CTL &= ~PMU_CTL_BKPWEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get flag state
|
||||
\param[in] flag:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_FLAG_WAKEUP: wakeup flag
|
||||
\arg PMU_FLAG_STANDBY: standby flag
|
||||
\arg PMU_FLAG_LVD: lvd flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus pmu_flag_get(uint32_t flag)
|
||||
{
|
||||
if(RESET != (PMU_CS & flag)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear flag bit
|
||||
\param[in] flag:
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag
|
||||
\arg PMU_FLAG_RESET_STANDBY: reset standby flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void pmu_flag_clear(uint32_t flag)
|
||||
{
|
||||
switch(flag){
|
||||
case PMU_FLAG_RESET_WAKEUP:
|
||||
/* reset wakeup flag */
|
||||
PMU_CTL |= PMU_CTL_WURST;
|
||||
break;
|
||||
case PMU_FLAG_RESET_STANDBY:
|
||||
/* reset standby flag */
|
||||
PMU_CTL |= PMU_CTL_STBRST;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,281 @@
|
||||
/*!
|
||||
\file gd32c10x_rtc.c
|
||||
\brief RTC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_rtc.h"
|
||||
|
||||
/* RTC register high / low bits mask */
|
||||
#define RTC_HIGH_BITS_MASK ((uint32_t)0x000F0000U) /* RTC high bits mask */
|
||||
#define RTC_LOW_BITS_MASK ((uint32_t)0x0000FFFFU) /* RTC low bits mask */
|
||||
|
||||
/* RTC register high bits offset */
|
||||
#define RTC_HIGH_BITS_OFFSET ((uint32_t)16U)
|
||||
|
||||
/*!
|
||||
\brief enter RTC configuration mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_configuration_mode_enter(void)
|
||||
{
|
||||
RTC_CTL |= RTC_CTL_CMF;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief exit RTC configuration mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_configuration_mode_exit(void)
|
||||
{
|
||||
RTC_CTL &= ~RTC_CTL_CMF;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set RTC counter value
|
||||
\param[in] cnt: RTC counter value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_counter_set(uint32_t cnt)
|
||||
{
|
||||
rtc_configuration_mode_enter();
|
||||
/* set the RTC counter high bits */
|
||||
RTC_CNTH = (cnt >> RTC_HIGH_BITS_OFFSET);
|
||||
/* set the RTC counter low bits */
|
||||
RTC_CNTL = (cnt & RTC_LOW_BITS_MASK);
|
||||
rtc_configuration_mode_exit();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set RTC prescaler value
|
||||
\param[in] psc: RTC prescaler value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_prescaler_set(uint32_t psc)
|
||||
{
|
||||
rtc_configuration_mode_enter();
|
||||
/* set the RTC prescaler high bits */
|
||||
RTC_PSCH = ((psc & RTC_HIGH_BITS_MASK) >> RTC_HIGH_BITS_OFFSET);
|
||||
/* set the RTC prescaler low bits */
|
||||
RTC_PSCL = (psc & RTC_LOW_BITS_MASK);
|
||||
rtc_configuration_mode_exit();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief wait RTC last write operation finished flag set
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_lwoff_wait(void)
|
||||
{
|
||||
/* loop until LWOFF flag is set */
|
||||
while(RESET == (RTC_CTL & RTC_CTL_LWOFF)){
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief wait RTC registers synchronized flag set
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_register_sync_wait(void)
|
||||
{
|
||||
/* clear RSYNF flag */
|
||||
RTC_CTL &= ~RTC_CTL_RSYNF;
|
||||
/* loop until RSYNF flag is set */
|
||||
while(RESET == (RTC_CTL & RTC_CTL_RSYNF)){
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set RTC alarm value
|
||||
\param[in] alarm: RTC alarm value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_alarm_config(uint32_t alarm)
|
||||
{
|
||||
rtc_configuration_mode_enter();
|
||||
/* set the alarm high bits */
|
||||
RTC_ALRMH = (alarm >> RTC_HIGH_BITS_OFFSET);
|
||||
/* set the alarm low bits */
|
||||
RTC_ALRML = (alarm & RTC_LOW_BITS_MASK);
|
||||
rtc_configuration_mode_exit();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get RTC counter value
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval RTC counter value
|
||||
*/
|
||||
uint32_t rtc_counter_get(void)
|
||||
{
|
||||
uint32_t temp = 0x0U, high_old, high_new;
|
||||
|
||||
high_old = RTC_CNTH;
|
||||
temp = RTC_CNTL;
|
||||
high_new = RTC_CNTH;
|
||||
|
||||
if(high_old != high_new){
|
||||
temp = (high_new << RTC_HIGH_BITS_OFFSET) | RTC_CNTL;
|
||||
}else{
|
||||
temp |= (high_new << RTC_HIGH_BITS_OFFSET);
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get RTC divider value
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval RTC divider value
|
||||
*/
|
||||
uint32_t rtc_divider_get(void)
|
||||
{
|
||||
uint32_t temp = 0x00U;
|
||||
|
||||
temp = ((RTC_DIVH & RTC_DIVH_DIV) << RTC_HIGH_BITS_OFFSET);
|
||||
temp |= RTC_DIVL;
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get RTC flag status
|
||||
\param[in] flag: specify which flag status to get
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg RTC_FLAG_SECOND: second interrupt flag
|
||||
\arg RTC_FLAG_ALARM: alarm interrupt flag
|
||||
\arg RTC_FLAG_OVERFLOW: overflow interrupt flag
|
||||
\arg RTC_FLAG_RSYN: registers synchronized flag
|
||||
\arg RTC_FLAG_LWOF: last write operation finished flag
|
||||
\param[out] none
|
||||
\retval SET or RESET
|
||||
*/
|
||||
FlagStatus rtc_flag_get(uint32_t flag)
|
||||
{
|
||||
if(RESET != (RTC_CTL & flag)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear RTC flag status
|
||||
\param[in] flag: specify which flag status to clear
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg RTC_FLAG_SECOND: second interrupt flag
|
||||
\arg RTC_FLAG_ALARM: alarm interrupt flag
|
||||
\arg RTC_FLAG_OVERFLOW: overflow interrupt flag
|
||||
\arg RTC_FLAG_RSYN: registers synchronized flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_flag_clear(uint32_t flag)
|
||||
{
|
||||
/* clear RTC flag */
|
||||
RTC_CTL &= ~flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get RTC interrupt flag status
|
||||
\param[in] flag: specify which flag status to get
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg RTC_INT_FLAG_SECOND: second interrupt flag
|
||||
\arg RTC_INT_FLAG_ALARM: alarm interrupt flag
|
||||
\arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag
|
||||
\param[out] none
|
||||
\retval SET or RESET
|
||||
*/
|
||||
FlagStatus rtc_interrupt_flag_get(uint32_t flag)
|
||||
{
|
||||
if(RESET != (RTC_CTL & flag)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear RTC interrupt flag status
|
||||
\param[in] flag: specify which flag status to clear
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg RTC_INT_FLAG_SECOND: second interrupt flag
|
||||
\arg RTC_INT_FLAG_ALARM: alarm interrupt flag
|
||||
\arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_interrupt_flag_clear(uint32_t flag)
|
||||
{
|
||||
/* clear RTC interrupt flag */
|
||||
RTC_CTL &= ~flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable RTC interrupt
|
||||
\param[in] interrupt: specify which interrupt to enable
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg RTC_INT_SECOND: second interrupt
|
||||
\arg RTC_INT_ALARM: alarm interrupt
|
||||
\arg RTC_INT_OVERFLOW: overflow interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_interrupt_enable(uint32_t interrupt)
|
||||
{
|
||||
RTC_INTEN |= interrupt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable RTC interrupt
|
||||
\param[in] interrupt: specify which interrupt to disable
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg RTC_INT_SECOND: second interrupt
|
||||
\arg RTC_INT_ALARM: alarm interrupt
|
||||
\arg RTC_INT_OVERFLOW: overflow interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_interrupt_disable(uint32_t interrupt)
|
||||
{
|
||||
RTC_INTEN &= ~interrupt;
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
/*!
|
||||
\file gd32c10x_rtc.c
|
||||
\brief RTC driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_rtc.h"
|
||||
|
||||
/* RTC register high / low bits mask */
|
||||
#define RTC_HIGH_BITS_MASK ((uint32_t)0x000F0000U) /* RTC high bits mask */
|
||||
#define RTC_LOW_BITS_MASK ((uint32_t)0x0000FFFFU) /* RTC low bits mask */
|
||||
|
||||
/* RTC register high bits offset */
|
||||
#define RTC_HIGH_BITS_OFFSET ((uint32_t)16U)
|
||||
|
||||
/*!
|
||||
\brief enter RTC configuration mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_configuration_mode_enter(void)
|
||||
{
|
||||
RTC_CTL |= RTC_CTL_CMF;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief exit RTC configuration mode
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_configuration_mode_exit(void)
|
||||
{
|
||||
RTC_CTL &= ~RTC_CTL_CMF;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set RTC counter value
|
||||
\param[in] cnt: RTC counter value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_counter_set(uint32_t cnt)
|
||||
{
|
||||
rtc_configuration_mode_enter();
|
||||
/* set the RTC counter high bits */
|
||||
RTC_CNTH = (cnt >> RTC_HIGH_BITS_OFFSET);
|
||||
/* set the RTC counter low bits */
|
||||
RTC_CNTL = (cnt & RTC_LOW_BITS_MASK);
|
||||
rtc_configuration_mode_exit();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set RTC prescaler value
|
||||
\param[in] psc: RTC prescaler value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_prescaler_set(uint32_t psc)
|
||||
{
|
||||
rtc_configuration_mode_enter();
|
||||
/* set the RTC prescaler high bits */
|
||||
RTC_PSCH = ((psc & RTC_HIGH_BITS_MASK) >> RTC_HIGH_BITS_OFFSET);
|
||||
/* set the RTC prescaler low bits */
|
||||
RTC_PSCL = (psc & RTC_LOW_BITS_MASK);
|
||||
rtc_configuration_mode_exit();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief wait RTC last write operation finished flag set
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_lwoff_wait(void)
|
||||
{
|
||||
/* loop until LWOFF flag is set */
|
||||
while(RESET == (RTC_CTL & RTC_CTL_LWOFF)){
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief wait RTC registers synchronized flag set
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_register_sync_wait(void)
|
||||
{
|
||||
/* clear RSYNF flag */
|
||||
RTC_CTL &= ~RTC_CTL_RSYNF;
|
||||
/* loop until RSYNF flag is set */
|
||||
while(RESET == (RTC_CTL & RTC_CTL_RSYNF)){
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set RTC alarm value
|
||||
\param[in] alarm: RTC alarm value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_alarm_config(uint32_t alarm)
|
||||
{
|
||||
rtc_configuration_mode_enter();
|
||||
/* set the alarm high bits */
|
||||
RTC_ALRMH = (alarm >> RTC_HIGH_BITS_OFFSET);
|
||||
/* set the alarm low bits */
|
||||
RTC_ALRML = (alarm & RTC_LOW_BITS_MASK);
|
||||
rtc_configuration_mode_exit();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get RTC counter value
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval RTC counter value
|
||||
*/
|
||||
uint32_t rtc_counter_get(void)
|
||||
{
|
||||
uint32_t temp = 0x0U, high_old, high_new;
|
||||
|
||||
high_old = RTC_CNTH;
|
||||
temp = RTC_CNTL;
|
||||
high_new = RTC_CNTH;
|
||||
|
||||
if(high_old != high_new){
|
||||
temp = (high_new << RTC_HIGH_BITS_OFFSET) | RTC_CNTL;
|
||||
}else{
|
||||
temp |= (high_new << RTC_HIGH_BITS_OFFSET);
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get RTC divider value
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval RTC divider value
|
||||
*/
|
||||
uint32_t rtc_divider_get(void)
|
||||
{
|
||||
uint32_t temp = 0x00U;
|
||||
|
||||
temp = ((RTC_DIVH & RTC_DIVH_DIV) << RTC_HIGH_BITS_OFFSET);
|
||||
temp |= RTC_DIVL;
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get RTC flag status
|
||||
\param[in] flag: specify which flag status to get
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg RTC_FLAG_SECOND: second interrupt flag
|
||||
\arg RTC_FLAG_ALARM: alarm interrupt flag
|
||||
\arg RTC_FLAG_OVERFLOW: overflow interrupt flag
|
||||
\arg RTC_FLAG_RSYN: registers synchronized flag
|
||||
\arg RTC_FLAG_LWOF: last write operation finished flag
|
||||
\param[out] none
|
||||
\retval SET or RESET
|
||||
*/
|
||||
FlagStatus rtc_flag_get(uint32_t flag)
|
||||
{
|
||||
if(RESET != (RTC_CTL & flag)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear RTC flag status
|
||||
\param[in] flag: specify which flag status to clear
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg RTC_FLAG_SECOND: second interrupt flag
|
||||
\arg RTC_FLAG_ALARM: alarm interrupt flag
|
||||
\arg RTC_FLAG_OVERFLOW: overflow interrupt flag
|
||||
\arg RTC_FLAG_RSYN: registers synchronized flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_flag_clear(uint32_t flag)
|
||||
{
|
||||
/* clear RTC flag */
|
||||
RTC_CTL &= ~flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get RTC interrupt flag status
|
||||
\param[in] flag: specify which flag status to get
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg RTC_INT_FLAG_SECOND: second interrupt flag
|
||||
\arg RTC_INT_FLAG_ALARM: alarm interrupt flag
|
||||
\arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag
|
||||
\param[out] none
|
||||
\retval SET or RESET
|
||||
*/
|
||||
FlagStatus rtc_interrupt_flag_get(uint32_t flag)
|
||||
{
|
||||
if(RESET != (RTC_CTL & flag)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear RTC interrupt flag status
|
||||
\param[in] flag: specify which flag status to clear
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg RTC_INT_FLAG_SECOND: second interrupt flag
|
||||
\arg RTC_INT_FLAG_ALARM: alarm interrupt flag
|
||||
\arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_interrupt_flag_clear(uint32_t flag)
|
||||
{
|
||||
/* clear RTC interrupt flag */
|
||||
RTC_CTL &= ~flag;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable RTC interrupt
|
||||
\param[in] interrupt: specify which interrupt to enable
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg RTC_INT_SECOND: second interrupt
|
||||
\arg RTC_INT_ALARM: alarm interrupt
|
||||
\arg RTC_INT_OVERFLOW: overflow interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_interrupt_enable(uint32_t interrupt)
|
||||
{
|
||||
RTC_INTEN |= interrupt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable RTC interrupt
|
||||
\param[in] interrupt: specify which interrupt to disable
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg RTC_INT_SECOND: second interrupt
|
||||
\arg RTC_INT_ALARM: alarm interrupt
|
||||
\arg RTC_INT_OVERFLOW: overflow interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rtc_interrupt_disable(uint32_t interrupt)
|
||||
{
|
||||
RTC_INTEN &= ~interrupt;
|
||||
}
|
||||
@@ -0,0 +1,855 @@
|
||||
/*!
|
||||
\file gd32c10x_spi.c
|
||||
\brief SPI driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_spi.h"
|
||||
|
||||
#define SPI_ERROR_HANDLE(s) do{}while(1)
|
||||
|
||||
/* SPI/I2S parameter initialization mask */
|
||||
#define SPI_INIT_MASK ((uint32_t)0x00003040U) /* SPI parameter initialization mask */
|
||||
#define I2S_INIT_MASK ((uint32_t)0x0000F047U) /* I2S parameter initialization mask */
|
||||
|
||||
/* I2S clock source selection, multiplication and division mask */
|
||||
#define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /* I2S1 clock source selection */
|
||||
#define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /* I2S2 clock source selection */
|
||||
#define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /* I2S clock multiplication mask */
|
||||
#define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /* I2S clock division mask */
|
||||
|
||||
/* default value and offset */
|
||||
#define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /* default value of SPI_I2SPSC register */
|
||||
#define RCU_CFG1_PREDV1_OFFSET 4U /* PREDV1 offset in RCU_CFG1 */
|
||||
#define RCU_CFG1_PLL2MF_OFFSET 12U /* PLL2MF offset in RCU_CFG1 */
|
||||
|
||||
/*!
|
||||
\brief reset SPI and I2S
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_i2s_deinit(uint32_t spi_periph)
|
||||
{
|
||||
switch(spi_periph){
|
||||
case SPI0:
|
||||
/* reset SPI0 */
|
||||
rcu_periph_reset_enable(RCU_SPI0RST);
|
||||
rcu_periph_reset_disable(RCU_SPI0RST);
|
||||
break;
|
||||
case SPI1:
|
||||
/* reset SPI1 and I2S1 */
|
||||
rcu_periph_reset_enable(RCU_SPI1RST);
|
||||
rcu_periph_reset_disable(RCU_SPI1RST);
|
||||
break;
|
||||
case SPI2:
|
||||
/* reset SPI2 and I2S2 */
|
||||
rcu_periph_reset_enable(RCU_SPI2RST);
|
||||
rcu_periph_reset_disable(RCU_SPI2RST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize the parameters of SPI struct with the default values
|
||||
\param[in] spi_struct: SPI parameter struct
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_struct_para_init(spi_parameter_struct* spi_struct)
|
||||
{
|
||||
/* set the SPI struct with the default values */
|
||||
spi_struct->device_mode = SPI_SLAVE;
|
||||
spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX;
|
||||
spi_struct->frame_size = SPI_FRAMESIZE_8BIT;
|
||||
spi_struct->nss = SPI_NSS_HARD;
|
||||
spi_struct->endian = SPI_ENDIAN_MSB;
|
||||
spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
|
||||
spi_struct->prescale = SPI_PSC_2;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize SPI parameter
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] spi_struct: SPI parameter initialization stuct members of the structure
|
||||
and the member values are shown as below:
|
||||
device_mode: SPI_MASTER, SPI_SLAVE
|
||||
trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY,
|
||||
SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT
|
||||
frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT
|
||||
nss: SPI_NSS_SOFT, SPI_NSS_HARD
|
||||
endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB
|
||||
clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE
|
||||
SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE
|
||||
prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct)
|
||||
{
|
||||
uint32_t reg = 0U;
|
||||
reg = SPI_CTL0(spi_periph);
|
||||
reg &= SPI_INIT_MASK;
|
||||
|
||||
/* select SPI as master or slave */
|
||||
reg |= spi_struct->device_mode;
|
||||
/* select SPI transfer mode */
|
||||
reg |= spi_struct->trans_mode;
|
||||
/* select SPI frame size */
|
||||
reg |= spi_struct->frame_size;
|
||||
/* select SPI NSS use hardware or software */
|
||||
reg |= spi_struct->nss;
|
||||
/* select SPI LSB or MSB */
|
||||
reg |= spi_struct->endian;
|
||||
/* select SPI polarity and phase */
|
||||
reg |= spi_struct->clock_polarity_phase;
|
||||
/* select SPI prescale to adjust transmit speed */
|
||||
reg |= spi_struct->prescale;
|
||||
|
||||
/* write to SPI_CTL0 register */
|
||||
SPI_CTL0(spi_periph) = (uint32_t)reg;
|
||||
|
||||
SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize I2S parameter
|
||||
\param[in] spi_periph: SPIx(x=1,2)
|
||||
\param[in] mode: I2S operation mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2S_MODE_SLAVETX: I2S slave transmit mode
|
||||
\arg I2S_MODE_SLAVERX: I2S slave receive mode
|
||||
\arg I2S_MODE_MASTERTX: I2S master transmit mode
|
||||
\arg I2S_MODE_MASTERRX: I2S master receive mode
|
||||
\param[in] standard: I2S standard
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2S_STD_PHILIPS: I2S Philips standard
|
||||
\arg I2S_STD_MSB: I2S MSB standard
|
||||
\arg I2S_STD_LSB: I2S LSB standard
|
||||
\arg I2S_STD_PCMSHORT: I2S PCM short standard
|
||||
\arg I2S_STD_PCMLONG: I2S PCM long standard
|
||||
\param[in] ckpl: I2S idle state clock polarity
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2S_CKPL_LOW: I2S clock polarity low level
|
||||
\arg I2S_CKPL_HIGH: I2S clock polarity high level
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl)
|
||||
{
|
||||
uint32_t reg = 0U;
|
||||
reg = SPI_I2SCTL(spi_periph);
|
||||
reg &= I2S_INIT_MASK;
|
||||
|
||||
/* enable I2S mode */
|
||||
reg |= (uint32_t)SPI_I2SCTL_I2SSEL;
|
||||
/* select I2S mode */
|
||||
reg |= (uint32_t)mode;
|
||||
/* select I2S standard */
|
||||
reg |= (uint32_t)standard;
|
||||
/* select I2S polarity */
|
||||
reg |= (uint32_t)ckpl;
|
||||
|
||||
/* write to SPI_I2SCTL register */
|
||||
SPI_I2SCTL(spi_periph) = (uint32_t)reg;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2S prescaler
|
||||
\param[in] spi_periph: SPIx(x=1,2)
|
||||
\param[in] audiosample: I2S audio sample rate
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz
|
||||
\arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz
|
||||
\arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz
|
||||
\arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz
|
||||
\arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz
|
||||
\arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz
|
||||
\arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz
|
||||
\arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz
|
||||
\arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz
|
||||
\param[in] frameformat: I2S data length and channel length
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit
|
||||
\arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit
|
||||
\arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit
|
||||
\arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit
|
||||
\param[in] mckout: I2S master clock output
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2S_MCKOUT_ENABLE: I2S master clock output enable
|
||||
\arg I2S_MCKOUT_DISABLE: I2S master clock output disable
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout)
|
||||
{
|
||||
uint32_t i2sdiv = 2U, i2sof = 0U;
|
||||
uint32_t clks = 0U;
|
||||
uint32_t i2sclock = 0U;
|
||||
|
||||
/* judge whether the audiosample is 0 */
|
||||
if(0U == audiosample){
|
||||
SPI_ERROR_HANDLE("the parameter can not be 0 \r\n");
|
||||
}
|
||||
|
||||
/* deinit SPI_I2SPSC register */
|
||||
SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE;
|
||||
|
||||
/* get the I2S clock source */
|
||||
if(SPI1 == ((uint32_t)spi_periph)){
|
||||
/* I2S1 clock source selection */
|
||||
clks = I2S1_CLOCK_SEL;
|
||||
}else{
|
||||
/* I2S2 clock source selection */
|
||||
clks = I2S2_CLOCK_SEL;
|
||||
}
|
||||
|
||||
if(0U != (RCU_CFG1 & clks)){
|
||||
/* get RCU PLL2 clock multiplication factor */
|
||||
clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> RCU_CFG1_PLL2MF_OFFSET);
|
||||
|
||||
if((clks > 5U) && (clks < 15U)){
|
||||
/* multiplier is between 8 and 16 */
|
||||
clks += 2U;
|
||||
}else{
|
||||
if(15U == clks){
|
||||
/* multiplier is 20 */
|
||||
clks = 20U;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the PREDV1 value */
|
||||
i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> RCU_CFG1_PREDV1_OFFSET) + 1U);
|
||||
/* calculate I2S clock based on PLL2 and PREDV1 */
|
||||
if(0U != (RCU_CFG1_PLLPRESEL & RCU_CFG1)){
|
||||
i2sclock = (uint32_t)((IRC48M_VALUE / i2sclock) * clks * 2U);
|
||||
}else{
|
||||
i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U);
|
||||
}
|
||||
}else{
|
||||
/* get system clock */
|
||||
i2sclock = rcu_clock_freq_get(CK_SYS);
|
||||
}
|
||||
|
||||
/* config the prescaler depending on the mclk output state, the frame format and audio sample rate */
|
||||
if(I2S_MCKOUT_ENABLE == mckout){
|
||||
clks = (uint32_t)(((i2sclock / 256U) * 10U) / audiosample);
|
||||
}else{
|
||||
if(I2S_FRAMEFORMAT_DT16B_CH16B == frameformat){
|
||||
clks = (uint32_t)(((i2sclock / 32U) *10U) / audiosample);
|
||||
}else{
|
||||
clks = (uint32_t)(((i2sclock / 64U) *10U) / audiosample);
|
||||
}
|
||||
}
|
||||
|
||||
/* remove the floating point */
|
||||
clks = (clks + 5U) / 10U;
|
||||
i2sof = (clks & 0x00000001U);
|
||||
i2sdiv = ((clks - i2sof) / 2U);
|
||||
i2sof = (i2sof << 8U);
|
||||
|
||||
/* set the default values */
|
||||
if((i2sdiv < 2U) || (i2sdiv > 255U)){
|
||||
i2sdiv = 2U;
|
||||
i2sof = 0U;
|
||||
}
|
||||
|
||||
/* configure SPI_I2SPSC */
|
||||
SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | mckout);
|
||||
|
||||
/* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */
|
||||
SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN));
|
||||
/* configure data frame format */
|
||||
SPI_I2SCTL(spi_periph) |= (uint32_t)frameformat;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable I2S
|
||||
\param[in] spi_periph: SPIx(x=1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2s_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable I2S
|
||||
\param[in] spi_periph: SPIx(x=1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2s_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI NSS output
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nss_output_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI NSS output
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nss_output_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief SPI NSS pin high level in software mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nss_internal_high(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief SPI NSS pin low level in software mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nss_internal_low(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI DMA send or receive
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] dma: SPI DMA mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_DMA_TRANSMIT: SPI transmit data using DMA
|
||||
\arg SPI_DMA_RECEIVE: SPI receive data using DMA
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_dma_enable(uint32_t spi_periph, uint8_t dma)
|
||||
{
|
||||
if(SPI_DMA_TRANSMIT == dma){
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN;
|
||||
}else{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI DMA send or receive
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] dma: SPI DMA mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_DMA_TRANSMIT: SPI transmit data using DMA
|
||||
\arg SPI_DMA_RECEIVE: SPI receive data using DMA
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_dma_disable(uint32_t spi_periph, uint8_t dma)
|
||||
{
|
||||
if(SPI_DMA_TRANSMIT == dma){
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN);
|
||||
}else{
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure SPI/I2S data frame format
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] frame_format: SPI frame size
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits
|
||||
\arg SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format)
|
||||
{
|
||||
/* clear SPI_CTL0_FF16 bit */
|
||||
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16);
|
||||
/* configure SPI_CTL0_FF16 bit */
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)frame_format;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief SPI transmit data
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] data: 16-bit data
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data)
|
||||
{
|
||||
SPI_DATA(spi_periph) = (uint32_t)data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief SPI receive data
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval 16-bit data
|
||||
*/
|
||||
uint16_t spi_i2s_data_receive(uint32_t spi_periph)
|
||||
{
|
||||
return ((uint16_t)SPI_DATA(spi_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure SPI bidirectional transfer direction
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] transfer_direction: SPI transfer direction
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode
|
||||
\arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction)
|
||||
{
|
||||
if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){
|
||||
/* set the transmit-only mode */
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT;
|
||||
}else{
|
||||
/* set the receive-only mode */
|
||||
SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear SPI/I2S format error flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] flag: SPI/I2S frame format error flag
|
||||
\arg SPI_FLAG_FERR: only for SPI work in TI mode
|
||||
\arg I2S_FLAG_FERR: for I2S
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_i2s_format_error_clear(uint32_t spi_periph, uint32_t flag)
|
||||
{
|
||||
SPI_STAT(spi_periph) = (uint32_t)(~flag);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set SPI CRC polynomial
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] crc_poly: CRC polynomial value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_crc_polynomial_set(uint32_t spi_periph,uint16_t crc_poly)
|
||||
{
|
||||
/* set SPI CRC polynomial */
|
||||
SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get SPI CRC polynomial
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval 16-bit CRC polynomial
|
||||
*/
|
||||
uint16_t spi_crc_polynomial_get(uint32_t spi_periph)
|
||||
{
|
||||
return ((uint16_t)SPI_CRCPOLY(spi_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief turn on CRC function
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_crc_on(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief turn off CRC function
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_crc_off(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief SPI next data is CRC value
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_crc_next(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get SPI CRC send value or receive value
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] crc: SPI crc value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_CRC_TX: get transmit crc value
|
||||
\arg SPI_CRC_RX: get receive crc value
|
||||
\param[out] none
|
||||
\retval 16-bit CRC value
|
||||
*/
|
||||
uint16_t spi_crc_get(uint32_t spi_periph,uint8_t crc)
|
||||
{
|
||||
if(SPI_CRC_TX == crc){
|
||||
return ((uint16_t)(SPI_TCRC(spi_periph)));
|
||||
}else{
|
||||
return ((uint16_t)(SPI_RCRC(spi_periph)));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear SPI CRC error flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_crc_error_clear(uint32_t spi_periph)
|
||||
{
|
||||
SPI_STAT(spi_periph) = (uint32_t)(~SPI_FLAG_CRCERR);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI TI mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_ti_mode_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TMOD;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI TI mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_ti_mode_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TMOD);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI NSS pulse mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nssp_mode_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSP;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI NSS pulse mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nssp_mode_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSP);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI quad wire mode
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_quad_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI quad wire mode
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_quad_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI quad wire mode write
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_quad_write_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QRD);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI quad wire mode read
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
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)
|
||||
\param[in] interrupt: SPI/I2S interrupt
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_I2S_INT_TBE: transmit buffer empty interrupt
|
||||
\arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt
|
||||
\arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
|
||||
transmission underrun error and format error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt)
|
||||
{
|
||||
switch(interrupt){
|
||||
/* SPI/I2S transmit buffer empty interrupt */
|
||||
case SPI_I2S_INT_TBE:
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE;
|
||||
break;
|
||||
/* SPI/I2S receive buffer not empty interrupt */
|
||||
case SPI_I2S_INT_RBNE:
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE;
|
||||
break;
|
||||
/* SPI/I2S error */
|
||||
case SPI_I2S_INT_ERR:
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI and I2S interrupt
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] interrupt: SPI/I2S interrupt
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_I2S_INT_TBE: transmit buffer empty interrupt
|
||||
\arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt
|
||||
\arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
|
||||
transmission underrun error and format error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt)
|
||||
{
|
||||
switch(interrupt){
|
||||
/* SPI/I2S transmit buffer empty interrupt */
|
||||
case SPI_I2S_INT_TBE:
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE);
|
||||
break;
|
||||
/* SPI/I2S receive buffer not empty interrupt */
|
||||
case SPI_I2S_INT_RBNE:
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE);
|
||||
break;
|
||||
/* SPI/I2S error */
|
||||
case SPI_I2S_INT_ERR:
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get SPI and I2S interrupt flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] interrupt: SPI/I2S interrupt flag status
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag
|
||||
\arg SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag
|
||||
\arg SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag
|
||||
\arg SPI_INT_FLAG_CONFERR: config error interrupt flag
|
||||
\arg SPI_INT_FLAG_CRCERR: CRC error interrupt flag
|
||||
\arg I2S_INT_FLAG_TXURERR: underrun error interrupt flag
|
||||
\arg SPI_I2S_INT_FLAG_FERR: format error interrupt flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt)
|
||||
{
|
||||
uint32_t reg1 = SPI_STAT(spi_periph);
|
||||
uint32_t reg2 = SPI_CTL1(spi_periph);
|
||||
|
||||
switch(interrupt){
|
||||
/* SPI/I2S transmit buffer empty interrupt */
|
||||
case SPI_I2S_INT_FLAG_TBE:
|
||||
reg1 = reg1 & SPI_STAT_TBE;
|
||||
reg2 = reg2 & SPI_CTL1_TBEIE;
|
||||
break;
|
||||
/* SPI/I2S receive buffer not empty interrupt */
|
||||
case SPI_I2S_INT_FLAG_RBNE:
|
||||
reg1 = reg1 & SPI_STAT_RBNE;
|
||||
reg2 = reg2 & SPI_CTL1_RBNEIE;
|
||||
break;
|
||||
/* SPI/I2S overrun interrupt */
|
||||
case SPI_I2S_INT_FLAG_RXORERR:
|
||||
reg1 = reg1 & SPI_STAT_RXORERR;
|
||||
reg2 = reg2 & SPI_CTL1_ERRIE;
|
||||
break;
|
||||
/* SPI config error interrupt */
|
||||
case SPI_INT_FLAG_CONFERR:
|
||||
reg1 = reg1 & SPI_STAT_CONFERR;
|
||||
reg2 = reg2 & SPI_CTL1_ERRIE;
|
||||
break;
|
||||
/* SPI CRC error interrupt */
|
||||
case SPI_INT_FLAG_CRCERR:
|
||||
reg1 = reg1 & SPI_STAT_CRCERR;
|
||||
reg2 = reg2 & SPI_CTL1_ERRIE;
|
||||
break;
|
||||
/* I2S underrun error interrupt */
|
||||
case I2S_INT_FLAG_TXURERR:
|
||||
reg1 = reg1 & SPI_STAT_TXURERR;
|
||||
reg2 = reg2 & SPI_CTL1_ERRIE;
|
||||
break;
|
||||
/* SPI/I2S format error interrupt */
|
||||
case SPI_I2S_INT_FLAG_FERR:
|
||||
reg1 = reg1 & SPI_STAT_FERR;
|
||||
reg2 = reg2 & SPI_CTL1_ERRIE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* get SPI/I2S interrupt flag status */
|
||||
if((0U != reg1) && (0U != reg2)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get SPI and I2S flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] flag: SPI/I2S flag status
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg SPI_FLAG_TBE: transmit buffer empty flag
|
||||
\arg SPI_FLAG_RBNE: receive buffer not empty flag
|
||||
\arg SPI_FLAG_TRANS: transmit on-going flag
|
||||
\arg SPI_FLAG_RXORERR: receive overrun error flag
|
||||
\arg SPI_FLAG_CONFERR: mode config error flag
|
||||
\arg SPI_FLAG_CRCERR: CRC error flag
|
||||
\arg SPI_FLAG_FERR: format error interrupt flag
|
||||
\arg I2S_FLAG_TBE: transmit buffer empty flag
|
||||
\arg I2S_FLAG_RBNE: receive buffer not empty flag
|
||||
\arg I2S_FLAG_TRANS: transmit on-going flag
|
||||
\arg I2S_FLAG_RXORERR: overrun error flag
|
||||
\arg I2S_FLAG_TXURERR: underrun error flag
|
||||
\arg I2S_FLAG_CH: channel side flag
|
||||
\arg I2S_FLAG_FERR: format error interrupt flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag)
|
||||
{
|
||||
if(RESET != (SPI_STAT(spi_periph) & flag)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,855 @@
|
||||
/*!
|
||||
\file gd32c10x_spi.c
|
||||
\brief SPI driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_spi.h"
|
||||
|
||||
#define SPI_ERROR_HANDLE(s) do{}while(1)
|
||||
|
||||
/* SPI/I2S parameter initialization mask */
|
||||
#define SPI_INIT_MASK ((uint32_t)0x00003040U) /* SPI parameter initialization mask */
|
||||
#define I2S_INIT_MASK ((uint32_t)0x0000F047U) /* I2S parameter initialization mask */
|
||||
|
||||
/* I2S clock source selection, multiplication and division mask */
|
||||
#define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /* I2S1 clock source selection */
|
||||
#define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /* I2S2 clock source selection */
|
||||
#define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /* I2S clock multiplication mask */
|
||||
#define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /* I2S clock division mask */
|
||||
|
||||
/* default value and offset */
|
||||
#define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /* default value of SPI_I2SPSC register */
|
||||
#define RCU_CFG1_PREDV1_OFFSET 4U /* PREDV1 offset in RCU_CFG1 */
|
||||
#define RCU_CFG1_PLL2MF_OFFSET 12U /* PLL2MF offset in RCU_CFG1 */
|
||||
|
||||
/*!
|
||||
\brief reset SPI and I2S
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_i2s_deinit(uint32_t spi_periph)
|
||||
{
|
||||
switch(spi_periph){
|
||||
case SPI0:
|
||||
/* reset SPI0 */
|
||||
rcu_periph_reset_enable(RCU_SPI0RST);
|
||||
rcu_periph_reset_disable(RCU_SPI0RST);
|
||||
break;
|
||||
case SPI1:
|
||||
/* reset SPI1 and I2S1 */
|
||||
rcu_periph_reset_enable(RCU_SPI1RST);
|
||||
rcu_periph_reset_disable(RCU_SPI1RST);
|
||||
break;
|
||||
case SPI2:
|
||||
/* reset SPI2 and I2S2 */
|
||||
rcu_periph_reset_enable(RCU_SPI2RST);
|
||||
rcu_periph_reset_disable(RCU_SPI2RST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize the parameters of SPI struct with the default values
|
||||
\param[in] spi_struct: SPI parameter struct
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_struct_para_init(spi_parameter_struct* spi_struct)
|
||||
{
|
||||
/* set the SPI struct with the default values */
|
||||
spi_struct->device_mode = SPI_SLAVE;
|
||||
spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX;
|
||||
spi_struct->frame_size = SPI_FRAMESIZE_8BIT;
|
||||
spi_struct->nss = SPI_NSS_HARD;
|
||||
spi_struct->endian = SPI_ENDIAN_MSB;
|
||||
spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
|
||||
spi_struct->prescale = SPI_PSC_2;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize SPI parameter
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] spi_struct: SPI parameter initialization stuct members of the structure
|
||||
and the member values are shown as below:
|
||||
device_mode: SPI_MASTER, SPI_SLAVE
|
||||
trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY,
|
||||
SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT
|
||||
frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT
|
||||
nss: SPI_NSS_SOFT, SPI_NSS_HARD
|
||||
endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB
|
||||
clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE
|
||||
SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE
|
||||
prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct)
|
||||
{
|
||||
uint32_t reg = 0U;
|
||||
reg = SPI_CTL0(spi_periph);
|
||||
reg &= SPI_INIT_MASK;
|
||||
|
||||
/* select SPI as master or slave */
|
||||
reg |= spi_struct->device_mode;
|
||||
/* select SPI transfer mode */
|
||||
reg |= spi_struct->trans_mode;
|
||||
/* select SPI frame size */
|
||||
reg |= spi_struct->frame_size;
|
||||
/* select SPI NSS use hardware or software */
|
||||
reg |= spi_struct->nss;
|
||||
/* select SPI LSB or MSB */
|
||||
reg |= spi_struct->endian;
|
||||
/* select SPI polarity and phase */
|
||||
reg |= spi_struct->clock_polarity_phase;
|
||||
/* select SPI prescale to adjust transmit speed */
|
||||
reg |= spi_struct->prescale;
|
||||
|
||||
/* write to SPI_CTL0 register */
|
||||
SPI_CTL0(spi_periph) = (uint32_t)reg;
|
||||
|
||||
SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize I2S parameter
|
||||
\param[in] spi_periph: SPIx(x=1,2)
|
||||
\param[in] mode: I2S operation mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2S_MODE_SLAVETX: I2S slave transmit mode
|
||||
\arg I2S_MODE_SLAVERX: I2S slave receive mode
|
||||
\arg I2S_MODE_MASTERTX: I2S master transmit mode
|
||||
\arg I2S_MODE_MASTERRX: I2S master receive mode
|
||||
\param[in] standard: I2S standard
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2S_STD_PHILIPS: I2S Philips standard
|
||||
\arg I2S_STD_MSB: I2S MSB standard
|
||||
\arg I2S_STD_LSB: I2S LSB standard
|
||||
\arg I2S_STD_PCMSHORT: I2S PCM short standard
|
||||
\arg I2S_STD_PCMLONG: I2S PCM long standard
|
||||
\param[in] ckpl: I2S idle state clock polarity
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2S_CKPL_LOW: I2S clock polarity low level
|
||||
\arg I2S_CKPL_HIGH: I2S clock polarity high level
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl)
|
||||
{
|
||||
uint32_t reg = 0U;
|
||||
reg = SPI_I2SCTL(spi_periph);
|
||||
reg &= I2S_INIT_MASK;
|
||||
|
||||
/* enable I2S mode */
|
||||
reg |= (uint32_t)SPI_I2SCTL_I2SSEL;
|
||||
/* select I2S mode */
|
||||
reg |= (uint32_t)mode;
|
||||
/* select I2S standard */
|
||||
reg |= (uint32_t)standard;
|
||||
/* select I2S polarity */
|
||||
reg |= (uint32_t)ckpl;
|
||||
|
||||
/* write to SPI_I2SCTL register */
|
||||
SPI_I2SCTL(spi_periph) = (uint32_t)reg;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure I2S prescaler
|
||||
\param[in] spi_periph: SPIx(x=1,2)
|
||||
\param[in] audiosample: I2S audio sample rate
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz
|
||||
\arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz
|
||||
\arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz
|
||||
\arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz
|
||||
\arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz
|
||||
\arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz
|
||||
\arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz
|
||||
\arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz
|
||||
\arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz
|
||||
\param[in] frameformat: I2S data length and channel length
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit
|
||||
\arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit
|
||||
\arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit
|
||||
\arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit
|
||||
\param[in] mckout: I2S master clock output
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg I2S_MCKOUT_ENABLE: I2S master clock output enable
|
||||
\arg I2S_MCKOUT_DISABLE: I2S master clock output disable
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout)
|
||||
{
|
||||
uint32_t i2sdiv = 2U, i2sof = 0U;
|
||||
uint32_t clks = 0U;
|
||||
uint32_t i2sclock = 0U;
|
||||
|
||||
/* judge whether the audiosample is 0 */
|
||||
if(0U == audiosample){
|
||||
SPI_ERROR_HANDLE("the parameter can not be 0 \r\n");
|
||||
}
|
||||
|
||||
/* deinit SPI_I2SPSC register */
|
||||
SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE;
|
||||
|
||||
/* get the I2S clock source */
|
||||
if(SPI1 == ((uint32_t)spi_periph)){
|
||||
/* I2S1 clock source selection */
|
||||
clks = I2S1_CLOCK_SEL;
|
||||
}else{
|
||||
/* I2S2 clock source selection */
|
||||
clks = I2S2_CLOCK_SEL;
|
||||
}
|
||||
|
||||
if(0U != (RCU_CFG1 & clks)){
|
||||
/* get RCU PLL2 clock multiplication factor */
|
||||
clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> RCU_CFG1_PLL2MF_OFFSET);
|
||||
|
||||
if((clks > 5U) && (clks < 15U)){
|
||||
/* multiplier is between 8 and 16 */
|
||||
clks += 2U;
|
||||
}else{
|
||||
if(15U == clks){
|
||||
/* multiplier is 20 */
|
||||
clks = 20U;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the PREDV1 value */
|
||||
i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> RCU_CFG1_PREDV1_OFFSET) + 1U);
|
||||
/* calculate I2S clock based on PLL2 and PREDV1 */
|
||||
if(0U != (RCU_CFG1_PLLPRESEL & RCU_CFG1)){
|
||||
i2sclock = (uint32_t)((IRC48M_VALUE / i2sclock) * clks * 2U);
|
||||
}else{
|
||||
i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U);
|
||||
}
|
||||
}else{
|
||||
/* get system clock */
|
||||
i2sclock = rcu_clock_freq_get(CK_SYS);
|
||||
}
|
||||
|
||||
/* config the prescaler depending on the mclk output state, the frame format and audio sample rate */
|
||||
if(I2S_MCKOUT_ENABLE == mckout){
|
||||
clks = (uint32_t)(((i2sclock / 256U) * 10U) / audiosample);
|
||||
}else{
|
||||
if(I2S_FRAMEFORMAT_DT16B_CH16B == frameformat){
|
||||
clks = (uint32_t)(((i2sclock / 32U) *10U) / audiosample);
|
||||
}else{
|
||||
clks = (uint32_t)(((i2sclock / 64U) *10U) / audiosample);
|
||||
}
|
||||
}
|
||||
|
||||
/* remove the floating point */
|
||||
clks = (clks + 5U) / 10U;
|
||||
i2sof = (clks & 0x00000001U);
|
||||
i2sdiv = ((clks - i2sof) / 2U);
|
||||
i2sof = (i2sof << 8U);
|
||||
|
||||
/* set the default values */
|
||||
if((i2sdiv < 2U) || (i2sdiv > 255U)){
|
||||
i2sdiv = 2U;
|
||||
i2sof = 0U;
|
||||
}
|
||||
|
||||
/* configure SPI_I2SPSC */
|
||||
SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | mckout);
|
||||
|
||||
/* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */
|
||||
SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN));
|
||||
/* configure data frame format */
|
||||
SPI_I2SCTL(spi_periph) |= (uint32_t)frameformat;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable I2S
|
||||
\param[in] spi_periph: SPIx(x=1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2s_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable I2S
|
||||
\param[in] spi_periph: SPIx(x=1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void i2s_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI NSS output
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nss_output_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI NSS output
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nss_output_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief SPI NSS pin high level in software mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nss_internal_high(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief SPI NSS pin low level in software mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nss_internal_low(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI DMA send or receive
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] dma: SPI DMA mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_DMA_TRANSMIT: SPI transmit data using DMA
|
||||
\arg SPI_DMA_RECEIVE: SPI receive data using DMA
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_dma_enable(uint32_t spi_periph, uint8_t dma)
|
||||
{
|
||||
if(SPI_DMA_TRANSMIT == dma){
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN;
|
||||
}else{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI DMA send or receive
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] dma: SPI DMA mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_DMA_TRANSMIT: SPI transmit data using DMA
|
||||
\arg SPI_DMA_RECEIVE: SPI receive data using DMA
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_dma_disable(uint32_t spi_periph, uint8_t dma)
|
||||
{
|
||||
if(SPI_DMA_TRANSMIT == dma){
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN);
|
||||
}else{
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure SPI/I2S data frame format
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] frame_format: SPI frame size
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits
|
||||
\arg SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format)
|
||||
{
|
||||
/* clear SPI_CTL0_FF16 bit */
|
||||
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16);
|
||||
/* configure SPI_CTL0_FF16 bit */
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)frame_format;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief SPI transmit data
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] data: 16-bit data
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data)
|
||||
{
|
||||
SPI_DATA(spi_periph) = (uint32_t)data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief SPI receive data
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval 16-bit data
|
||||
*/
|
||||
uint16_t spi_i2s_data_receive(uint32_t spi_periph)
|
||||
{
|
||||
return ((uint16_t)SPI_DATA(spi_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure SPI bidirectional transfer direction
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] transfer_direction: SPI transfer direction
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode
|
||||
\arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction)
|
||||
{
|
||||
if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){
|
||||
/* set the transmit-only mode */
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT;
|
||||
}else{
|
||||
/* set the receive-only mode */
|
||||
SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear SPI/I2S format error flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] flag: SPI/I2S frame format error flag
|
||||
\arg SPI_FLAG_FERR: only for SPI work in TI mode
|
||||
\arg I2S_FLAG_FERR: for I2S
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_i2s_format_error_clear(uint32_t spi_periph, uint32_t flag)
|
||||
{
|
||||
SPI_STAT(spi_periph) = (uint32_t)(~flag);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set SPI CRC polynomial
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] crc_poly: CRC polynomial value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_crc_polynomial_set(uint32_t spi_periph,uint16_t crc_poly)
|
||||
{
|
||||
/* set SPI CRC polynomial */
|
||||
SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get SPI CRC polynomial
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval 16-bit CRC polynomial
|
||||
*/
|
||||
uint16_t spi_crc_polynomial_get(uint32_t spi_periph)
|
||||
{
|
||||
return ((uint16_t)SPI_CRCPOLY(spi_periph));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief turn on CRC function
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_crc_on(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief turn off CRC function
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_crc_off(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief SPI next data is CRC value
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_crc_next(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get SPI CRC send value or receive value
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] crc: SPI crc value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_CRC_TX: get transmit crc value
|
||||
\arg SPI_CRC_RX: get receive crc value
|
||||
\param[out] none
|
||||
\retval 16-bit CRC value
|
||||
*/
|
||||
uint16_t spi_crc_get(uint32_t spi_periph,uint8_t crc)
|
||||
{
|
||||
if(SPI_CRC_TX == crc){
|
||||
return ((uint16_t)(SPI_TCRC(spi_periph)));
|
||||
}else{
|
||||
return ((uint16_t)(SPI_RCRC(spi_periph)));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear SPI CRC error flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_crc_error_clear(uint32_t spi_periph)
|
||||
{
|
||||
SPI_STAT(spi_periph) = (uint32_t)(~SPI_FLAG_CRCERR);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI TI mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_ti_mode_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TMOD;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI TI mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_ti_mode_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TMOD);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI NSS pulse mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nssp_mode_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSP;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI NSS pulse mode
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_nssp_mode_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSP);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI quad wire mode
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_quad_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI quad wire mode
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_quad_disable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI quad wire mode write
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_quad_write_enable(uint32_t spi_periph)
|
||||
{
|
||||
SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QRD);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable SPI quad wire mode read
|
||||
\param[in] spi_periph: SPIx(only x=0)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
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)
|
||||
\param[in] interrupt: SPI/I2S interrupt
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_I2S_INT_TBE: transmit buffer empty interrupt
|
||||
\arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt
|
||||
\arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
|
||||
transmission underrun error and format error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt)
|
||||
{
|
||||
switch(interrupt){
|
||||
/* SPI/I2S transmit buffer empty interrupt */
|
||||
case SPI_I2S_INT_TBE:
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE;
|
||||
break;
|
||||
/* SPI/I2S receive buffer not empty interrupt */
|
||||
case SPI_I2S_INT_RBNE:
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE;
|
||||
break;
|
||||
/* SPI/I2S error */
|
||||
case SPI_I2S_INT_ERR:
|
||||
SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable SPI and I2S interrupt
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] interrupt: SPI/I2S interrupt
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_I2S_INT_TBE: transmit buffer empty interrupt
|
||||
\arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt
|
||||
\arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error,
|
||||
transmission underrun error and format error interrupt
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt)
|
||||
{
|
||||
switch(interrupt){
|
||||
/* SPI/I2S transmit buffer empty interrupt */
|
||||
case SPI_I2S_INT_TBE:
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE);
|
||||
break;
|
||||
/* SPI/I2S receive buffer not empty interrupt */
|
||||
case SPI_I2S_INT_RBNE:
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE);
|
||||
break;
|
||||
/* SPI/I2S error */
|
||||
case SPI_I2S_INT_ERR:
|
||||
SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get SPI and I2S interrupt flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] interrupt: SPI/I2S interrupt flag status
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag
|
||||
\arg SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag
|
||||
\arg SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag
|
||||
\arg SPI_INT_FLAG_CONFERR: config error interrupt flag
|
||||
\arg SPI_INT_FLAG_CRCERR: CRC error interrupt flag
|
||||
\arg I2S_INT_FLAG_TXURERR: underrun error interrupt flag
|
||||
\arg SPI_I2S_INT_FLAG_FERR: format error interrupt flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt)
|
||||
{
|
||||
uint32_t reg1 = SPI_STAT(spi_periph);
|
||||
uint32_t reg2 = SPI_CTL1(spi_periph);
|
||||
|
||||
switch(interrupt){
|
||||
/* SPI/I2S transmit buffer empty interrupt */
|
||||
case SPI_I2S_INT_FLAG_TBE:
|
||||
reg1 = reg1 & SPI_STAT_TBE;
|
||||
reg2 = reg2 & SPI_CTL1_TBEIE;
|
||||
break;
|
||||
/* SPI/I2S receive buffer not empty interrupt */
|
||||
case SPI_I2S_INT_FLAG_RBNE:
|
||||
reg1 = reg1 & SPI_STAT_RBNE;
|
||||
reg2 = reg2 & SPI_CTL1_RBNEIE;
|
||||
break;
|
||||
/* SPI/I2S overrun interrupt */
|
||||
case SPI_I2S_INT_FLAG_RXORERR:
|
||||
reg1 = reg1 & SPI_STAT_RXORERR;
|
||||
reg2 = reg2 & SPI_CTL1_ERRIE;
|
||||
break;
|
||||
/* SPI config error interrupt */
|
||||
case SPI_INT_FLAG_CONFERR:
|
||||
reg1 = reg1 & SPI_STAT_CONFERR;
|
||||
reg2 = reg2 & SPI_CTL1_ERRIE;
|
||||
break;
|
||||
/* SPI CRC error interrupt */
|
||||
case SPI_INT_FLAG_CRCERR:
|
||||
reg1 = reg1 & SPI_STAT_CRCERR;
|
||||
reg2 = reg2 & SPI_CTL1_ERRIE;
|
||||
break;
|
||||
/* I2S underrun error interrupt */
|
||||
case I2S_INT_FLAG_TXURERR:
|
||||
reg1 = reg1 & SPI_STAT_TXURERR;
|
||||
reg2 = reg2 & SPI_CTL1_ERRIE;
|
||||
break;
|
||||
/* SPI/I2S format error interrupt */
|
||||
case SPI_I2S_INT_FLAG_FERR:
|
||||
reg1 = reg1 & SPI_STAT_FERR;
|
||||
reg2 = reg2 & SPI_CTL1_ERRIE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* get SPI/I2S interrupt flag status */
|
||||
if((0U != reg1) && (0U != reg2)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get SPI and I2S flag status
|
||||
\param[in] spi_periph: SPIx(x=0,1,2)
|
||||
\param[in] flag: SPI/I2S flag status
|
||||
one or more parameters can be selected which are shown as below:
|
||||
\arg SPI_FLAG_TBE: transmit buffer empty flag
|
||||
\arg SPI_FLAG_RBNE: receive buffer not empty flag
|
||||
\arg SPI_FLAG_TRANS: transmit on-going flag
|
||||
\arg SPI_FLAG_RXORERR: receive overrun error flag
|
||||
\arg SPI_FLAG_CONFERR: mode config error flag
|
||||
\arg SPI_FLAG_CRCERR: CRC error flag
|
||||
\arg SPI_FLAG_FERR: format error interrupt flag
|
||||
\arg I2S_FLAG_TBE: transmit buffer empty flag
|
||||
\arg I2S_FLAG_RBNE: receive buffer not empty flag
|
||||
\arg I2S_FLAG_TRANS: transmit on-going flag
|
||||
\arg I2S_FLAG_RXORERR: overrun error flag
|
||||
\arg I2S_FLAG_TXURERR: underrun error flag
|
||||
\arg I2S_FLAG_CH: channel side flag
|
||||
\arg I2S_FLAG_FERR: format error interrupt flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag)
|
||||
{
|
||||
if(RESET != (SPI_STAT(spi_periph) & flag)){
|
||||
return SET;
|
||||
}else{
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,890 @@
|
||||
/*!
|
||||
\file gd32c10x_usart.c
|
||||
\brief USART driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_usart.h"
|
||||
|
||||
/* USART register bit offset */
|
||||
#define GP_GUAT_OFFSET ((uint32_t)8U) /* bit offset of GUAT in USART_GP */
|
||||
#define CTL3_SCRTNUM_OFFSET ((uint32_t)1U) /* bit offset of SCRTNUM in USART_CTL3 */
|
||||
#define RT_BL_OFFSET ((uint32_t)24U) /* bit offset of BL in USART_RT */
|
||||
|
||||
/*!
|
||||
\brief reset USART/UART
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_deinit(uint32_t usart_periph)
|
||||
{
|
||||
switch(usart_periph) {
|
||||
case USART0:
|
||||
/* reset USART0 */
|
||||
rcu_periph_reset_enable(RCU_USART0RST);
|
||||
rcu_periph_reset_disable(RCU_USART0RST);
|
||||
break;
|
||||
case USART1:
|
||||
/* reset USART1 */
|
||||
rcu_periph_reset_enable(RCU_USART1RST);
|
||||
rcu_periph_reset_disable(RCU_USART1RST);
|
||||
break;
|
||||
case USART2:
|
||||
/* reset USART2 */
|
||||
rcu_periph_reset_enable(RCU_USART2RST);
|
||||
rcu_periph_reset_disable(RCU_USART2RST);
|
||||
break;
|
||||
case UART3:
|
||||
/* reset UART3 */
|
||||
rcu_periph_reset_enable(RCU_UART3RST);
|
||||
rcu_periph_reset_disable(RCU_UART3RST);
|
||||
break;
|
||||
case UART4:
|
||||
/* reset UART4 */
|
||||
rcu_periph_reset_enable(RCU_UART4RST);
|
||||
rcu_periph_reset_disable(RCU_UART4RST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART baud rate value
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] baudval: baud rate value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval)
|
||||
{
|
||||
uint32_t uclk = 0U, intdiv = 0U, fradiv = 0U, udiv = 0U;
|
||||
switch(usart_periph) {
|
||||
/* get clock frequency */
|
||||
case USART0:
|
||||
/* get USART0 clock */
|
||||
uclk = rcu_clock_freq_get(CK_APB2);
|
||||
break;
|
||||
case USART1:
|
||||
/* get USART1 clock */
|
||||
uclk = rcu_clock_freq_get(CK_APB1);
|
||||
break;
|
||||
case USART2:
|
||||
/* get USART2 clock */
|
||||
uclk = rcu_clock_freq_get(CK_APB1);
|
||||
break;
|
||||
case UART3:
|
||||
/* get UART3 clock */
|
||||
uclk = rcu_clock_freq_get(CK_APB1);
|
||||
break;
|
||||
case UART4:
|
||||
/* get UART4 clock */
|
||||
uclk = rcu_clock_freq_get(CK_APB1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* oversampling by 16, configure the value of USART_BAUD */
|
||||
udiv = (uclk + baudval / 2U) / baudval;
|
||||
intdiv = udiv & 0xfff0U;
|
||||
fradiv = udiv & 0xfU;
|
||||
USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART parity
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] paritycfg: configure USART parity
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_PM_NONE: no parity
|
||||
\arg USART_PM_ODD: odd parity
|
||||
\arg USART_PM_EVEN: even parity
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg)
|
||||
{
|
||||
/* clear USART_CTL0 PM,PCEN bits */
|
||||
USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN);
|
||||
/* configure USART parity mode */
|
||||
USART_CTL0(usart_periph) |= paritycfg;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART word length
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] wlen: USART word length configure
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_WL_8BIT: 8 bits
|
||||
\arg USART_WL_9BIT: 9 bits
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_word_length_set(uint32_t usart_periph, uint32_t wlen)
|
||||
{
|
||||
/* clear USART_CTL0 WL bit */
|
||||
USART_CTL0(usart_periph) &= ~USART_CTL0_WL;
|
||||
/* configure USART word length */
|
||||
USART_CTL0(usart_periph) |= wlen;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART stop bit length
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] stblen: USART stop bit configure
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_STB_1BIT: 1 bit
|
||||
\arg USART_STB_0_5BIT: 0.5 bit, not available for UARTx(x=3,4)
|
||||
\arg USART_STB_2BIT: 2 bits
|
||||
\arg USART_STB_1_5BIT: 1.5 bits, not available for UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen)
|
||||
{
|
||||
/* clear USART_CTL1 STB bits */
|
||||
USART_CTL1(usart_periph) &= ~USART_CTL1_STB;
|
||||
/* configure USART stop bits */
|
||||
USART_CTL1(usart_periph) |= stblen;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable USART
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL0(usart_periph) |= USART_CTL0_UEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable USART
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART transmitter
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] txconfig: enable or disable USART transmitter
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_TRANSMIT_ENABLE: enable USART transmission
|
||||
\arg USART_TRANSMIT_DISABLE: disable USART transmission
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig)
|
||||
{
|
||||
USART_CTL0(usart_periph) &= ~(USART_CTL0_TEN);
|
||||
USART_CTL0(usart_periph) |= (USART_CTL0_TEN & txconfig);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART receiver
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] rxconfig: enable or disable USART receiver
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_RECEIVE_ENABLE: enable USART reception
|
||||
\arg USART_RECEIVE_DISABLE: disable USART reception
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig)
|
||||
{
|
||||
USART_CTL0(usart_periph) &= ~(USART_CTL0_REN);
|
||||
USART_CTL0(usart_periph) |= (USART_CTL0_REN & rxconfig);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief data is transmitted/received with the LSB/MSB first
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] msbf: LSB/MSB
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_MSBF_LSB: LSB first
|
||||
\arg USART_MSBF_MSB: MSB first
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_data_first_config(uint32_t usart_periph, uint32_t msbf)
|
||||
{
|
||||
USART_CTL3(usart_periph) &= ~(USART_CTL3_MSBF);
|
||||
USART_CTL3(usart_periph) |= msbf;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART inversion
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] invertpara: refer to enum usart_invert_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_DINV_ENABLE: data bit level inversion
|
||||
\arg USART_DINV_DISABLE: data bit level not inversion
|
||||
\arg USART_TXPIN_ENABLE: TX pin level inversion
|
||||
\arg USART_TXPIN_DISABLE: TX pin level not inversion
|
||||
\arg USART_RXPIN_ENABLE: RX pin level inversion
|
||||
\arg USART_RXPIN_DISABLE: RX pin level not inversion
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara)
|
||||
{
|
||||
/* inverted or not the specified signal */
|
||||
switch(invertpara) {
|
||||
case USART_DINV_ENABLE:
|
||||
/* data bit level inversion */
|
||||
USART_CTL3(usart_periph) |= USART_CTL3_DINV;
|
||||
break;
|
||||
case USART_TXPIN_ENABLE:
|
||||
/* TX pin level inversion */
|
||||
USART_CTL3(usart_periph) |= USART_CTL3_TINV;
|
||||
break;
|
||||
case USART_RXPIN_ENABLE:
|
||||
/* RX pin level inversion */
|
||||
USART_CTL3(usart_periph) |= USART_CTL3_RINV;
|
||||
break;
|
||||
case USART_DINV_DISABLE:
|
||||
/* data bit level not inversion */
|
||||
USART_CTL3(usart_periph) &= ~(USART_CTL3_DINV);
|
||||
break;
|
||||
case USART_TXPIN_DISABLE:
|
||||
/* TX pin level not inversion */
|
||||
USART_CTL3(usart_periph) &= ~(USART_CTL3_TINV);
|
||||
break;
|
||||
case USART_RXPIN_DISABLE:
|
||||
/* RX pin level not inversion */
|
||||
USART_CTL3(usart_periph) &= ~(USART_CTL3_RINV);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable receiver timeout
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_receiver_timeout_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL3(usart_periph) |= USART_CTL3_RTEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable receiver timeout
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_receiver_timeout_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL3(usart_periph) &= ~(USART_CTL3_RTEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure receiver timeout threshold
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] rtimeout: 0-0xFFFFFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout)
|
||||
{
|
||||
USART_RT(usart_periph) &= ~(USART_RT_RT);
|
||||
USART_RT(usart_periph) |= rtimeout;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief USART transmit data function
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] data: data to be transmitted
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_data_transmit(uint32_t usart_periph, uint16_t data)
|
||||
{
|
||||
USART_DATA(usart_periph) = USART_DATA_DATA & (uint32_t)data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief USART receive data function
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval data of received
|
||||
*/
|
||||
uint16_t usart_data_receive(uint32_t usart_periph)
|
||||
{
|
||||
return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the address of the USART in wake up by address match mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] addr: address of USART/UART
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_address_config(uint32_t usart_periph, uint8_t addr)
|
||||
{
|
||||
USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR);
|
||||
USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & (uint32_t)addr);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable mute mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_mute_mode_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL0(usart_periph) |= USART_CTL0_RWU;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable mute mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_mute_mode_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure wakeup method in mute mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] wmethod: two methods be used to enter or exit the mute mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_WM_IDLE: idle line
|
||||
\arg USART_WM_ADDR: address mask
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod)
|
||||
{
|
||||
USART_CTL0(usart_periph) &= ~(USART_CTL0_WM);
|
||||
USART_CTL0(usart_periph) |= wmethod;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable LIN mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_lin_mode_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL1(usart_periph) |= USART_CTL1_LMEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable LIN mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_lin_mode_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure lin break frame length
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] lblen: lin break frame length
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_LBLEN_10B: 10 bits
|
||||
\arg USART_LBLEN_11B: 11 bits
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen)
|
||||
{
|
||||
USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN);
|
||||
USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief send break frame
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_send_break(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable half duplex mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_halfduplex_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) |= USART_CTL2_HDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable half duplex mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_halfduplex_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable CK pin in synchronous mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_synchronous_clock_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL1(usart_periph) |= USART_CTL1_CKEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable CK pin in synchronous mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_synchronous_clock_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART synchronous mode parameters
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] clen: CK length
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame
|
||||
\arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame
|
||||
\param[in] cph: clock phase
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_CPH_1CK: first clock transition is the first data capture edge
|
||||
\arg USART_CPH_2CK: second clock transition is the first data capture edge
|
||||
\param[in] cpl: clock polarity
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_CPL_LOW: steady low value on CK pin
|
||||
\arg USART_CPL_HIGH: steady high value on CK pin
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl)
|
||||
{
|
||||
USART_CTL1(usart_periph) &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL);
|
||||
USART_CTL1(usart_periph) |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure guard time value in smartcard mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] guat: guard time value, 0-0xFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_guard_time_config(uint32_t usart_periph, uint8_t guat)
|
||||
{
|
||||
USART_GP(usart_periph) &= ~(USART_GP_GUAT);
|
||||
USART_GP(usart_periph) |= (USART_GP_GUAT & ((uint32_t)guat << GP_GUAT_OFFSET));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable smartcard mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_smartcard_mode_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) |= USART_CTL2_SCEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable smartcard mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_smartcard_mode_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_SCEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable NACK in smartcard mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_smartcard_mode_nack_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) |= USART_CTL2_NKEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable NACK in smartcard mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_smartcard_mode_nack_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_NKEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure smartcard auto-retry number
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] scrtnum: smartcard auto-retry number
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_smartcard_autoretry_config(uint32_t usart_periph, uint8_t scrtnum)
|
||||
{
|
||||
USART_CTL3(usart_periph) &= ~(USART_CTL3_SCRTNUM);
|
||||
USART_CTL3(usart_periph) |= (USART_CTL3_SCRTNUM & ((uint32_t)scrtnum << CTL3_SCRTNUM_OFFSET));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure block length
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] bl: block length
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_block_length_config(uint32_t usart_periph, uint8_t bl)
|
||||
{
|
||||
USART_RT(usart_periph) &= ~(USART_RT_BL);
|
||||
USART_RT(usart_periph) |= (USART_RT_BL & ((uint32_t)bl << RT_BL_OFFSET));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable IrDA mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_irda_mode_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) |= USART_CTL2_IREN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable IrDA mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_irda_mode_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_IREN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the peripheral clock prescaler
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] psc: 0x00-0xFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_prescaler_config(uint32_t usart_periph, uint8_t psc)
|
||||
{
|
||||
USART_GP(usart_periph) &= ~(USART_GP_PSC);
|
||||
USART_GP(usart_periph) |= (uint32_t)psc;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure IrDA low-power
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] irlp: IrDA low-power or normal
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_IRLP_LOW: low-power
|
||||
\arg USART_IRLP_NORMAL: normal
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_IRLP);
|
||||
USART_CTL2(usart_periph) |= (USART_CTL2_IRLP & irlp);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure hardware flow control RTS
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] rtsconfig: enable or disable RTS
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_RTS_ENABLE: enable RTS
|
||||
\arg USART_RTS_DISABLE: disable RTS
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_RTSEN);
|
||||
USART_CTL2(usart_periph) |= (USART_CTL2_RTSEN & rtsconfig);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure hardware flow control CTS
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] ctsconfig: enable or disable CTS
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_CTS_ENABLE: enable CTS
|
||||
\arg USART_CTS_DISABLE: disable CTS
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_CTSEN);
|
||||
USART_CTL2(usart_periph) |= (USART_CTL2_CTSEN & ctsconfig);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART DMA reception
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3)
|
||||
\param[in] dmaconfig: USART DMA mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_RECEIVE_DMA_ENABLE: enable USART DMA for reception
|
||||
\arg USART_RECEIVE_DMA_DISABLE: disable USART DMA for reception
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_dma_receive_config(uint32_t usart_periph, uint8_t dmaconfig)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_DENR);
|
||||
USART_CTL2(usart_periph) |= (USART_CTL2_DENR & dmaconfig);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART DMA transmission
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3)
|
||||
\param[in] dmaconfig: USART DMA mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_TRANSMIT_DMA_ENABLE: enable USART DMA for transmission
|
||||
\arg USART_TRANSMIT_DMA_DISABLE: disable USART DMA for transmission
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_dma_transmit_config(uint32_t usart_periph, uint8_t dmaconfig)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_DENT);
|
||||
USART_CTL2(usart_periph) |= (USART_CTL2_DENT & dmaconfig);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure hardware flow control coherence mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3)
|
||||
\param[in] hcm:
|
||||
\arg USART_RTS_NONE_COHERENCE: nRTS signal equals to the rxne status register
|
||||
\arg USART_RTS_COHERENCE: nRTS signal is set when the last data bit has been sampled
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_hardware_flow_coherence_config(uint32_t usart_periph, uint32_t hcm)
|
||||
{
|
||||
USART_CHC(usart_periph) &= ~(USART_CHC_HCM);
|
||||
USART_CHC(usart_periph) |= (USART_CHC_HCM & hcm);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get flag in STAT0/STAT1 register
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] flag: USART flags, refer to usart_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_FLAG_CTS: CTS change flag
|
||||
\arg USART_FLAG_LBD: LIN break detected flag
|
||||
\arg USART_FLAG_TBE: transmit data buffer empty
|
||||
\arg USART_FLAG_TC: transmission complete
|
||||
\arg USART_FLAG_RBNE: read data buffer not empty
|
||||
\arg USART_FLAG_IDLE: IDLE frame detected flag
|
||||
\arg USART_FLAG_ORERR: overrun error
|
||||
\arg USART_FLAG_NERR: noise error flag
|
||||
\arg USART_FLAG_FERR: frame error flag
|
||||
\arg USART_FLAG_PERR: parity error flag
|
||||
\arg USART_FLAG_BSY: busy flag
|
||||
\arg USART_FLAG_EB: end of block flag
|
||||
\arg USART_FLAG_RT: receiver timeout flag
|
||||
\arg USART_FLAG_EPERR: early parity error flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag)
|
||||
{
|
||||
if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))) {
|
||||
return SET;
|
||||
} else {
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear flag in STAT0/STAT1 register
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] flag: USART flags, refer to usart_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_FLAG_CTS: CTS change flag
|
||||
\arg USART_FLAG_LBD: LIN break detected flag
|
||||
\arg USART_FLAG_TC: transmission complete
|
||||
\arg USART_FLAG_RBNE: read data buffer not empty
|
||||
\arg USART_FLAG_EB: end of block flag
|
||||
\arg USART_FLAG_RT: receiver timeout flag
|
||||
\arg USART_FLAG_EPERR: early parity error flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag)
|
||||
{
|
||||
if(USART_FLAG_EPERR == flag) {
|
||||
USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag));
|
||||
} else {
|
||||
USART_REG_VAL(usart_periph, flag) = ~BIT(USART_BIT_POS(flag));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable USART interrupt
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] interrupt: USART interrupts, refer to usart_interrupt_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_INT_PERR: parity error interrupt
|
||||
\arg USART_INT_TBE: transmitter buffer empty interrupt
|
||||
\arg USART_INT_TC: transmission complete interrupt
|
||||
\arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt
|
||||
\arg USART_INT_IDLE: IDLE line detected interrupt
|
||||
\arg USART_INT_LBD: LIN break detected interrupt
|
||||
\arg USART_INT_ERR: error interrupt
|
||||
\arg USART_INT_CTS: CTS interrupt
|
||||
\arg USART_INT_RT: interrupt enable bit of receive timeout event
|
||||
\arg USART_INT_EB: interrupt enable bit of end of block event
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_interrupt_enable(uint32_t usart_periph, usart_interrupt_enum interrupt)
|
||||
{
|
||||
USART_REG_VAL(usart_periph, interrupt) |= BIT(USART_BIT_POS(interrupt));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable USART interrupt
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] interrupt: USART interrupts, refer to usart_interrupt_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_INT_PERR: parity error interrupt
|
||||
\arg USART_INT_TBE: transmitter buffer empty interrupt
|
||||
\arg USART_INT_TC: transmission complete interrupt
|
||||
\arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt
|
||||
\arg USART_INT_IDLE: IDLE line detected interrupt
|
||||
\arg USART_INT_LBD: LIN break detected interrupt
|
||||
\arg USART_INT_ERR: error interrupt
|
||||
\arg USART_INT_CTS: CTS interrupt
|
||||
\arg USART_INT_RT: interrupt enable bit of receive timeout event
|
||||
\arg USART_INT_EB: interrupt enable bit of end of block event
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_interrupt_disable(uint32_t usart_periph, usart_interrupt_enum interrupt)
|
||||
{
|
||||
USART_REG_VAL(usart_periph, interrupt) &= ~BIT(USART_BIT_POS(interrupt));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get USART interrupt and flag status
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] int_flag: USART interrupt flags, refer to usart_interrupt_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_INT_FLAG_PERR: parity error interrupt and flag
|
||||
\arg USART_INT_FLAG_TBE: transmitter buffer empty interrupt and flag
|
||||
\arg USART_INT_FLAG_TC: transmission complete interrupt and flag
|
||||
\arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag
|
||||
\arg USART_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag
|
||||
\arg USART_INT_FLAG_IDLE: IDLE line detected interrupt and flag
|
||||
\arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag
|
||||
\arg USART_INT_FLAG_CTS: CTS interrupt and flag
|
||||
\arg USART_INT_FLAG_ERR_ORERR: error interrupt and overrun error
|
||||
\arg USART_INT_FLAG_ERR_NERR: error interrupt and noise error flag
|
||||
\arg USART_INT_FLAG_ERR_FERR: error interrupt and frame error flag
|
||||
\arg USART_INT_FLAG_EB: interrupt enable bit of end of block event and flag
|
||||
\arg USART_INT_FLAG_RT: interrupt enable bit of receive timeout event and flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, usart_interrupt_flag_enum int_flag)
|
||||
{
|
||||
uint32_t intenable = 0U, flagstatus = 0U;
|
||||
/* 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;
|
||||
} else {
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear USART interrupt flag in STAT0/STAT1 register
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] int_flag: USART interrupt flags, refer to usart_interrupt_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_INT_FLAG_CTS: CTS change flag
|
||||
\arg USART_INT_FLAG_LBD: LIN break detected flag
|
||||
\arg USART_INT_FLAG_TC: transmission complete
|
||||
\arg USART_INT_FLAG_RBNE: read data buffer not empty
|
||||
\arg USART_INT_FLAG_EB: end of block flag
|
||||
\arg USART_INT_FLAG_RT: receiver timeout flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_interrupt_flag_clear(uint32_t usart_periph, usart_interrupt_flag_enum int_flag)
|
||||
{
|
||||
USART_REG_VAL2(usart_periph, int_flag) = ~BIT(USART_BIT_POS2(int_flag));
|
||||
}
|
||||
@@ -0,0 +1,890 @@
|
||||
/*!
|
||||
\file gd32c10x_usart.c
|
||||
\brief USART driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_usart.h"
|
||||
|
||||
/* USART register bit offset */
|
||||
#define GP_GUAT_OFFSET ((uint32_t)8U) /* bit offset of GUAT in USART_GP */
|
||||
#define CTL3_SCRTNUM_OFFSET ((uint32_t)1U) /* bit offset of SCRTNUM in USART_CTL3 */
|
||||
#define RT_BL_OFFSET ((uint32_t)24U) /* bit offset of BL in USART_RT */
|
||||
|
||||
/*!
|
||||
\brief reset USART/UART
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_deinit(uint32_t usart_periph)
|
||||
{
|
||||
switch(usart_periph) {
|
||||
case USART0:
|
||||
/* reset USART0 */
|
||||
rcu_periph_reset_enable(RCU_USART0RST);
|
||||
rcu_periph_reset_disable(RCU_USART0RST);
|
||||
break;
|
||||
case USART1:
|
||||
/* reset USART1 */
|
||||
rcu_periph_reset_enable(RCU_USART1RST);
|
||||
rcu_periph_reset_disable(RCU_USART1RST);
|
||||
break;
|
||||
case USART2:
|
||||
/* reset USART2 */
|
||||
rcu_periph_reset_enable(RCU_USART2RST);
|
||||
rcu_periph_reset_disable(RCU_USART2RST);
|
||||
break;
|
||||
case UART3:
|
||||
/* reset UART3 */
|
||||
rcu_periph_reset_enable(RCU_UART3RST);
|
||||
rcu_periph_reset_disable(RCU_UART3RST);
|
||||
break;
|
||||
case UART4:
|
||||
/* reset UART4 */
|
||||
rcu_periph_reset_enable(RCU_UART4RST);
|
||||
rcu_periph_reset_disable(RCU_UART4RST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART baud rate value
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] baudval: baud rate value
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval)
|
||||
{
|
||||
uint32_t uclk = 0U, intdiv = 0U, fradiv = 0U, udiv = 0U;
|
||||
switch(usart_periph) {
|
||||
/* get clock frequency */
|
||||
case USART0:
|
||||
/* get USART0 clock */
|
||||
uclk = rcu_clock_freq_get(CK_APB2);
|
||||
break;
|
||||
case USART1:
|
||||
/* get USART1 clock */
|
||||
uclk = rcu_clock_freq_get(CK_APB1);
|
||||
break;
|
||||
case USART2:
|
||||
/* get USART2 clock */
|
||||
uclk = rcu_clock_freq_get(CK_APB1);
|
||||
break;
|
||||
case UART3:
|
||||
/* get UART3 clock */
|
||||
uclk = rcu_clock_freq_get(CK_APB1);
|
||||
break;
|
||||
case UART4:
|
||||
/* get UART4 clock */
|
||||
uclk = rcu_clock_freq_get(CK_APB1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* oversampling by 16, configure the value of USART_BAUD */
|
||||
udiv = (uclk + baudval / 2U) / baudval;
|
||||
intdiv = udiv & 0xfff0U;
|
||||
fradiv = udiv & 0xfU;
|
||||
USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART parity
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] paritycfg: configure USART parity
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_PM_NONE: no parity
|
||||
\arg USART_PM_ODD: odd parity
|
||||
\arg USART_PM_EVEN: even parity
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg)
|
||||
{
|
||||
/* clear USART_CTL0 PM,PCEN bits */
|
||||
USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN);
|
||||
/* configure USART parity mode */
|
||||
USART_CTL0(usart_periph) |= paritycfg;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART word length
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] wlen: USART word length configure
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_WL_8BIT: 8 bits
|
||||
\arg USART_WL_9BIT: 9 bits
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_word_length_set(uint32_t usart_periph, uint32_t wlen)
|
||||
{
|
||||
/* clear USART_CTL0 WL bit */
|
||||
USART_CTL0(usart_periph) &= ~USART_CTL0_WL;
|
||||
/* configure USART word length */
|
||||
USART_CTL0(usart_periph) |= wlen;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART stop bit length
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] stblen: USART stop bit configure
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_STB_1BIT: 1 bit
|
||||
\arg USART_STB_0_5BIT: 0.5 bit, not available for UARTx(x=3,4)
|
||||
\arg USART_STB_2BIT: 2 bits
|
||||
\arg USART_STB_1_5BIT: 1.5 bits, not available for UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen)
|
||||
{
|
||||
/* clear USART_CTL1 STB bits */
|
||||
USART_CTL1(usart_periph) &= ~USART_CTL1_STB;
|
||||
/* configure USART stop bits */
|
||||
USART_CTL1(usart_periph) |= stblen;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable USART
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL0(usart_periph) |= USART_CTL0_UEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable USART
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART transmitter
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] txconfig: enable or disable USART transmitter
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_TRANSMIT_ENABLE: enable USART transmission
|
||||
\arg USART_TRANSMIT_DISABLE: disable USART transmission
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig)
|
||||
{
|
||||
USART_CTL0(usart_periph) &= ~(USART_CTL0_TEN);
|
||||
USART_CTL0(usart_periph) |= (USART_CTL0_TEN & txconfig);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART receiver
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] rxconfig: enable or disable USART receiver
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_RECEIVE_ENABLE: enable USART reception
|
||||
\arg USART_RECEIVE_DISABLE: disable USART reception
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig)
|
||||
{
|
||||
USART_CTL0(usart_periph) &= ~(USART_CTL0_REN);
|
||||
USART_CTL0(usart_periph) |= (USART_CTL0_REN & rxconfig);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief data is transmitted/received with the LSB/MSB first
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] msbf: LSB/MSB
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_MSBF_LSB: LSB first
|
||||
\arg USART_MSBF_MSB: MSB first
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_data_first_config(uint32_t usart_periph, uint32_t msbf)
|
||||
{
|
||||
USART_CTL3(usart_periph) &= ~(USART_CTL3_MSBF);
|
||||
USART_CTL3(usart_periph) |= msbf;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART inversion
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] invertpara: refer to enum usart_invert_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_DINV_ENABLE: data bit level inversion
|
||||
\arg USART_DINV_DISABLE: data bit level not inversion
|
||||
\arg USART_TXPIN_ENABLE: TX pin level inversion
|
||||
\arg USART_TXPIN_DISABLE: TX pin level not inversion
|
||||
\arg USART_RXPIN_ENABLE: RX pin level inversion
|
||||
\arg USART_RXPIN_DISABLE: RX pin level not inversion
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara)
|
||||
{
|
||||
/* inverted or not the specified signal */
|
||||
switch(invertpara) {
|
||||
case USART_DINV_ENABLE:
|
||||
/* data bit level inversion */
|
||||
USART_CTL3(usart_periph) |= USART_CTL3_DINV;
|
||||
break;
|
||||
case USART_TXPIN_ENABLE:
|
||||
/* TX pin level inversion */
|
||||
USART_CTL3(usart_periph) |= USART_CTL3_TINV;
|
||||
break;
|
||||
case USART_RXPIN_ENABLE:
|
||||
/* RX pin level inversion */
|
||||
USART_CTL3(usart_periph) |= USART_CTL3_RINV;
|
||||
break;
|
||||
case USART_DINV_DISABLE:
|
||||
/* data bit level not inversion */
|
||||
USART_CTL3(usart_periph) &= ~(USART_CTL3_DINV);
|
||||
break;
|
||||
case USART_TXPIN_DISABLE:
|
||||
/* TX pin level not inversion */
|
||||
USART_CTL3(usart_periph) &= ~(USART_CTL3_TINV);
|
||||
break;
|
||||
case USART_RXPIN_DISABLE:
|
||||
/* RX pin level not inversion */
|
||||
USART_CTL3(usart_periph) &= ~(USART_CTL3_RINV);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable receiver timeout
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_receiver_timeout_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL3(usart_periph) |= USART_CTL3_RTEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable receiver timeout
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_receiver_timeout_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL3(usart_periph) &= ~(USART_CTL3_RTEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure receiver timeout threshold
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] rtimeout: 0-0xFFFFFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rtimeout)
|
||||
{
|
||||
USART_RT(usart_periph) &= ~(USART_RT_RT);
|
||||
USART_RT(usart_periph) |= rtimeout;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief USART transmit data function
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] data: data to be transmitted
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_data_transmit(uint32_t usart_periph, uint16_t data)
|
||||
{
|
||||
USART_DATA(usart_periph) = USART_DATA_DATA & (uint32_t)data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief USART receive data function
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval data of received
|
||||
*/
|
||||
uint16_t usart_data_receive(uint32_t usart_periph)
|
||||
{
|
||||
return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the address of the USART in wake up by address match mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] addr: address of USART/UART
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_address_config(uint32_t usart_periph, uint8_t addr)
|
||||
{
|
||||
USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR);
|
||||
USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & (uint32_t)addr);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable mute mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_mute_mode_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL0(usart_periph) |= USART_CTL0_RWU;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable mute mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_mute_mode_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure wakeup method in mute mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] wmethod: two methods be used to enter or exit the mute mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_WM_IDLE: idle line
|
||||
\arg USART_WM_ADDR: address mask
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod)
|
||||
{
|
||||
USART_CTL0(usart_periph) &= ~(USART_CTL0_WM);
|
||||
USART_CTL0(usart_periph) |= wmethod;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable LIN mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_lin_mode_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL1(usart_periph) |= USART_CTL1_LMEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable LIN mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_lin_mode_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure lin break frame length
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] lblen: lin break frame length
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_LBLEN_10B: 10 bits
|
||||
\arg USART_LBLEN_11B: 11 bits
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen)
|
||||
{
|
||||
USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN);
|
||||
USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief send break frame
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_send_break(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable half duplex mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_halfduplex_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) |= USART_CTL2_HDEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable half duplex mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_halfduplex_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable CK pin in synchronous mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_synchronous_clock_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL1(usart_periph) |= USART_CTL1_CKEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable CK pin in synchronous mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_synchronous_clock_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART synchronous mode parameters
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] clen: CK length
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame
|
||||
\arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame
|
||||
\param[in] cph: clock phase
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_CPH_1CK: first clock transition is the first data capture edge
|
||||
\arg USART_CPH_2CK: second clock transition is the first data capture edge
|
||||
\param[in] cpl: clock polarity
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_CPL_LOW: steady low value on CK pin
|
||||
\arg USART_CPL_HIGH: steady high value on CK pin
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl)
|
||||
{
|
||||
USART_CTL1(usart_periph) &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL);
|
||||
USART_CTL1(usart_periph) |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure guard time value in smartcard mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] guat: guard time value, 0-0xFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_guard_time_config(uint32_t usart_periph, uint8_t guat)
|
||||
{
|
||||
USART_GP(usart_periph) &= ~(USART_GP_GUAT);
|
||||
USART_GP(usart_periph) |= (USART_GP_GUAT & ((uint32_t)guat << GP_GUAT_OFFSET));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable smartcard mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_smartcard_mode_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) |= USART_CTL2_SCEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable smartcard mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_smartcard_mode_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_SCEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable NACK in smartcard mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_smartcard_mode_nack_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) |= USART_CTL2_NKEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable NACK in smartcard mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_smartcard_mode_nack_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_NKEN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure smartcard auto-retry number
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] scrtnum: smartcard auto-retry number
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_smartcard_autoretry_config(uint32_t usart_periph, uint8_t scrtnum)
|
||||
{
|
||||
USART_CTL3(usart_periph) &= ~(USART_CTL3_SCRTNUM);
|
||||
USART_CTL3(usart_periph) |= (USART_CTL3_SCRTNUM & ((uint32_t)scrtnum << CTL3_SCRTNUM_OFFSET));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure block length
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] bl: block length
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_block_length_config(uint32_t usart_periph, uint8_t bl)
|
||||
{
|
||||
USART_RT(usart_periph) &= ~(USART_RT_BL);
|
||||
USART_RT(usart_periph) |= (USART_RT_BL & ((uint32_t)bl << RT_BL_OFFSET));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable IrDA mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_irda_mode_enable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) |= USART_CTL2_IREN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable IrDA mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_irda_mode_disable(uint32_t usart_periph)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_IREN);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the peripheral clock prescaler
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] psc: 0x00-0xFF
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_prescaler_config(uint32_t usart_periph, uint8_t psc)
|
||||
{
|
||||
USART_GP(usart_periph) &= ~(USART_GP_PSC);
|
||||
USART_GP(usart_periph) |= (uint32_t)psc;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure IrDA low-power
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] irlp: IrDA low-power or normal
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_IRLP_LOW: low-power
|
||||
\arg USART_IRLP_NORMAL: normal
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_IRLP);
|
||||
USART_CTL2(usart_periph) |= (USART_CTL2_IRLP & irlp);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure hardware flow control RTS
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] rtsconfig: enable or disable RTS
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_RTS_ENABLE: enable RTS
|
||||
\arg USART_RTS_DISABLE: disable RTS
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_RTSEN);
|
||||
USART_CTL2(usart_periph) |= (USART_CTL2_RTSEN & rtsconfig);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure hardware flow control CTS
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)
|
||||
\param[in] ctsconfig: enable or disable CTS
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_CTS_ENABLE: enable CTS
|
||||
\arg USART_CTS_DISABLE: disable CTS
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_CTSEN);
|
||||
USART_CTL2(usart_periph) |= (USART_CTL2_CTSEN & ctsconfig);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART DMA reception
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3)
|
||||
\param[in] dmaconfig: USART DMA mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_RECEIVE_DMA_ENABLE: enable USART DMA for reception
|
||||
\arg USART_RECEIVE_DMA_DISABLE: disable USART DMA for reception
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_dma_receive_config(uint32_t usart_periph, uint8_t dmaconfig)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_DENR);
|
||||
USART_CTL2(usart_periph) |= (USART_CTL2_DENR & dmaconfig);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure USART DMA transmission
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3)
|
||||
\param[in] dmaconfig: USART DMA mode
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_TRANSMIT_DMA_ENABLE: enable USART DMA for transmission
|
||||
\arg USART_TRANSMIT_DMA_DISABLE: disable USART DMA for transmission
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_dma_transmit_config(uint32_t usart_periph, uint8_t dmaconfig)
|
||||
{
|
||||
USART_CTL2(usart_periph) &= ~(USART_CTL2_DENT);
|
||||
USART_CTL2(usart_periph) |= (USART_CTL2_DENT & dmaconfig);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure hardware flow control coherence mode
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3)
|
||||
\param[in] hcm:
|
||||
\arg USART_RTS_NONE_COHERENCE: nRTS signal equals to the rxne status register
|
||||
\arg USART_RTS_COHERENCE: nRTS signal is set when the last data bit has been sampled
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_hardware_flow_coherence_config(uint32_t usart_periph, uint32_t hcm)
|
||||
{
|
||||
USART_CHC(usart_periph) &= ~(USART_CHC_HCM);
|
||||
USART_CHC(usart_periph) |= (USART_CHC_HCM & hcm);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get flag in STAT0/STAT1 register
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] flag: USART flags, refer to usart_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_FLAG_CTS: CTS change flag
|
||||
\arg USART_FLAG_LBD: LIN break detected flag
|
||||
\arg USART_FLAG_TBE: transmit data buffer empty
|
||||
\arg USART_FLAG_TC: transmission complete
|
||||
\arg USART_FLAG_RBNE: read data buffer not empty
|
||||
\arg USART_FLAG_IDLE: IDLE frame detected flag
|
||||
\arg USART_FLAG_ORERR: overrun error
|
||||
\arg USART_FLAG_NERR: noise error flag
|
||||
\arg USART_FLAG_FERR: frame error flag
|
||||
\arg USART_FLAG_PERR: parity error flag
|
||||
\arg USART_FLAG_BSY: busy flag
|
||||
\arg USART_FLAG_EB: end of block flag
|
||||
\arg USART_FLAG_RT: receiver timeout flag
|
||||
\arg USART_FLAG_EPERR: early parity error flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag)
|
||||
{
|
||||
if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))) {
|
||||
return SET;
|
||||
} else {
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear flag in STAT0/STAT1 register
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] flag: USART flags, refer to usart_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_FLAG_CTS: CTS change flag
|
||||
\arg USART_FLAG_LBD: LIN break detected flag
|
||||
\arg USART_FLAG_TC: transmission complete
|
||||
\arg USART_FLAG_RBNE: read data buffer not empty
|
||||
\arg USART_FLAG_EB: end of block flag
|
||||
\arg USART_FLAG_RT: receiver timeout flag
|
||||
\arg USART_FLAG_EPERR: early parity error flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag)
|
||||
{
|
||||
if(USART_FLAG_EPERR == flag) {
|
||||
USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag));
|
||||
} else {
|
||||
USART_REG_VAL(usart_periph, flag) = ~BIT(USART_BIT_POS(flag));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable USART interrupt
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] interrupt: USART interrupts, refer to usart_interrupt_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_INT_PERR: parity error interrupt
|
||||
\arg USART_INT_TBE: transmitter buffer empty interrupt
|
||||
\arg USART_INT_TC: transmission complete interrupt
|
||||
\arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt
|
||||
\arg USART_INT_IDLE: IDLE line detected interrupt
|
||||
\arg USART_INT_LBD: LIN break detected interrupt
|
||||
\arg USART_INT_ERR: error interrupt
|
||||
\arg USART_INT_CTS: CTS interrupt
|
||||
\arg USART_INT_RT: interrupt enable bit of receive timeout event
|
||||
\arg USART_INT_EB: interrupt enable bit of end of block event
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_interrupt_enable(uint32_t usart_periph, usart_interrupt_enum interrupt)
|
||||
{
|
||||
USART_REG_VAL(usart_periph, interrupt) |= BIT(USART_BIT_POS(interrupt));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief disable USART interrupt
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] interrupt: USART interrupts, refer to usart_interrupt_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_INT_PERR: parity error interrupt
|
||||
\arg USART_INT_TBE: transmitter buffer empty interrupt
|
||||
\arg USART_INT_TC: transmission complete interrupt
|
||||
\arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt
|
||||
\arg USART_INT_IDLE: IDLE line detected interrupt
|
||||
\arg USART_INT_LBD: LIN break detected interrupt
|
||||
\arg USART_INT_ERR: error interrupt
|
||||
\arg USART_INT_CTS: CTS interrupt
|
||||
\arg USART_INT_RT: interrupt enable bit of receive timeout event
|
||||
\arg USART_INT_EB: interrupt enable bit of end of block event
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_interrupt_disable(uint32_t usart_periph, usart_interrupt_enum interrupt)
|
||||
{
|
||||
USART_REG_VAL(usart_periph, interrupt) &= ~BIT(USART_BIT_POS(interrupt));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief get USART interrupt and flag status
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] int_flag: USART interrupt flags, refer to usart_interrupt_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_INT_FLAG_PERR: parity error interrupt and flag
|
||||
\arg USART_INT_FLAG_TBE: transmitter buffer empty interrupt and flag
|
||||
\arg USART_INT_FLAG_TC: transmission complete interrupt and flag
|
||||
\arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag
|
||||
\arg USART_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag
|
||||
\arg USART_INT_FLAG_IDLE: IDLE line detected interrupt and flag
|
||||
\arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag
|
||||
\arg USART_INT_FLAG_CTS: CTS interrupt and flag
|
||||
\arg USART_INT_FLAG_ERR_ORERR: error interrupt and overrun error
|
||||
\arg USART_INT_FLAG_ERR_NERR: error interrupt and noise error flag
|
||||
\arg USART_INT_FLAG_ERR_FERR: error interrupt and frame error flag
|
||||
\arg USART_INT_FLAG_EB: interrupt enable bit of end of block event and flag
|
||||
\arg USART_INT_FLAG_RT: interrupt enable bit of receive timeout event and flag
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, usart_interrupt_flag_enum int_flag)
|
||||
{
|
||||
uint32_t intenable = 0U, flagstatus = 0U;
|
||||
/* 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;
|
||||
} else {
|
||||
return RESET;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear USART interrupt flag in STAT0/STAT1 register
|
||||
\param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4)
|
||||
\param[in] int_flag: USART interrupt flags, refer to usart_interrupt_flag_enum
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg USART_INT_FLAG_CTS: CTS change flag
|
||||
\arg USART_INT_FLAG_LBD: LIN break detected flag
|
||||
\arg USART_INT_FLAG_TC: transmission complete
|
||||
\arg USART_INT_FLAG_RBNE: read data buffer not empty
|
||||
\arg USART_INT_FLAG_EB: end of block flag
|
||||
\arg USART_INT_FLAG_RT: receiver timeout flag
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void usart_interrupt_flag_clear(uint32_t usart_periph, usart_interrupt_flag_enum int_flag)
|
||||
{
|
||||
USART_REG_VAL2(usart_periph, int_flag) = ~BIT(USART_BIT_POS2(int_flag));
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*!
|
||||
\file gd32c10x_wwdgt.c
|
||||
\brief WWDGT driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_wwdgt.h"
|
||||
|
||||
/*!
|
||||
\brief reset the window watchdog timer configuration
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void wwdgt_deinit(void)
|
||||
{
|
||||
rcu_periph_reset_enable(RCU_WWDGTRST);
|
||||
rcu_periph_reset_disable(RCU_WWDGTRST);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief start the window watchdog timer counter
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void wwdgt_enable(void)
|
||||
{
|
||||
WWDGT_CTL |= WWDGT_CTL_WDGTEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the window watchdog timer counter value
|
||||
\param[in] counter_value: 0x00 - 0x7F
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void wwdgt_counter_update(uint16_t counter_value)
|
||||
{
|
||||
WWDGT_CTL = (uint32_t)(CTL_CNT(counter_value));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure counter value, window value, and prescaler divider value
|
||||
\param[in] counter: 0x00 - 0x7F
|
||||
\param[in] window: 0x00 - 0x7F
|
||||
\param[in] prescaler: wwdgt prescaler value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WWDGT_CFG_PSC_DIV1: the time base of window watchdog counter = (PCLK1/4096)/1
|
||||
\arg WWDGT_CFG_PSC_DIV2: the time base of window watchdog counter = (PCLK1/4096)/2
|
||||
\arg WWDGT_CFG_PSC_DIV4: the time base of window watchdog counter = (PCLK1/4096)/4
|
||||
\arg WWDGT_CFG_PSC_DIV8: the time base of window watchdog counter = (PCLK1/4096)/8
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler)
|
||||
{
|
||||
WWDGT_CTL = (uint32_t)(CTL_CNT(counter));
|
||||
WWDGT_CFG = (uint32_t)(CFG_WIN(window) | prescaler);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check early wakeup interrupt state of WWDGT
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus wwdgt_flag_get(void)
|
||||
{
|
||||
if(RESET != (WWDGT_STAT & WWDGT_STAT_EWIF)) {
|
||||
return SET;
|
||||
}
|
||||
|
||||
return RESET;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear early wakeup interrupt state of WWDGT
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void wwdgt_flag_clear(void)
|
||||
{
|
||||
WWDGT_STAT = (uint32_t)(RESET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable early wakeup interrupt of WWDGT
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void wwdgt_interrupt_enable(void)
|
||||
{
|
||||
WWDGT_CFG |= WWDGT_CFG_EWIE;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*!
|
||||
\file gd32c10x_wwdgt.c
|
||||
\brief WWDGT driver
|
||||
|
||||
\version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gd32c10x_wwdgt.h"
|
||||
|
||||
/*!
|
||||
\brief reset the window watchdog timer configuration
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void wwdgt_deinit(void)
|
||||
{
|
||||
rcu_periph_reset_enable(RCU_WWDGTRST);
|
||||
rcu_periph_reset_disable(RCU_WWDGTRST);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief start the window watchdog timer counter
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void wwdgt_enable(void)
|
||||
{
|
||||
WWDGT_CTL |= WWDGT_CTL_WDGTEN;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the window watchdog timer counter value
|
||||
\param[in] counter_value: 0x00 - 0x7F
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void wwdgt_counter_update(uint16_t counter_value)
|
||||
{
|
||||
WWDGT_CTL = (uint32_t)(CTL_CNT(counter_value));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure counter value, window value, and prescaler divider value
|
||||
\param[in] counter: 0x00 - 0x7F
|
||||
\param[in] window: 0x00 - 0x7F
|
||||
\param[in] prescaler: wwdgt prescaler value
|
||||
only one parameter can be selected which is shown as below:
|
||||
\arg WWDGT_CFG_PSC_DIV1: the time base of window watchdog counter = (PCLK1/4096)/1
|
||||
\arg WWDGT_CFG_PSC_DIV2: the time base of window watchdog counter = (PCLK1/4096)/2
|
||||
\arg WWDGT_CFG_PSC_DIV4: the time base of window watchdog counter = (PCLK1/4096)/4
|
||||
\arg WWDGT_CFG_PSC_DIV8: the time base of window watchdog counter = (PCLK1/4096)/8
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler)
|
||||
{
|
||||
WWDGT_CTL = (uint32_t)(CTL_CNT(counter));
|
||||
WWDGT_CFG = (uint32_t)(CFG_WIN(window) | prescaler);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief check early wakeup interrupt state of WWDGT
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval FlagStatus: SET or RESET
|
||||
*/
|
||||
FlagStatus wwdgt_flag_get(void)
|
||||
{
|
||||
if(RESET != (WWDGT_STAT & WWDGT_STAT_EWIF)) {
|
||||
return SET;
|
||||
}
|
||||
|
||||
return RESET;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief clear early wakeup interrupt state of WWDGT
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void wwdgt_flag_clear(void)
|
||||
{
|
||||
WWDGT_STAT = (uint32_t)(RESET);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief enable early wakeup interrupt of WWDGT
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void wwdgt_interrupt_enable(void)
|
||||
{
|
||||
WWDGT_CFG |= WWDGT_CFG_EWIE;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
#ifndef REGIONS_GD32C103CB_H
|
||||
#define REGIONS_GD32C103CB_H
|
||||
|
||||
|
||||
//-------- <<< Use Configuration Wizard in Context Menu >>> --------------------
|
||||
//------ With VS Code: Open Preview for Configuration Wizard -------------------
|
||||
|
||||
// <n> Auto-generated using information from packs
|
||||
// <i> Device Family Pack (DFP): GigaDevice::GD32C10x_DFP@1.0.1
|
||||
|
||||
// <h> ROM Configuration
|
||||
// =======================
|
||||
// <h> __ROM0 (is rx memory: IROM1 from DFP)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region. Default: 0x08000000
|
||||
// <i> Contains Startup and Vector Table
|
||||
#define __ROM0_BASE 0x08000000
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region. Default: 0x00020000
|
||||
#define __ROM0_SIZE 0x00020000
|
||||
// </h>
|
||||
|
||||
// <h> __ROM1 (unused)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region.
|
||||
#define __ROM1_BASE 0x0
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region.
|
||||
#define __ROM1_SIZE 0x0
|
||||
// </h>
|
||||
|
||||
// <h> __ROM2 (unused)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region.
|
||||
#define __ROM2_BASE 0x0
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region.
|
||||
#define __ROM2_SIZE 0x0
|
||||
// </h>
|
||||
|
||||
// <h> __ROM3 (unused)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region.
|
||||
#define __ROM3_BASE 0x0
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region.
|
||||
#define __ROM3_SIZE 0x0
|
||||
// </h>
|
||||
|
||||
// </h>
|
||||
|
||||
// <h> RAM Configuration
|
||||
// =======================
|
||||
// <h> __RAM0 (is rwx memory: IRAM1 from DFP)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region. Default: 0x20000000
|
||||
// <i> Contains uninitialized RAM, Stack, and Heap
|
||||
#define __RAM0_BASE 0x20000000
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region. Default: 0x00008000
|
||||
#define __RAM0_SIZE 0x00008000
|
||||
// </h>
|
||||
|
||||
// <h> __RAM1 (unused)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region.
|
||||
#define __RAM1_BASE 0x0
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region.
|
||||
#define __RAM1_SIZE 0x0
|
||||
// </h>
|
||||
|
||||
// <h> __RAM2 (unused)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region.
|
||||
#define __RAM2_BASE 0x0
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region.
|
||||
#define __RAM2_SIZE 0x0
|
||||
// </h>
|
||||
|
||||
// <h> __RAM3 (unused)
|
||||
// <o> Base address <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines base address of memory region.
|
||||
#define __RAM3_BASE 0x0
|
||||
// <o> Region size [bytes] <0x0-0xFFFFFFFF:8>
|
||||
// <i> Defines size of memory region.
|
||||
#define __RAM3_SIZE 0x0
|
||||
// </h>
|
||||
|
||||
// </h>
|
||||
|
||||
// <h> Stack / Heap Configuration
|
||||
// <o0> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
// <o1> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
#define __STACK_SIZE 0x00000200
|
||||
#define __HEAP_SIZE 0x00000C00
|
||||
// </h>
|
||||
|
||||
|
||||
#endif /* REGIONS_GD32C103CB_H */
|
||||
@@ -0,0 +1,383 @@
|
||||
;/*!
|
||||
; \file startup_gd32c10x.s
|
||||
; \brief start up file
|
||||
;
|
||||
; \version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
;*/
|
||||
;
|
||||
;/* Copyright (c) 2011 - 2012 ARM LIMITED
|
||||
; Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
;
|
||||
; All rights reserved.
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions are met:
|
||||
; - Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
; - Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in the
|
||||
; documentation and/or other materials provided with the distribution.
|
||||
; - Neither the name of ARM nor the names of its contributors may be used
|
||||
; to endorse or promote products derived from this software without
|
||||
; specific prior written permission.
|
||||
; *
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
; ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
; POSSIBILITY OF SUCH DAMAGE.
|
||||
;*/
|
||||
|
||||
;/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */
|
||||
|
||||
; <h> Stack Configuration
|
||||
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
; </h>
|
||||
|
||||
Stack_Size EQU 0x0000800
|
||||
|
||||
AREA STACK, NOINIT, READWRITE, ALIGN=3
|
||||
Stack_Mem SPACE Stack_Size
|
||||
__initial_sp
|
||||
|
||||
|
||||
; <h> Heap Configuration
|
||||
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
; </h>
|
||||
|
||||
Heap_Size EQU 0x00000800
|
||||
|
||||
AREA HEAP, NOINIT, READWRITE, ALIGN=3
|
||||
__heap_base
|
||||
Heap_Mem SPACE Heap_Size
|
||||
__heap_limit
|
||||
|
||||
PRESERVE8
|
||||
THUMB
|
||||
|
||||
; /* reset Vector Mapped to at Address 0 */
|
||||
AREA RESET, DATA, READONLY
|
||||
EXPORT __Vectors
|
||||
EXPORT __Vectors_End
|
||||
EXPORT __Vectors_Size
|
||||
|
||||
__Vectors DCD __initial_sp ; Top of Stack
|
||||
DCD Reset_Handler ; Reset Handler
|
||||
DCD NMI_Handler ; NMI Handler
|
||||
DCD HardFault_Handler ; Hard Fault Handler
|
||||
DCD MemManage_Handler ; MPU Fault Handler
|
||||
DCD BusFault_Handler ; Bus Fault Handler
|
||||
DCD UsageFault_Handler ; Usage Fault Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD SVC_Handler ; SVCall Handler
|
||||
DCD DebugMon_Handler ; Debug Monitor Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD PendSV_Handler ; PendSV Handler
|
||||
DCD SysTick_Handler ; SysTick Handler
|
||||
|
||||
; /* external interrupts handler */
|
||||
DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer
|
||||
DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect
|
||||
DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect
|
||||
DCD RTC_IRQHandler ; 19:RTC through EXTI Line
|
||||
DCD FMC_IRQHandler ; 20:FMC
|
||||
DCD RCU_CTC_IRQHandler ; 21:RCU and CTC
|
||||
DCD EXTI0_IRQHandler ; 22:EXTI Line 0
|
||||
DCD EXTI1_IRQHandler ; 23:EXTI Line 1
|
||||
DCD EXTI2_IRQHandler ; 24:EXTI Line 2
|
||||
DCD EXTI3_IRQHandler ; 25:EXTI Line 3
|
||||
DCD EXTI4_IRQHandler ; 26:EXTI Line 4
|
||||
DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0
|
||||
DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1
|
||||
DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2
|
||||
DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3
|
||||
DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4
|
||||
DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5
|
||||
DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6
|
||||
DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1
|
||||
DCD CAN0_TX_IRQHandler ; 35:CAN0 TX
|
||||
DCD CAN0_RX0_IRQHandler ; 36:CAN0 RX0
|
||||
DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1
|
||||
DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC
|
||||
DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9
|
||||
DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8
|
||||
DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9
|
||||
DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10
|
||||
DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare
|
||||
DCD TIMER1_IRQHandler ; 44:TIMER1
|
||||
DCD TIMER2_IRQHandler ; 45:TIMER2
|
||||
DCD TIMER3_IRQHandler ; 46:TIMER3
|
||||
DCD I2C0_EV_IRQHandler ; 47:I2C0 Event
|
||||
DCD I2C0_ER_IRQHandler ; 48:I2C0 Error
|
||||
DCD I2C1_EV_IRQHandler ; 49:I2C1 Event
|
||||
DCD I2C1_ER_IRQHandler ; 50:I2C1 Error
|
||||
DCD SPI0_IRQHandler ; 51:SPI0
|
||||
DCD SPI1_IRQHandler ; 52:SPI1
|
||||
DCD USART0_IRQHandler ; 53:USART0
|
||||
DCD USART1_IRQHandler ; 54:USART1
|
||||
DCD USART2_IRQHandler ; 55:USART2
|
||||
DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15
|
||||
DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm
|
||||
DCD USBFS_WKUP_IRQHandler ; 58:USBFS Wakeup
|
||||
DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break and TIMER11
|
||||
DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update and TIMER12
|
||||
DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13
|
||||
DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare
|
||||
DCD 0 ; 63:Reserved
|
||||
DCD EXMC_IRQHandler ; 64:EXMC
|
||||
DCD 0 ; 65:Reserved
|
||||
DCD TIMER4_IRQHandler ; 66:TIMER4
|
||||
DCD SPI2_IRQHandler ; 67:SPI2
|
||||
DCD UART3_IRQHandler ; 68:UART3
|
||||
DCD UART4_IRQHandler ; 69:UART4
|
||||
DCD TIMER5_IRQHandler ; 70:TIMER5
|
||||
DCD TIMER6_IRQHandler ; 71:TIMER6
|
||||
DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0
|
||||
DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1
|
||||
DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2
|
||||
DCD DMA1_Channel3_IRQHandler ; 75:DMA1 Channel3
|
||||
DCD DMA1_Channel4_IRQHandler ; 76:DMA1 Channel4
|
||||
DCD 0 ; 77:Reserved
|
||||
DCD 0 ; 78:Reserved
|
||||
DCD CAN1_TX_IRQHandler ; 79:CAN1 TX
|
||||
DCD CAN1_RX0_IRQHandler ; 80:CAN1 RX0
|
||||
DCD CAN1_RX1_IRQHandler ; 81:CAN1 RX1
|
||||
DCD CAN1_EWMC_IRQHandler ; 82:CAN1 EWMC
|
||||
DCD USBFS_IRQHandler ; 83:USBFS
|
||||
|
||||
__Vectors_End
|
||||
|
||||
__Vectors_Size EQU __Vectors_End - __Vectors
|
||||
|
||||
AREA |.text|, CODE, READONLY
|
||||
|
||||
;/* reset Handler */
|
||||
Reset_Handler PROC
|
||||
EXPORT Reset_Handler [WEAK]
|
||||
IMPORT SystemInit
|
||||
IMPORT __main
|
||||
LDR R0, =SystemInit
|
||||
BLX R0
|
||||
LDR R0, =__main
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
;/* dummy Exception Handlers */
|
||||
NMI_Handler PROC
|
||||
EXPORT NMI_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
HardFault_Handler\
|
||||
PROC
|
||||
EXPORT HardFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
MemManage_Handler\
|
||||
PROC
|
||||
EXPORT MemManage_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
BusFault_Handler\
|
||||
PROC
|
||||
EXPORT BusFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
UsageFault_Handler\
|
||||
PROC
|
||||
EXPORT UsageFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
SVC_Handler PROC
|
||||
EXPORT SVC_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
DebugMon_Handler\
|
||||
PROC
|
||||
EXPORT DebugMon_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
PendSV_Handler\
|
||||
PROC
|
||||
EXPORT PendSV_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
SysTick_Handler\
|
||||
PROC
|
||||
EXPORT SysTick_Handler [WEAK]
|
||||
IMPORT delay_decrement
|
||||
LDR R0, =delay_decrement
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
Default_Handler PROC
|
||||
; /* external interrupts handler */
|
||||
EXPORT WWDGT_IRQHandler [WEAK]
|
||||
EXPORT LVD_IRQHandler [WEAK]
|
||||
EXPORT TAMPER_IRQHandler [WEAK]
|
||||
EXPORT RTC_IRQHandler [WEAK]
|
||||
EXPORT FMC_IRQHandler [WEAK]
|
||||
EXPORT RCU_CTC_IRQHandler [WEAK]
|
||||
EXPORT EXTI0_IRQHandler [WEAK]
|
||||
EXPORT EXTI1_IRQHandler [WEAK]
|
||||
EXPORT EXTI2_IRQHandler [WEAK]
|
||||
EXPORT EXTI3_IRQHandler [WEAK]
|
||||
EXPORT EXTI4_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel0_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel1_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel2_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel3_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel4_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel5_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel6_IRQHandler [WEAK]
|
||||
EXPORT ADC0_1_IRQHandler [WEAK]
|
||||
EXPORT CAN0_TX_IRQHandler [WEAK]
|
||||
EXPORT CAN0_RX0_IRQHandler [WEAK]
|
||||
EXPORT CAN0_RX1_IRQHandler [WEAK]
|
||||
EXPORT CAN0_EWMC_IRQHandler [WEAK]
|
||||
EXPORT EXTI5_9_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_Channel_IRQHandler [WEAK]
|
||||
EXPORT TIMER1_IRQHandler [WEAK]
|
||||
EXPORT TIMER2_IRQHandler [WEAK]
|
||||
EXPORT TIMER3_IRQHandler [WEAK]
|
||||
EXPORT I2C0_EV_IRQHandler [WEAK]
|
||||
EXPORT I2C0_ER_IRQHandler [WEAK]
|
||||
EXPORT I2C1_EV_IRQHandler [WEAK]
|
||||
EXPORT I2C1_ER_IRQHandler [WEAK]
|
||||
EXPORT SPI0_IRQHandler [WEAK]
|
||||
EXPORT SPI1_IRQHandler [WEAK]
|
||||
EXPORT USART0_IRQHandler [WEAK]
|
||||
EXPORT USART1_IRQHandler [WEAK]
|
||||
EXPORT USART2_IRQHandler [WEAK]
|
||||
EXPORT EXTI10_15_IRQHandler [WEAK]
|
||||
EXPORT RTC_Alarm_IRQHandler [WEAK]
|
||||
EXPORT USBFS_WKUP_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_Channel_IRQHandler [WEAK]
|
||||
EXPORT EXMC_IRQHandler [WEAK]
|
||||
EXPORT TIMER4_IRQHandler [WEAK]
|
||||
EXPORT SPI2_IRQHandler [WEAK]
|
||||
EXPORT UART3_IRQHandler [WEAK]
|
||||
EXPORT UART4_IRQHandler [WEAK]
|
||||
EXPORT TIMER5_IRQHandler [WEAK]
|
||||
EXPORT TIMER6_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel0_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel1_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel2_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel3_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel4_IRQHandler [WEAK]
|
||||
EXPORT CAN1_TX_IRQHandler [WEAK]
|
||||
EXPORT CAN1_RX0_IRQHandler [WEAK]
|
||||
EXPORT CAN1_RX1_IRQHandler [WEAK]
|
||||
EXPORT CAN1_EWMC_IRQHandler [WEAK]
|
||||
EXPORT USBFS_IRQHandler [WEAK]
|
||||
|
||||
;/* external interrupts handler */
|
||||
WWDGT_IRQHandler
|
||||
LVD_IRQHandler
|
||||
TAMPER_IRQHandler
|
||||
RTC_IRQHandler
|
||||
FMC_IRQHandler
|
||||
RCU_CTC_IRQHandler
|
||||
EXTI0_IRQHandler
|
||||
EXTI1_IRQHandler
|
||||
EXTI2_IRQHandler
|
||||
EXTI3_IRQHandler
|
||||
EXTI4_IRQHandler
|
||||
DMA0_Channel0_IRQHandler
|
||||
DMA0_Channel1_IRQHandler
|
||||
DMA0_Channel2_IRQHandler
|
||||
DMA0_Channel3_IRQHandler
|
||||
DMA0_Channel4_IRQHandler
|
||||
DMA0_Channel5_IRQHandler
|
||||
DMA0_Channel6_IRQHandler
|
||||
ADC0_1_IRQHandler
|
||||
CAN0_TX_IRQHandler
|
||||
CAN0_RX0_IRQHandler
|
||||
CAN0_RX1_IRQHandler
|
||||
CAN0_EWMC_IRQHandler
|
||||
EXTI5_9_IRQHandler
|
||||
TIMER0_BRK_TIMER8_IRQHandler
|
||||
TIMER0_UP_TIMER9_IRQHandler
|
||||
TIMER0_TRG_CMT_TIMER10_IRQHandler
|
||||
TIMER0_Channel_IRQHandler
|
||||
TIMER1_IRQHandler
|
||||
TIMER2_IRQHandler
|
||||
TIMER3_IRQHandler
|
||||
I2C0_EV_IRQHandler
|
||||
I2C0_ER_IRQHandler
|
||||
I2C1_EV_IRQHandler
|
||||
I2C1_ER_IRQHandler
|
||||
SPI0_IRQHandler
|
||||
SPI1_IRQHandler
|
||||
USART0_IRQHandler
|
||||
USART1_IRQHandler
|
||||
USART2_IRQHandler
|
||||
EXTI10_15_IRQHandler
|
||||
RTC_Alarm_IRQHandler
|
||||
USBFS_WKUP_IRQHandler
|
||||
TIMER7_BRK_TIMER11_IRQHandler
|
||||
TIMER7_UP_TIMER12_IRQHandler
|
||||
TIMER7_TRG_CMT_TIMER13_IRQHandler
|
||||
TIMER7_Channel_IRQHandler
|
||||
EXMC_IRQHandler
|
||||
TIMER4_IRQHandler
|
||||
SPI2_IRQHandler
|
||||
UART3_IRQHandler
|
||||
UART4_IRQHandler
|
||||
TIMER5_IRQHandler
|
||||
TIMER6_IRQHandler
|
||||
DMA1_Channel0_IRQHandler
|
||||
DMA1_Channel1_IRQHandler
|
||||
DMA1_Channel2_IRQHandler
|
||||
DMA1_Channel3_IRQHandler
|
||||
DMA1_Channel4_IRQHandler
|
||||
CAN1_TX_IRQHandler
|
||||
CAN1_RX0_IRQHandler
|
||||
CAN1_RX1_IRQHandler
|
||||
CAN1_EWMC_IRQHandler
|
||||
USBFS_IRQHandler
|
||||
|
||||
B .
|
||||
ENDP
|
||||
|
||||
ALIGN
|
||||
|
||||
; user Initial Stack & Heap
|
||||
|
||||
IF :DEF:__MICROLIB
|
||||
|
||||
EXPORT __initial_sp
|
||||
EXPORT __heap_base
|
||||
EXPORT __heap_limit
|
||||
|
||||
ELSE
|
||||
|
||||
IMPORT __use_two_region_memory
|
||||
EXPORT __user_initial_stackheap
|
||||
|
||||
__user_initial_stackheap PROC
|
||||
LDR R0, = Heap_Mem
|
||||
LDR R1, =(Stack_Mem + Stack_Size)
|
||||
LDR R2, = (Heap_Mem + Heap_Size)
|
||||
LDR R3, = Stack_Mem
|
||||
BX LR
|
||||
ENDP
|
||||
|
||||
ALIGN
|
||||
|
||||
ENDIF
|
||||
|
||||
END
|
||||
@@ -0,0 +1,381 @@
|
||||
;/*!
|
||||
; \file startup_gd32c10x.s
|
||||
; \brief start up file
|
||||
;
|
||||
; \version 2025-08-07, V1.6.0, firmware for GD32C10x
|
||||
;*/
|
||||
;
|
||||
;/* Copyright (c) 2011 - 2012 ARM LIMITED
|
||||
; Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
;
|
||||
; All rights reserved.
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions are met:
|
||||
; - Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
; - Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in the
|
||||
; documentation and/or other materials provided with the distribution.
|
||||
; - Neither the name of ARM nor the names of its contributors may be used
|
||||
; to endorse or promote products derived from this software without
|
||||
; specific prior written permission.
|
||||
; *
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
; ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
; POSSIBILITY OF SUCH DAMAGE.
|
||||
;*/
|
||||
|
||||
;/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */
|
||||
|
||||
; <h> Stack Configuration
|
||||
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
; </h>
|
||||
|
||||
Stack_Size EQU 0x0000800
|
||||
|
||||
AREA STACK, NOINIT, READWRITE, ALIGN=3
|
||||
Stack_Mem SPACE Stack_Size
|
||||
__initial_sp
|
||||
|
||||
|
||||
; <h> Heap Configuration
|
||||
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
|
||||
; </h>
|
||||
|
||||
Heap_Size EQU 0x00000800
|
||||
|
||||
AREA HEAP, NOINIT, READWRITE, ALIGN=3
|
||||
__heap_base
|
||||
Heap_Mem SPACE Heap_Size
|
||||
__heap_limit
|
||||
|
||||
PRESERVE8
|
||||
THUMB
|
||||
|
||||
; /* reset Vector Mapped to at Address 0 */
|
||||
AREA RESET, DATA, READONLY
|
||||
EXPORT __Vectors
|
||||
EXPORT __Vectors_End
|
||||
EXPORT __Vectors_Size
|
||||
|
||||
__Vectors DCD __initial_sp ; Top of Stack
|
||||
DCD Reset_Handler ; Reset Handler
|
||||
DCD NMI_Handler ; NMI Handler
|
||||
DCD HardFault_Handler ; Hard Fault Handler
|
||||
DCD MemManage_Handler ; MPU Fault Handler
|
||||
DCD BusFault_Handler ; Bus Fault Handler
|
||||
DCD UsageFault_Handler ; Usage Fault Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD SVC_Handler ; SVCall Handler
|
||||
DCD DebugMon_Handler ; Debug Monitor Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD PendSV_Handler ; PendSV Handler
|
||||
DCD SysTick_Handler ; SysTick Handler
|
||||
|
||||
; /* external interrupts handler */
|
||||
DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer
|
||||
DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect
|
||||
DCD TAMPER_IRQHandler ; 18:Tamper through EXTI Line detect
|
||||
DCD RTC_IRQHandler ; 19:RTC through EXTI Line
|
||||
DCD FMC_IRQHandler ; 20:FMC
|
||||
DCD RCU_CTC_IRQHandler ; 21:RCU and CTC
|
||||
DCD EXTI0_IRQHandler ; 22:EXTI Line 0
|
||||
DCD EXTI1_IRQHandler ; 23:EXTI Line 1
|
||||
DCD EXTI2_IRQHandler ; 24:EXTI Line 2
|
||||
DCD EXTI3_IRQHandler ; 25:EXTI Line 3
|
||||
DCD EXTI4_IRQHandler ; 26:EXTI Line 4
|
||||
DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0
|
||||
DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1
|
||||
DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2
|
||||
DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3
|
||||
DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4
|
||||
DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5
|
||||
DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6
|
||||
DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1
|
||||
DCD CAN0_TX_IRQHandler ; 35:CAN0 TX
|
||||
DCD CAN0_RX0_IRQHandler ; 36:CAN0 RX0
|
||||
DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1
|
||||
DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC
|
||||
DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9
|
||||
DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8
|
||||
DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9
|
||||
DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10
|
||||
DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare
|
||||
DCD TIMER1_IRQHandler ; 44:TIMER1
|
||||
DCD TIMER2_IRQHandler ; 45:TIMER2
|
||||
DCD TIMER3_IRQHandler ; 46:TIMER3
|
||||
DCD I2C0_EV_IRQHandler ; 47:I2C0 Event
|
||||
DCD I2C0_ER_IRQHandler ; 48:I2C0 Error
|
||||
DCD I2C1_EV_IRQHandler ; 49:I2C1 Event
|
||||
DCD I2C1_ER_IRQHandler ; 50:I2C1 Error
|
||||
DCD SPI0_IRQHandler ; 51:SPI0
|
||||
DCD SPI1_IRQHandler ; 52:SPI1
|
||||
DCD USART0_IRQHandler ; 53:USART0
|
||||
DCD USART1_IRQHandler ; 54:USART1
|
||||
DCD USART2_IRQHandler ; 55:USART2
|
||||
DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15
|
||||
DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm
|
||||
DCD USBFS_WKUP_IRQHandler ; 58:USBFS Wakeup
|
||||
DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break and TIMER11
|
||||
DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update and TIMER12
|
||||
DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13
|
||||
DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare
|
||||
DCD 0 ; 63:Reserved
|
||||
DCD EXMC_IRQHandler ; 64:EXMC
|
||||
DCD 0 ; 65:Reserved
|
||||
DCD TIMER4_IRQHandler ; 66:TIMER4
|
||||
DCD SPI2_IRQHandler ; 67:SPI2
|
||||
DCD UART3_IRQHandler ; 68:UART3
|
||||
DCD UART4_IRQHandler ; 69:UART4
|
||||
DCD TIMER5_IRQHandler ; 70:TIMER5
|
||||
DCD TIMER6_IRQHandler ; 71:TIMER6
|
||||
DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0
|
||||
DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1
|
||||
DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2
|
||||
DCD DMA1_Channel3_IRQHandler ; 75:DMA1 Channel3
|
||||
DCD DMA1_Channel4_IRQHandler ; 76:DMA1 Channel4
|
||||
DCD 0 ; 77:Reserved
|
||||
DCD 0 ; 78:Reserved
|
||||
DCD CAN1_TX_IRQHandler ; 79:CAN1 TX
|
||||
DCD CAN1_RX0_IRQHandler ; 80:CAN1 RX0
|
||||
DCD CAN1_RX1_IRQHandler ; 81:CAN1 RX1
|
||||
DCD CAN1_EWMC_IRQHandler ; 82:CAN1 EWMC
|
||||
DCD USBFS_IRQHandler ; 83:USBFS
|
||||
|
||||
__Vectors_End
|
||||
|
||||
__Vectors_Size EQU __Vectors_End - __Vectors
|
||||
|
||||
AREA |.text|, CODE, READONLY
|
||||
|
||||
;/* reset Handler */
|
||||
Reset_Handler PROC
|
||||
EXPORT Reset_Handler [WEAK]
|
||||
IMPORT SystemInit
|
||||
IMPORT __main
|
||||
LDR R0, =SystemInit
|
||||
BLX R0
|
||||
LDR R0, =__main
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
;/* dummy Exception Handlers */
|
||||
NMI_Handler PROC
|
||||
EXPORT NMI_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
HardFault_Handler\
|
||||
PROC
|
||||
EXPORT HardFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
MemManage_Handler\
|
||||
PROC
|
||||
EXPORT MemManage_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
BusFault_Handler\
|
||||
PROC
|
||||
EXPORT BusFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
UsageFault_Handler\
|
||||
PROC
|
||||
EXPORT UsageFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
SVC_Handler PROC
|
||||
EXPORT SVC_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
DebugMon_Handler\
|
||||
PROC
|
||||
EXPORT DebugMon_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
PendSV_Handler\
|
||||
PROC
|
||||
EXPORT PendSV_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
SysTick_Handler\
|
||||
PROC
|
||||
EXPORT SysTick_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
Default_Handler PROC
|
||||
; /* external interrupts handler */
|
||||
EXPORT WWDGT_IRQHandler [WEAK]
|
||||
EXPORT LVD_IRQHandler [WEAK]
|
||||
EXPORT TAMPER_IRQHandler [WEAK]
|
||||
EXPORT RTC_IRQHandler [WEAK]
|
||||
EXPORT FMC_IRQHandler [WEAK]
|
||||
EXPORT RCU_CTC_IRQHandler [WEAK]
|
||||
EXPORT EXTI0_IRQHandler [WEAK]
|
||||
EXPORT EXTI1_IRQHandler [WEAK]
|
||||
EXPORT EXTI2_IRQHandler [WEAK]
|
||||
EXPORT EXTI3_IRQHandler [WEAK]
|
||||
EXPORT EXTI4_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel0_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel1_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel2_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel3_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel4_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel5_IRQHandler [WEAK]
|
||||
EXPORT DMA0_Channel6_IRQHandler [WEAK]
|
||||
EXPORT ADC0_1_IRQHandler [WEAK]
|
||||
EXPORT CAN0_TX_IRQHandler [WEAK]
|
||||
EXPORT CAN0_RX0_IRQHandler [WEAK]
|
||||
EXPORT CAN0_RX1_IRQHandler [WEAK]
|
||||
EXPORT CAN0_EWMC_IRQHandler [WEAK]
|
||||
EXPORT EXTI5_9_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_BRK_TIMER8_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_UP_TIMER9_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_TRG_CMT_TIMER10_IRQHandler [WEAK]
|
||||
EXPORT TIMER0_Channel_IRQHandler [WEAK]
|
||||
EXPORT TIMER1_IRQHandler [WEAK]
|
||||
EXPORT TIMER2_IRQHandler [WEAK]
|
||||
EXPORT TIMER3_IRQHandler [WEAK]
|
||||
EXPORT I2C0_EV_IRQHandler [WEAK]
|
||||
EXPORT I2C0_ER_IRQHandler [WEAK]
|
||||
EXPORT I2C1_EV_IRQHandler [WEAK]
|
||||
EXPORT I2C1_ER_IRQHandler [WEAK]
|
||||
EXPORT SPI0_IRQHandler [WEAK]
|
||||
EXPORT SPI1_IRQHandler [WEAK]
|
||||
EXPORT USART0_IRQHandler [WEAK]
|
||||
EXPORT USART1_IRQHandler [WEAK]
|
||||
EXPORT USART2_IRQHandler [WEAK]
|
||||
EXPORT EXTI10_15_IRQHandler [WEAK]
|
||||
EXPORT RTC_Alarm_IRQHandler [WEAK]
|
||||
EXPORT USBFS_WKUP_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_BRK_TIMER11_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_UP_TIMER12_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_TRG_CMT_TIMER13_IRQHandler [WEAK]
|
||||
EXPORT TIMER7_Channel_IRQHandler [WEAK]
|
||||
EXPORT EXMC_IRQHandler [WEAK]
|
||||
EXPORT TIMER4_IRQHandler [WEAK]
|
||||
EXPORT SPI2_IRQHandler [WEAK]
|
||||
EXPORT UART3_IRQHandler [WEAK]
|
||||
EXPORT UART4_IRQHandler [WEAK]
|
||||
EXPORT TIMER5_IRQHandler [WEAK]
|
||||
EXPORT TIMER6_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel0_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel1_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel2_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel3_IRQHandler [WEAK]
|
||||
EXPORT DMA1_Channel4_IRQHandler [WEAK]
|
||||
EXPORT CAN1_TX_IRQHandler [WEAK]
|
||||
EXPORT CAN1_RX0_IRQHandler [WEAK]
|
||||
EXPORT CAN1_RX1_IRQHandler [WEAK]
|
||||
EXPORT CAN1_EWMC_IRQHandler [WEAK]
|
||||
EXPORT USBFS_IRQHandler [WEAK]
|
||||
|
||||
;/* external interrupts handler */
|
||||
WWDGT_IRQHandler
|
||||
LVD_IRQHandler
|
||||
TAMPER_IRQHandler
|
||||
RTC_IRQHandler
|
||||
FMC_IRQHandler
|
||||
RCU_CTC_IRQHandler
|
||||
EXTI0_IRQHandler
|
||||
EXTI1_IRQHandler
|
||||
EXTI2_IRQHandler
|
||||
EXTI3_IRQHandler
|
||||
EXTI4_IRQHandler
|
||||
DMA0_Channel0_IRQHandler
|
||||
DMA0_Channel1_IRQHandler
|
||||
DMA0_Channel2_IRQHandler
|
||||
DMA0_Channel3_IRQHandler
|
||||
DMA0_Channel4_IRQHandler
|
||||
DMA0_Channel5_IRQHandler
|
||||
DMA0_Channel6_IRQHandler
|
||||
ADC0_1_IRQHandler
|
||||
CAN0_TX_IRQHandler
|
||||
CAN0_RX0_IRQHandler
|
||||
CAN0_RX1_IRQHandler
|
||||
CAN0_EWMC_IRQHandler
|
||||
EXTI5_9_IRQHandler
|
||||
TIMER0_BRK_TIMER8_IRQHandler
|
||||
TIMER0_UP_TIMER9_IRQHandler
|
||||
TIMER0_TRG_CMT_TIMER10_IRQHandler
|
||||
TIMER0_Channel_IRQHandler
|
||||
TIMER1_IRQHandler
|
||||
TIMER2_IRQHandler
|
||||
TIMER3_IRQHandler
|
||||
I2C0_EV_IRQHandler
|
||||
I2C0_ER_IRQHandler
|
||||
I2C1_EV_IRQHandler
|
||||
I2C1_ER_IRQHandler
|
||||
SPI0_IRQHandler
|
||||
SPI1_IRQHandler
|
||||
USART0_IRQHandler
|
||||
USART1_IRQHandler
|
||||
USART2_IRQHandler
|
||||
EXTI10_15_IRQHandler
|
||||
RTC_Alarm_IRQHandler
|
||||
USBFS_WKUP_IRQHandler
|
||||
TIMER7_BRK_TIMER11_IRQHandler
|
||||
TIMER7_UP_TIMER12_IRQHandler
|
||||
TIMER7_TRG_CMT_TIMER13_IRQHandler
|
||||
TIMER7_Channel_IRQHandler
|
||||
EXMC_IRQHandler
|
||||
TIMER4_IRQHandler
|
||||
SPI2_IRQHandler
|
||||
UART3_IRQHandler
|
||||
UART4_IRQHandler
|
||||
TIMER5_IRQHandler
|
||||
TIMER6_IRQHandler
|
||||
DMA1_Channel0_IRQHandler
|
||||
DMA1_Channel1_IRQHandler
|
||||
DMA1_Channel2_IRQHandler
|
||||
DMA1_Channel3_IRQHandler
|
||||
DMA1_Channel4_IRQHandler
|
||||
CAN1_TX_IRQHandler
|
||||
CAN1_RX0_IRQHandler
|
||||
CAN1_RX1_IRQHandler
|
||||
CAN1_EWMC_IRQHandler
|
||||
USBFS_IRQHandler
|
||||
|
||||
B .
|
||||
ENDP
|
||||
|
||||
ALIGN
|
||||
|
||||
; user Initial Stack & Heap
|
||||
|
||||
IF :DEF:__MICROLIB
|
||||
|
||||
EXPORT __initial_sp
|
||||
EXPORT __heap_base
|
||||
EXPORT __heap_limit
|
||||
|
||||
ELSE
|
||||
|
||||
IMPORT __use_two_region_memory
|
||||
EXPORT __user_initial_stackheap
|
||||
|
||||
__user_initial_stackheap PROC
|
||||
LDR R0, = Heap_Mem
|
||||
LDR R1, =(Stack_Mem + Stack_Size)
|
||||
LDR R2, = (Heap_Mem + Heap_Size)
|
||||
LDR R3, = Stack_Mem
|
||||
BX LR
|
||||
ENDP
|
||||
|
||||
ALIGN
|
||||
|
||||
ENDIF
|
||||
|
||||
END
|
||||
@@ -0,0 +1,947 @@
|
||||
/*!
|
||||
\file system_gd32c10x.c
|
||||
\brief CMSIS Cortex-M4 Device Peripheral Access Layer Source File for
|
||||
GD32C10x Device Series
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2009 - 2014 ARM LIMITED
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of ARM nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
*
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */
|
||||
|
||||
#include "gd32c10x.h"
|
||||
|
||||
/* system frequency define */
|
||||
#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */
|
||||
#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */
|
||||
#define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */
|
||||
|
||||
/* Vector Table base offset */
|
||||
#define VECT_TAB_OFFSET 0x00 /* This value must be a multiple of 0x200. */
|
||||
|
||||
/* select a system clock by uncommenting the following line */
|
||||
/* use IRC8M */
|
||||
// #define __SYSTEM_CLOCK_IRC8M (uint32_t)(__IRC8M)
|
||||
// #define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000)
|
||||
//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000)
|
||||
//#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000)
|
||||
// #define __SYSTEM_CLOCK_120M_PLL_IRC8M (uint32_t)(120000000)
|
||||
|
||||
/* use HXTAL(CK_HXTAL = 8M) */
|
||||
// #define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL)
|
||||
// #define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000)
|
||||
//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000)
|
||||
//#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000)
|
||||
#define __SYSTEM_CLOCK_120M_PLL_HXTAL (uint32_t)(120000000)
|
||||
|
||||
/* The following is to prevent Vcore fluctuations caused by frequency switching.
|
||||
It is strongly recommended to include it to avoid issues caused by self-removal. */
|
||||
#define RCU_MODIFY_4(__delay) do{ \
|
||||
volatile uint32_t i, reg; \
|
||||
if(0 != __delay){ \
|
||||
/* Insert a software delay */ \
|
||||
for(i=0; i<__delay; i++){ \
|
||||
} \
|
||||
reg = RCU_CFG0; \
|
||||
reg &= ~(RCU_CFG0_AHBPSC); \
|
||||
reg |= RCU_AHB_CKSYS_DIV2; \
|
||||
/* AHB = SYSCLK/2 */ \
|
||||
RCU_CFG0 = reg; \
|
||||
/* Insert a software delay */ \
|
||||
for(i=0; i<__delay; i++){ \
|
||||
} \
|
||||
reg = RCU_CFG0; \
|
||||
reg &= ~(RCU_CFG0_AHBPSC); \
|
||||
reg |= RCU_AHB_CKSYS_DIV4; \
|
||||
/* AHB = SYSCLK/4 */ \
|
||||
RCU_CFG0 = reg; \
|
||||
/* Insert a software delay */ \
|
||||
for(i=0; i<__delay; i++){ \
|
||||
} \
|
||||
reg = RCU_CFG0; \
|
||||
reg &= ~(RCU_CFG0_AHBPSC); \
|
||||
reg |= RCU_AHB_CKSYS_DIV8; \
|
||||
/* AHB = SYSCLK/8 */ \
|
||||
RCU_CFG0 = reg; \
|
||||
/* Insert a software delay */ \
|
||||
for(i=0; i<__delay; i++){ \
|
||||
} \
|
||||
reg = RCU_CFG0; \
|
||||
reg &= ~(RCU_CFG0_AHBPSC); \
|
||||
reg |= RCU_AHB_CKSYS_DIV16; \
|
||||
/* AHB = SYSCLK/16 */ \
|
||||
RCU_CFG0 = reg; \
|
||||
/* Insert a software delay */ \
|
||||
for(i=0; i<__delay; i++){ \
|
||||
} \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
#define SEL_IRC8M 0x00U
|
||||
#define SEL_HXTAL 0x01U
|
||||
#define SEL_PLL 0x02U
|
||||
|
||||
/* set the system clock frequency and declare the system clock configuration function */
|
||||
#ifdef __SYSTEM_CLOCK_IRC8M
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC8M;
|
||||
static void system_clock_8m_irc8m(void);
|
||||
#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_IRC8M;
|
||||
static void system_clock_48m_irc8m(void);
|
||||
#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M;
|
||||
static void system_clock_72m_irc8m(void);
|
||||
#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_IRC8M;
|
||||
static void system_clock_108m_irc8m(void);
|
||||
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_IRC8M;
|
||||
static void system_clock_120m_irc8m(void);
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_HXTAL)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL;
|
||||
static void system_clock_hxtal(void);
|
||||
#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL;
|
||||
static void system_clock_48m_hxtal(void);
|
||||
#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL;
|
||||
static void system_clock_72m_hxtal(void);
|
||||
#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL;
|
||||
static void system_clock_108m_hxtal(void);
|
||||
#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_HXTAL;
|
||||
static void system_clock_120m_hxtal(void);
|
||||
#endif /* __SYSTEM_CLOCK_IRC8M */
|
||||
|
||||
/* configure the system clock */
|
||||
static void system_clock_config(void);
|
||||
|
||||
/* software delay to prevent the impact of Vcore fluctuations.
|
||||
It is strongly recommended to include it to avoid issues caused by self-removal. */
|
||||
static void _soft_delay_(uint32_t time)
|
||||
{
|
||||
__IO uint32_t i;
|
||||
for(i=0; i<time*10; i++){
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief setup the micro controller system, initialize the system
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void SystemInit (void)
|
||||
{
|
||||
/* FPU settings */
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
|
||||
#endif
|
||||
/* reset the RCU clock configuration to the default reset state */
|
||||
/* Set IRC8MEN bit */
|
||||
RCU_CTL |= RCU_CTL_IRC8MEN;
|
||||
while(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) {
|
||||
}
|
||||
if(((RCU_CFG0 & RCU_CFG0_SCSS) == RCU_SCSS_PLL)){
|
||||
RCU_MODIFY_4(0x50);
|
||||
}
|
||||
|
||||
RCU_CFG0 &= ~RCU_CFG0_SCS;
|
||||
_soft_delay_(200);
|
||||
|
||||
/* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */
|
||||
RCU_CTL &= ~(RCU_CTL_PLLEN |RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);
|
||||
/* disable all interrupts */
|
||||
RCU_INT = 0x00ff0000U;
|
||||
|
||||
/* Reset CFG0 and CFG1 registers */
|
||||
RCU_CFG0 = 0x00000000U;
|
||||
RCU_CFG1 = 0x00000000U;
|
||||
|
||||
/* reset HXTALBPS bit */
|
||||
RCU_CTL &= ~(RCU_CTL_HXTALBPS);
|
||||
|
||||
/* configure the system clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */
|
||||
system_clock_config();
|
||||
|
||||
#ifdef VECT_TAB_SRAM
|
||||
nvic_vector_table_set(NVIC_VECTTAB_RAM,VECT_TAB_OFFSET);
|
||||
#else
|
||||
nvic_vector_table_set(NVIC_VECTTAB_FLASH,VECT_TAB_OFFSET);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the system clock
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_config(void)
|
||||
{
|
||||
#ifdef __SYSTEM_CLOCK_IRC8M
|
||||
system_clock_8m_irc8m();
|
||||
#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M)
|
||||
system_clock_48m_irc8m();
|
||||
#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
|
||||
system_clock_72m_irc8m();
|
||||
#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M)
|
||||
system_clock_108m_irc8m();
|
||||
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M)
|
||||
system_clock_120m_irc8m();
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_HXTAL)
|
||||
system_clock_hxtal();
|
||||
#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
|
||||
system_clock_48m_hxtal();
|
||||
#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
|
||||
system_clock_72m_hxtal();
|
||||
#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
|
||||
system_clock_108m_hxtal();
|
||||
#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL)
|
||||
system_clock_120m_hxtal();
|
||||
#endif /* __SYSTEM_CLOCK_IRC8M */
|
||||
}
|
||||
|
||||
#ifdef __SYSTEM_CLOCK_IRC8M
|
||||
/*!
|
||||
\brief configure the system clock to 8M by IRC8M
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_8m_irc8m(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable IRC8M */
|
||||
RCU_CTL |= RCU_CTL_IRC8MEN;
|
||||
|
||||
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
|
||||
}
|
||||
while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select IRC8M as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_IRC8M;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until IRC8M is selected as system clock */
|
||||
while(0U != (RCU_CFG0 & RCU_SCSS_IRC8M)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M)
|
||||
/*!
|
||||
\brief configure the system clock to 48M by PLL which selects IRC8M as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_48m_irc8m(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable IRC8M */
|
||||
RCU_CTL |= RCU_CTL_IRC8MEN;
|
||||
|
||||
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
|
||||
}
|
||||
while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_1;
|
||||
|
||||
/* IRC8M is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_IRC8M/2) * 12 = 48 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= RCU_PLL_MUL12;
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
|
||||
/*!
|
||||
\brief configure the system clock to 72M by PLL which selects IRC8M as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_72m_irc8m(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable IRC8M */
|
||||
RCU_CTL |= RCU_CTL_IRC8MEN;
|
||||
|
||||
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
|
||||
}while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_2;
|
||||
|
||||
/* IRC8M is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= RCU_PLL_MUL18;
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M)
|
||||
/*!
|
||||
\brief configure the system clock to 108M by PLL which selects IRC8M as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_108m_irc8m(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable IRC8M */
|
||||
RCU_CTL |= RCU_CTL_IRC8MEN;
|
||||
|
||||
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
|
||||
}while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_3;
|
||||
|
||||
/* IRC8M is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_IRC8M/2) * 27 = 108 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= RCU_PLL_MUL27;
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M)
|
||||
/*!
|
||||
\brief configure the system clock to 120M by PLL which selects IRC8M as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_120m_irc8m(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable IRC8M */
|
||||
RCU_CTL |= RCU_CTL_IRC8MEN;
|
||||
|
||||
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
|
||||
}while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_3;
|
||||
|
||||
/* IRC8M is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_IRC8M/2) * 30 = 120 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= RCU_PLL_MUL30;
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_HXTAL)
|
||||
/*!
|
||||
\brief configure the system clock to HXTAL
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_hxtal(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable HXTAL */
|
||||
RCU_CTL |= RCU_CTL_HXTALEN;
|
||||
|
||||
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
||||
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select HXTAL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_HXTAL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until HXTAL is selected as system clock */
|
||||
while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
|
||||
/*!
|
||||
\brief configure the system clock to 48M by PLL which selects HXTAL(8M) as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_48m_hxtal(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable HXTAL */
|
||||
RCU_CTL |= RCU_CTL_HXTALEN;
|
||||
|
||||
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
||||
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_1;
|
||||
|
||||
/* HXTAL is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_PREDIV0) * 12 = 48 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL12);
|
||||
|
||||
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
|
||||
|
||||
/* CK_PREDIV0 = (CK_HXTAL)/2 *10 /10 = 4 MHz */
|
||||
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL10 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV10);
|
||||
|
||||
/* enable PLL1 */
|
||||
RCU_CTL |= RCU_CTL_PLL1EN;
|
||||
/* wait till PLL1 is ready */
|
||||
while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
|
||||
}
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
|
||||
/*!
|
||||
\brief configure the system clock to 72M by PLL which selects HXTAL(8M) as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_72m_hxtal(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable HXTAL */
|
||||
RCU_CTL |= RCU_CTL_HXTALEN;
|
||||
|
||||
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
||||
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_2;
|
||||
|
||||
/* HXTAL is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL18);
|
||||
|
||||
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
|
||||
|
||||
/* CK_PREDIV0 = (CK_HXTAL)/2 *10 /10 = 4 MHz */
|
||||
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL10 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV10);
|
||||
|
||||
/* enable PLL1 */
|
||||
RCU_CTL |= RCU_CTL_PLL1EN;
|
||||
/* wait till PLL1 is ready */
|
||||
while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
|
||||
}
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
|
||||
/*!
|
||||
\brief configure the system clock to 108M by PLL which selects HXTAL(8M) as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_108m_hxtal(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable HXTAL */
|
||||
RCU_CTL |= RCU_CTL_HXTALEN;
|
||||
|
||||
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
||||
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_3;
|
||||
|
||||
/* HXTAL is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL27);
|
||||
|
||||
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
|
||||
|
||||
/* CK_PREDIV0 = (CK_HXTAL)/2 *10 /10 = 4 MHz */
|
||||
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL10 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV10);
|
||||
|
||||
/* enable PLL1 */
|
||||
RCU_CTL |= RCU_CTL_PLL1EN;
|
||||
/* wait till PLL1 is ready */
|
||||
while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
|
||||
}
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL)
|
||||
/*!
|
||||
\brief configure the system clock to 120M by PLL which selects HXTAL(8M) as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_120m_hxtal(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable HXTAL */
|
||||
RCU_CTL |= RCU_CTL_HXTALEN;
|
||||
|
||||
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
||||
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_3;
|
||||
|
||||
/* HXTAL is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_PREDIV0) * 30 = 120 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL30);
|
||||
|
||||
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
|
||||
|
||||
/* CK_PREDIV0 = (CK_HXTAL)/2 *10 /10 = 4 MHz */
|
||||
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL10 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV10);
|
||||
|
||||
/* enable PLL1 */
|
||||
RCU_CTL |= RCU_CTL_PLL1EN;
|
||||
/* wait till PLL1 is ready */
|
||||
while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){
|
||||
}
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
#endif /* __SYSTEM_CLOCK_IRC8M */
|
||||
|
||||
/*!
|
||||
\brief update the SystemCoreClock with current core clock retrieved from cpu registers
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void SystemCoreClockUpdate (void)
|
||||
{
|
||||
uint32_t sws = 0U;
|
||||
uint32_t pllsel = 0U, pllpresel = 0U, predv0sel = 0U, pllmf,ck_src = 0U;
|
||||
uint32_t predv0 = 0U, predv1 = 0U, pll1mf = 0U,idx = 0U,clk_exp = 0U;
|
||||
/* exponent of AHB clock divider */
|
||||
const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
||||
|
||||
sws = GET_BITS(RCU_CFG0, 2, 3);
|
||||
switch(sws){
|
||||
/* IRC8M is selected as CK_SYS */
|
||||
case SEL_IRC8M:
|
||||
SystemCoreClock = IRC8M_VALUE;
|
||||
break;
|
||||
/* HXTAL is selected as CK_SYS */
|
||||
case SEL_HXTAL:
|
||||
SystemCoreClock = HXTAL_VALUE;
|
||||
break;
|
||||
/* PLL is selected as CK_SYS */
|
||||
case SEL_PLL:
|
||||
/* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */
|
||||
pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
|
||||
|
||||
if(RCU_PLLSRC_HXTAL_IRC48M == pllsel){
|
||||
/* PLL clock source is HXTAL or IRC48M */
|
||||
pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL);
|
||||
|
||||
if(RCU_PLLPRESRC_HXTAL == pllpresel){
|
||||
/* PLL clock source is HXTAL */
|
||||
ck_src = HXTAL_VALUE;
|
||||
}else{
|
||||
/* PLL clock source is IRC48 */
|
||||
ck_src = IRC48M_VALUE;
|
||||
}
|
||||
|
||||
predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL);
|
||||
/* source clock use PLL1 */
|
||||
if(RCU_PREDV0SRC_CKPLL1 == predv0sel){
|
||||
predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U;
|
||||
pll1mf = ((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U;
|
||||
if(17U == pll1mf){
|
||||
pll1mf = 20U;
|
||||
}
|
||||
ck_src = (ck_src/predv1)*pll1mf;
|
||||
}
|
||||
predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U;
|
||||
ck_src /= predv0;
|
||||
}else{
|
||||
/* PLL clock source is IRC8M/2 */
|
||||
ck_src = IRC8M_VALUE/2U;
|
||||
}
|
||||
|
||||
/* PLL multiplication factor */
|
||||
pllmf = GET_BITS(RCU_CFG0, 18, 21);
|
||||
if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){
|
||||
pllmf |= 0x10U;
|
||||
}
|
||||
if(pllmf < 15U){
|
||||
pllmf += 2U;
|
||||
}else{
|
||||
pllmf += 1U;
|
||||
}
|
||||
SystemCoreClock = ck_src*pllmf;
|
||||
if(15U == pllmf){
|
||||
SystemCoreClock = ck_src*6U + ck_src/2U;
|
||||
}
|
||||
|
||||
break;
|
||||
/* IRC8M is selected as CK_SYS */
|
||||
default:
|
||||
SystemCoreClock = IRC8M_VALUE;
|
||||
break;
|
||||
}
|
||||
/* calculate AHB clock frequency */
|
||||
idx = GET_BITS(RCU_CFG0, 4, 7);
|
||||
clk_exp = ahb_exp[idx];
|
||||
SystemCoreClock >>= clk_exp;
|
||||
}
|
||||
|
||||
#ifdef __FIRMWARE_VERSION_DEFINE
|
||||
/*!
|
||||
\brief get firmware version
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval firmware version
|
||||
*/
|
||||
uint32_t gd32c10x_firmware_version_get(void)
|
||||
{
|
||||
return __GD32C10X_STDPERIPH_VERSION;
|
||||
}
|
||||
#endif /* __FIRMWARE_VERSION_DEFINE */
|
||||
@@ -0,0 +1,947 @@
|
||||
/*!
|
||||
\file system_gd32c10x.c
|
||||
\brief CMSIS Cortex-M4 Device Peripheral Access Layer Source File for
|
||||
GD32C10x Device Series
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2009 - 2014 ARM LIMITED
|
||||
Copyright (c) 2025, GigaDevice Semiconductor Inc.
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of ARM nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
*
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* This file refers the CMSIS standard, some adjustments are made according to GigaDevice chips */
|
||||
|
||||
#include "gd32c10x.h"
|
||||
|
||||
/* system frequency define */
|
||||
#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */
|
||||
#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */
|
||||
#define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */
|
||||
|
||||
/* Vector Table base offset */
|
||||
#define VECT_TAB_OFFSET 0x00 /* This value must be a multiple of 0x200. */
|
||||
|
||||
/* select a system clock by uncommenting the following line */
|
||||
/* use IRC8M */
|
||||
//#define __SYSTEM_CLOCK_IRC8M (uint32_t)(__IRC8M)
|
||||
//#define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000)
|
||||
//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000)
|
||||
//#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000)
|
||||
//#define __SYSTEM_CLOCK_120M_PLL_IRC8M (uint32_t)(120000000)
|
||||
|
||||
/* use HXTAL(CK_HXTAL = 8M) */
|
||||
//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL)
|
||||
//#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000)
|
||||
//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000)
|
||||
//#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000)
|
||||
#define __SYSTEM_CLOCK_120M_PLL_HXTAL (uint32_t)(120000000)
|
||||
|
||||
/* The following is to prevent Vcore fluctuations caused by frequency switching.
|
||||
It is strongly recommended to include it to avoid issues caused by self-removal. */
|
||||
#define RCU_MODIFY_4(__delay) do{ \
|
||||
volatile uint32_t i, reg; \
|
||||
if(0 != __delay){ \
|
||||
/* Insert a software delay */ \
|
||||
for(i=0; i<__delay; i++){ \
|
||||
} \
|
||||
reg = RCU_CFG0; \
|
||||
reg &= ~(RCU_CFG0_AHBPSC); \
|
||||
reg |= RCU_AHB_CKSYS_DIV2; \
|
||||
/* AHB = SYSCLK/2 */ \
|
||||
RCU_CFG0 = reg; \
|
||||
/* Insert a software delay */ \
|
||||
for(i=0; i<__delay; i++){ \
|
||||
} \
|
||||
reg = RCU_CFG0; \
|
||||
reg &= ~(RCU_CFG0_AHBPSC); \
|
||||
reg |= RCU_AHB_CKSYS_DIV4; \
|
||||
/* AHB = SYSCLK/4 */ \
|
||||
RCU_CFG0 = reg; \
|
||||
/* Insert a software delay */ \
|
||||
for(i=0; i<__delay; i++){ \
|
||||
} \
|
||||
reg = RCU_CFG0; \
|
||||
reg &= ~(RCU_CFG0_AHBPSC); \
|
||||
reg |= RCU_AHB_CKSYS_DIV8; \
|
||||
/* AHB = SYSCLK/8 */ \
|
||||
RCU_CFG0 = reg; \
|
||||
/* Insert a software delay */ \
|
||||
for(i=0; i<__delay; i++){ \
|
||||
} \
|
||||
reg = RCU_CFG0; \
|
||||
reg &= ~(RCU_CFG0_AHBPSC); \
|
||||
reg |= RCU_AHB_CKSYS_DIV16; \
|
||||
/* AHB = SYSCLK/16 */ \
|
||||
RCU_CFG0 = reg; \
|
||||
/* Insert a software delay */ \
|
||||
for(i=0; i<__delay; i++){ \
|
||||
} \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
#define SEL_IRC8M 0x00U
|
||||
#define SEL_HXTAL 0x01U
|
||||
#define SEL_PLL 0x02U
|
||||
|
||||
/* set the system clock frequency and declare the system clock configuration function */
|
||||
#ifdef __SYSTEM_CLOCK_IRC8M
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_IRC8M;
|
||||
static void system_clock_8m_irc8m(void);
|
||||
#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_IRC8M;
|
||||
static void system_clock_48m_irc8m(void);
|
||||
#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M;
|
||||
static void system_clock_72m_irc8m(void);
|
||||
#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_IRC8M;
|
||||
static void system_clock_108m_irc8m(void);
|
||||
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_IRC8M;
|
||||
static void system_clock_120m_irc8m(void);
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_HXTAL)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL;
|
||||
static void system_clock_hxtal(void);
|
||||
#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL;
|
||||
static void system_clock_48m_hxtal(void);
|
||||
#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL;
|
||||
static void system_clock_72m_hxtal(void);
|
||||
#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL;
|
||||
static void system_clock_108m_hxtal(void);
|
||||
#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL)
|
||||
uint32_t SystemCoreClock = __SYSTEM_CLOCK_120M_PLL_HXTAL;
|
||||
static void system_clock_120m_hxtal(void);
|
||||
#endif /* __SYSTEM_CLOCK_IRC8M */
|
||||
|
||||
/* configure the system clock */
|
||||
static void system_clock_config(void);
|
||||
|
||||
/* software delay to prevent the impact of Vcore fluctuations.
|
||||
It is strongly recommended to include it to avoid issues caused by self-removal. */
|
||||
static void _soft_delay_(uint32_t time)
|
||||
{
|
||||
__IO uint32_t i;
|
||||
for(i=0; i<time*10; i++){
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief setup the micro controller system, initialize the system
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void SystemInit (void)
|
||||
{
|
||||
/* FPU settings */
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
|
||||
#endif
|
||||
/* reset the RCU clock configuration to the default reset state */
|
||||
/* Set IRC8MEN bit */
|
||||
RCU_CTL |= RCU_CTL_IRC8MEN;
|
||||
while(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) {
|
||||
}
|
||||
if(((RCU_CFG0 & RCU_CFG0_SCSS) == RCU_SCSS_PLL)){
|
||||
RCU_MODIFY_4(0x50);
|
||||
}
|
||||
|
||||
RCU_CFG0 &= ~RCU_CFG0_SCS;
|
||||
_soft_delay_(200);
|
||||
|
||||
/* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */
|
||||
RCU_CTL &= ~(RCU_CTL_PLLEN |RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);
|
||||
/* disable all interrupts */
|
||||
RCU_INT = 0x00ff0000U;
|
||||
|
||||
/* Reset CFG0 and CFG1 registers */
|
||||
RCU_CFG0 = 0x00000000U;
|
||||
RCU_CFG1 = 0x00000000U;
|
||||
|
||||
/* reset HXTALBPS bit */
|
||||
RCU_CTL &= ~(RCU_CTL_HXTALBPS);
|
||||
|
||||
/* configure the system clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */
|
||||
system_clock_config();
|
||||
|
||||
#ifdef VECT_TAB_SRAM
|
||||
nvic_vector_table_set(NVIC_VECTTAB_RAM,VECT_TAB_OFFSET);
|
||||
#else
|
||||
nvic_vector_table_set(NVIC_VECTTAB_FLASH,VECT_TAB_OFFSET);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief configure the system clock
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_config(void)
|
||||
{
|
||||
#ifdef __SYSTEM_CLOCK_IRC8M
|
||||
system_clock_8m_irc8m();
|
||||
#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M)
|
||||
system_clock_48m_irc8m();
|
||||
#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
|
||||
system_clock_72m_irc8m();
|
||||
#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M)
|
||||
system_clock_108m_irc8m();
|
||||
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M)
|
||||
system_clock_120m_irc8m();
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_HXTAL)
|
||||
system_clock_hxtal();
|
||||
#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
|
||||
system_clock_48m_hxtal();
|
||||
#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
|
||||
system_clock_72m_hxtal();
|
||||
#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
|
||||
system_clock_108m_hxtal();
|
||||
#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL)
|
||||
system_clock_120m_hxtal();
|
||||
#endif /* __SYSTEM_CLOCK_IRC8M */
|
||||
}
|
||||
|
||||
#ifdef __SYSTEM_CLOCK_IRC8M
|
||||
/*!
|
||||
\brief configure the system clock to 8M by IRC8M
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_8m_irc8m(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable IRC8M */
|
||||
RCU_CTL |= RCU_CTL_IRC8MEN;
|
||||
|
||||
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
|
||||
}
|
||||
while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select IRC8M as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_IRC8M;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until IRC8M is selected as system clock */
|
||||
while(0U != (RCU_CFG0 & RCU_SCSS_IRC8M)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_48M_PLL_IRC8M)
|
||||
/*!
|
||||
\brief configure the system clock to 48M by PLL which selects IRC8M as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_48m_irc8m(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable IRC8M */
|
||||
RCU_CTL |= RCU_CTL_IRC8MEN;
|
||||
|
||||
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
|
||||
}
|
||||
while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_1;
|
||||
|
||||
/* IRC8M is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_IRC8M/2) * 12 = 48 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= RCU_PLL_MUL12;
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_72M_PLL_IRC8M)
|
||||
/*!
|
||||
\brief configure the system clock to 72M by PLL which selects IRC8M as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_72m_irc8m(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable IRC8M */
|
||||
RCU_CTL |= RCU_CTL_IRC8MEN;
|
||||
|
||||
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
|
||||
}while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_2;
|
||||
|
||||
/* IRC8M is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= RCU_PLL_MUL18;
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_108M_PLL_IRC8M)
|
||||
/*!
|
||||
\brief configure the system clock to 108M by PLL which selects IRC8M as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_108m_irc8m(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable IRC8M */
|
||||
RCU_CTL |= RCU_CTL_IRC8MEN;
|
||||
|
||||
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
|
||||
}while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_3;
|
||||
|
||||
/* IRC8M is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_IRC8M/2) * 27 = 108 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= RCU_PLL_MUL27;
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_120M_PLL_IRC8M)
|
||||
/*!
|
||||
\brief configure the system clock to 120M by PLL which selects IRC8M as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_120m_irc8m(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable IRC8M */
|
||||
RCU_CTL |= RCU_CTL_IRC8MEN;
|
||||
|
||||
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
|
||||
}while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_3;
|
||||
|
||||
/* IRC8M is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_IRC8M/2) * 30 = 120 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= RCU_PLL_MUL30;
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_HXTAL)
|
||||
/*!
|
||||
\brief configure the system clock to HXTAL
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_hxtal(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable HXTAL */
|
||||
RCU_CTL |= RCU_CTL_HXTALEN;
|
||||
|
||||
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
||||
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select HXTAL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_HXTAL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until HXTAL is selected as system clock */
|
||||
while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL)
|
||||
/*!
|
||||
\brief configure the system clock to 48M by PLL which selects HXTAL(8M) as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_48m_hxtal(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable HXTAL */
|
||||
RCU_CTL |= RCU_CTL_HXTALEN;
|
||||
|
||||
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
||||
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_1;
|
||||
|
||||
/* HXTAL is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_PREDIV0) * 12 = 48 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL12);
|
||||
|
||||
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
|
||||
|
||||
/* CK_PREDIV0 = (CK_HXTAL)/2 *10 /10 = 4 MHz */
|
||||
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL10 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV10);
|
||||
|
||||
/* enable PLL1 */
|
||||
RCU_CTL |= RCU_CTL_PLL1EN;
|
||||
/* wait till PLL1 is ready */
|
||||
while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
|
||||
}
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
#elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL)
|
||||
/*!
|
||||
\brief configure the system clock to 72M by PLL which selects HXTAL(8M) as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_72m_hxtal(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable HXTAL */
|
||||
RCU_CTL |= RCU_CTL_HXTALEN;
|
||||
|
||||
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
||||
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_2;
|
||||
|
||||
/* HXTAL is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL18);
|
||||
|
||||
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
|
||||
|
||||
/* CK_PREDIV0 = (CK_HXTAL)/2 *10 /10 = 4 MHz */
|
||||
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL10 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV10);
|
||||
|
||||
/* enable PLL1 */
|
||||
RCU_CTL |= RCU_CTL_PLL1EN;
|
||||
/* wait till PLL1 is ready */
|
||||
while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
|
||||
}
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL)
|
||||
/*!
|
||||
\brief configure the system clock to 108M by PLL which selects HXTAL(8M) as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_108m_hxtal(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable HXTAL */
|
||||
RCU_CTL |= RCU_CTL_HXTALEN;
|
||||
|
||||
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
||||
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_3;
|
||||
|
||||
/* HXTAL is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL27);
|
||||
|
||||
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
|
||||
|
||||
/* CK_PREDIV0 = (CK_HXTAL)/2 *10 /10 = 4 MHz */
|
||||
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL10 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV10);
|
||||
|
||||
/* enable PLL1 */
|
||||
RCU_CTL |= RCU_CTL_PLL1EN;
|
||||
/* wait till PLL1 is ready */
|
||||
while((RCU_CTL & RCU_CTL_PLL1STB) == 0){
|
||||
}
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL)
|
||||
/*!
|
||||
\brief configure the system clock to 120M by PLL which selects HXTAL(8M) as its clock source
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void system_clock_120m_hxtal(void)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t stab_flag = 0U;
|
||||
__IO uint32_t reg_temp;
|
||||
|
||||
/* enable HXTAL */
|
||||
RCU_CTL |= RCU_CTL_HXTALEN;
|
||||
|
||||
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
|
||||
do{
|
||||
timeout++;
|
||||
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
|
||||
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
|
||||
|
||||
/* if fail */
|
||||
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
|
||||
while(1){
|
||||
}
|
||||
}
|
||||
|
||||
FMC_WS = (FMC_WS & (~FMC_WS_WSCNT)) | FMC_WAIT_STATE_3;
|
||||
|
||||
/* HXTAL is stable */
|
||||
/* AHB = SYSCLK */
|
||||
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
|
||||
/* APB2 = AHB/1 */
|
||||
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
|
||||
/* APB1 = AHB/2 */
|
||||
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
|
||||
|
||||
/* CK_PLL = (CK_PREDIV0) * 30 = 120 MHz */
|
||||
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
|
||||
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL30);
|
||||
|
||||
RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0);
|
||||
|
||||
/* CK_PREDIV0 = (CK_HXTAL)/2 *10 /10 = 4 MHz */
|
||||
RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL10 | RCU_PREDV1_DIV2 | RCU_PREDV0_DIV10);
|
||||
|
||||
/* enable PLL1 */
|
||||
RCU_CTL |= RCU_CTL_PLL1EN;
|
||||
/* wait till PLL1 is ready */
|
||||
while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){
|
||||
}
|
||||
|
||||
/* enable PLL */
|
||||
RCU_CTL |= RCU_CTL_PLLEN;
|
||||
|
||||
/* wait until PLL is stable */
|
||||
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
|
||||
}
|
||||
|
||||
reg_temp = RCU_CFG0;
|
||||
/* select PLL as system clock */
|
||||
reg_temp &= ~RCU_CFG0_SCS;
|
||||
reg_temp |= RCU_CKSYSSRC_PLL;
|
||||
RCU_CFG0 = reg_temp;
|
||||
|
||||
/* wait until PLL is selected as system clock */
|
||||
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
|
||||
}
|
||||
}
|
||||
#endif /* __SYSTEM_CLOCK_IRC8M */
|
||||
|
||||
/*!
|
||||
\brief update the SystemCoreClock with current core clock retrieved from cpu registers
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void SystemCoreClockUpdate (void)
|
||||
{
|
||||
uint32_t sws = 0U;
|
||||
uint32_t pllsel = 0U, pllpresel = 0U, predv0sel = 0U, pllmf,ck_src = 0U;
|
||||
uint32_t predv0 = 0U, predv1 = 0U, pll1mf = 0U,idx = 0U,clk_exp = 0U;
|
||||
/* exponent of AHB clock divider */
|
||||
const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
||||
|
||||
sws = GET_BITS(RCU_CFG0, 2, 3);
|
||||
switch(sws){
|
||||
/* IRC8M is selected as CK_SYS */
|
||||
case SEL_IRC8M:
|
||||
SystemCoreClock = IRC8M_VALUE;
|
||||
break;
|
||||
/* HXTAL is selected as CK_SYS */
|
||||
case SEL_HXTAL:
|
||||
SystemCoreClock = HXTAL_VALUE;
|
||||
break;
|
||||
/* PLL is selected as CK_SYS */
|
||||
case SEL_PLL:
|
||||
/* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */
|
||||
pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
|
||||
|
||||
if(RCU_PLLSRC_HXTAL_IRC48M == pllsel){
|
||||
/* PLL clock source is HXTAL or IRC48M */
|
||||
pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL);
|
||||
|
||||
if(RCU_PLLPRESRC_HXTAL == pllpresel){
|
||||
/* PLL clock source is HXTAL */
|
||||
ck_src = HXTAL_VALUE;
|
||||
}else{
|
||||
/* PLL clock source is IRC48 */
|
||||
ck_src = IRC48M_VALUE;
|
||||
}
|
||||
|
||||
predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL);
|
||||
/* source clock use PLL1 */
|
||||
if(RCU_PREDV0SRC_CKPLL1 == predv0sel){
|
||||
predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U;
|
||||
pll1mf = ((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U;
|
||||
if(17U == pll1mf){
|
||||
pll1mf = 20U;
|
||||
}
|
||||
ck_src = (ck_src/predv1)*pll1mf;
|
||||
}
|
||||
predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U;
|
||||
ck_src /= predv0;
|
||||
}else{
|
||||
/* PLL clock source is IRC8M/2 */
|
||||
ck_src = IRC8M_VALUE/2U;
|
||||
}
|
||||
|
||||
/* PLL multiplication factor */
|
||||
pllmf = GET_BITS(RCU_CFG0, 18, 21);
|
||||
if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){
|
||||
pllmf |= 0x10U;
|
||||
}
|
||||
if(pllmf < 15U){
|
||||
pllmf += 2U;
|
||||
}else{
|
||||
pllmf += 1U;
|
||||
}
|
||||
SystemCoreClock = ck_src*pllmf;
|
||||
if(15U == pllmf){
|
||||
SystemCoreClock = ck_src*6U + ck_src/2U;
|
||||
}
|
||||
|
||||
break;
|
||||
/* IRC8M is selected as CK_SYS */
|
||||
default:
|
||||
SystemCoreClock = IRC8M_VALUE;
|
||||
break;
|
||||
}
|
||||
/* calculate AHB clock frequency */
|
||||
idx = GET_BITS(RCU_CFG0, 4, 7);
|
||||
clk_exp = ahb_exp[idx];
|
||||
SystemCoreClock >>= clk_exp;
|
||||
}
|
||||
|
||||
#ifdef __FIRMWARE_VERSION_DEFINE
|
||||
/*!
|
||||
\brief get firmware version
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval firmware version
|
||||
*/
|
||||
uint32_t gd32c10x_firmware_version_get(void)
|
||||
{
|
||||
return __GD32C10X_STDPERIPH_VERSION;
|
||||
}
|
||||
#endif /* __FIRMWARE_VERSION_DEFINE */
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* CSOLUTION generated file: DO NOT EDIT!
|
||||
* Generated by: csolution version 2.11.0
|
||||
*
|
||||
* Project: 'Robot_V2.Debug+GD32C103CB'
|
||||
* Target: 'Debug+GD32C103CB'
|
||||
*/
|
||||
|
||||
#ifndef RTE_COMPONENTS_H
|
||||
#define RTE_COMPONENTS_H
|
||||
|
||||
|
||||
/*
|
||||
* Define the Device Header File:
|
||||
*/
|
||||
#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:DBG@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_DBG
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:DMA@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_DMA
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:EXTI@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_EXTI
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:FMC@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_FMC
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:FWDGT@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_FWDGT
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:GPIO@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_GPIO
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:MISC@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_MISC
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:PMU@1.0.0 */
|
||||
#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 */
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* CSOLUTION generated file: DO NOT EDIT!
|
||||
* Generated by: csolution version 2.12.0+p41-gfeadfc5e
|
||||
*
|
||||
* Project: 'Robot_V2.Release+GD32C103CB'
|
||||
* Target: 'Release+GD32C103CB'
|
||||
*/
|
||||
|
||||
#ifndef RTE_COMPONENTS_H
|
||||
#define RTE_COMPONENTS_H
|
||||
|
||||
|
||||
/*
|
||||
* Define the Device Header File:
|
||||
*/
|
||||
#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 */
|
||||
#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 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_DMA
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:EXTI@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_EXTI
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:FMC@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_FMC
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:FWDGT@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_FWDGT
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:GPIO@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_GPIO
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:MISC@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_MISC
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:PMU@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_PMU
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:RCU@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_RCU
|
||||
/* GigaDevice::Device:GD32C10x_StdPeripherals:USART@1.0.0 */
|
||||
#define RTE_DEVICE_STDPERIPHERALS_USART
|
||||
|
||||
|
||||
#endif /* RTE_COMPONENTS_H */
|
||||
@@ -0,0 +1,62 @@
|
||||
project:
|
||||
groups:
|
||||
- group: Source Files
|
||||
files:
|
||||
- file: main.h
|
||||
- file: main.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
|
||||
- group: device
|
||||
files:
|
||||
- file: device/Can.cpp
|
||||
- file: device/Can.h
|
||||
components:
|
||||
- component: ARM::CMSIS:CORE
|
||||
- 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:CRC
|
||||
output:
|
||||
type:
|
||||
- elf
|
||||
- hex
|
||||
- map
|
||||
packs:
|
||||
- pack: ARM::CMSIS
|
||||
- pack: GigaDevice::GD32C10x_DFP
|
||||
misc:
|
||||
- for-compiler: AC6
|
||||
C-CPP:
|
||||
- -fshort-enums
|
||||
- -fshort-wchar
|
||||
- -D__MICROLIB
|
||||
- -Wno-register
|
||||
C:
|
||||
- -D__packed=packed
|
||||
ASM:
|
||||
- -D__packed=packed
|
||||
- -D__MICROLIB
|
||||
Link:
|
||||
- --library_type=microlib
|
||||
- --entry=Reset_Handler
|
||||
@@ -0,0 +1,274 @@
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,697 @@
|
||||
#include "Can.h"
|
||||
#include "flash.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 <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;
|
||||
|
||||
// 添加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发送缓冲区
|
||||
|
||||
/*!
|
||||
\brief initialize CAN GPIO
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval ErrStatus: SUCCESS or ERROR
|
||||
*/
|
||||
u8 can_gpio_init() {
|
||||
/* enable CAN clock */
|
||||
rcu_periph_clock_enable(RCU_CAN0);
|
||||
rcu_periph_clock_enable(RCU_GPIOB);
|
||||
rcu_periph_clock_enable(RCU_AF);
|
||||
|
||||
/* configure CAN0 GPIO */
|
||||
gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_8); // rx
|
||||
gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); // tx
|
||||
gpio_pin_remap_config(GPIO_CAN0_PARTIAL_REMAP, ENABLE);
|
||||
/* enable the EN GPIO clock */
|
||||
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13);
|
||||
gpio_bit_reset(GPIOB, GPIO_PIN_13);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief 初始化CAN DMA
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void can_dma_init(void) {
|
||||
// 使能DMA时钟
|
||||
rcu_periph_clock_enable(RCU_DMA0);
|
||||
|
||||
// 配置接收DMA
|
||||
dma_struct_para_init(&dma_rx_parameter);
|
||||
dma_rx_parameter.periph_addr =
|
||||
(uint32_t)(&CAN_RFIFOMDATA0(CAN0, CAN_FIFO0)); // CAN接收数据寄存器地址
|
||||
dma_rx_parameter.memory_addr = (uint32_t)can_rx_buffer; // 接收缓冲区地址
|
||||
dma_rx_parameter.direction = DMA_PERIPHERAL_TO_MEMORY; // 外设到内存
|
||||
dma_rx_parameter.memory_width = DMA_MEMORY_WIDTH_8BIT; // 内存宽度8位
|
||||
dma_rx_parameter.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; // 外设宽度8位
|
||||
dma_rx_parameter.priority = DMA_PRIORITY_HIGH; // 高优先级
|
||||
dma_rx_parameter.number = 8; // 传输字节数
|
||||
dma_rx_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE; // 外设地址不递增
|
||||
dma_rx_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE; // 内存地址递增
|
||||
dma_init(DMA0, DMA_CH4, &dma_rx_parameter); // 使用DMA通道4
|
||||
|
||||
// 配置发送DMA
|
||||
dma_struct_para_init(&dma_tx_parameter);
|
||||
dma_tx_parameter.periph_addr =
|
||||
(uint32_t)(&CAN_TMI0(CAN0)); // CAN发送数据寄存器地址
|
||||
dma_tx_parameter.memory_addr = (uint32_t)can_tx_buffer; // 发送缓冲区地址
|
||||
dma_tx_parameter.direction = DMA_MEMORY_TO_PERIPHERAL; // 内存到外设
|
||||
dma_tx_parameter.memory_width = DMA_MEMORY_WIDTH_8BIT; // 内存宽度8位
|
||||
dma_tx_parameter.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; // 外设宽度8位
|
||||
dma_tx_parameter.priority = DMA_PRIORITY_HIGH; // 高优先级
|
||||
dma_tx_parameter.number = 8; // 传输字节数
|
||||
dma_tx_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE; // 外设地址不递增
|
||||
dma_tx_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE; // 内存地址递增
|
||||
dma_init(DMA0, DMA_CH5, &dma_tx_parameter); // 使用DMA通道5
|
||||
|
||||
// 使能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);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief 初始化CAN0 CANFD模式
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void canfd_config(void) {
|
||||
can_gpio_init();
|
||||
can_parameter_struct can_parameter;
|
||||
can_fdframe_struct can_fd_parameter;
|
||||
can_fd_tdc_struct can_fd_tdc_parameter;
|
||||
can_filter_parameter_struct can_filter;
|
||||
|
||||
/* initialize CAN register */
|
||||
can_deinit(CAN0);
|
||||
|
||||
/* initialize CAN */
|
||||
can_parameter.time_triggered = DISABLE;
|
||||
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.trans_fifo_order = ENABLE;
|
||||
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;
|
||||
can_init(CAN0, &can_parameter);
|
||||
|
||||
can_struct_para_init(CAN_FD_FRAME_STRUCT, &can_fd_parameter);
|
||||
can_fd_parameter.fd_frame = ENABLE;
|
||||
can_fd_parameter.excp_event_detect = ENABLE;
|
||||
can_fd_parameter.delay_compensation = ENABLE;
|
||||
can_fd_tdc_parameter.tdc_filter = 0x04;
|
||||
can_fd_tdc_parameter.tdc_mode = CAN_TDCMOD_CALC_AND_OFFSET;
|
||||
can_fd_tdc_parameter.tdc_offset = 0x04;
|
||||
can_fd_parameter.p_delay_compensation = &can_fd_tdc_parameter;
|
||||
can_fd_parameter.iso_bosch = CAN_FDMOD_ISO;
|
||||
can_fd_parameter.esi_mode = CAN_ESIMOD_HARDWARE;
|
||||
/* FD mode data baudrate 2Mbps, sample piont at 80% */
|
||||
can_fd_parameter.data_resync_jump_width = CAN_BT_SJW_1TQ;
|
||||
can_fd_parameter.data_time_segment_1 = CAN_BT_BS1_3TQ;
|
||||
can_fd_parameter.data_time_segment_2 = CAN_BT_BS2_1TQ;
|
||||
/* CAN-FD data segement prescaler should be the same as non-data segement
|
||||
* prescaler */
|
||||
can_fd_parameter.data_prescaler = 6;
|
||||
can_fd_init(CAN0, &can_fd_parameter);
|
||||
|
||||
/* initialize filter */
|
||||
can_filter.filter_mode = CAN_FILTERMODE_MASK;
|
||||
can_filter.filter_bits = CAN_FILTERBITS_32BIT;
|
||||
/* configure filter ID */
|
||||
can_filter.filter_list_high = 0x0000;
|
||||
can_filter.filter_list_low = 0x0000;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/*!
|
||||
\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");
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief CAN_transmiter构造函数
|
||||
\note 初始化CAN通信相关参数和硬件配置
|
||||
*/
|
||||
u8 CAN_transmiter::init() {
|
||||
// 初始化CAN硬件
|
||||
// can_config();
|
||||
canfd_config();
|
||||
|
||||
// 初始化发送消息结构体
|
||||
can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &transmit_message);
|
||||
/* initialize receive message */
|
||||
can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &receive_message);
|
||||
|
||||
// 初始化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: 有新消息
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
u8 CAN_transmiter::sendACK(u32 CANFD_OTA_ACK_ID, u32 packet_num) {
|
||||
u32_union_t pack_data;
|
||||
pack_data.u = packet_num;
|
||||
memset(transmit_data, 0, 4);
|
||||
pack_u32_to_bytes(transmit_data, 3, pack_data);
|
||||
|
||||
return CANFD_Send(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中断服务程序
|
||||
* @retval 无
|
||||
*/
|
||||
void CAN0_RX0_IRQHandler(void) {
|
||||
// 检查是否是FIFO0消息挂起中断
|
||||
if (can_interrupt_flag_get(CAN0, CAN_INT_FLAG_RFL0) != RESET) {
|
||||
// 清除中断标志
|
||||
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);
|
||||
|
||||
// 读取接收到的数据
|
||||
can_message_receive(CAN0, CAN_FIFO0, &CAN0_transmiter.receive_message);
|
||||
|
||||
// 接收标志位置1
|
||||
CAN0_transmiter.can0_receive_flag = SET;
|
||||
}
|
||||
|
||||
// 检查其他可能的中断源
|
||||
if (can_interrupt_flag_get(CAN0, CAN_INT_FLAG_RFF0) != RESET) {
|
||||
// FIFO0满中断
|
||||
can_interrupt_flag_clear(CAN0, CAN_INT_FLAG_RFF0);
|
||||
printf("CAN FIFO0 full\n");
|
||||
}
|
||||
|
||||
if (can_interrupt_flag_get(CAN0, CAN_INT_FLAG_RFO0) != RESET) {
|
||||
// FIFO0溢出中断
|
||||
can_interrupt_flag_clear(CAN0, CAN_INT_FLAG_RFO0);
|
||||
printf("CAN FIFO0 overflow\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA通道4中断服务程序(CAN接收DMA)
|
||||
* @retval 无
|
||||
*/
|
||||
void DMA0_Channel4_IRQHandler(void) {
|
||||
if (dma_interrupt_flag_get(DMA0, DMA_CH4, DMA_INT_FLAG_FTF)) {
|
||||
// 清除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++) {
|
||||
CAN0_transmiter.receive_message.rx_data[i] = can_rx_buffer[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA通道5中断服务程序(CAN/CANFD发送DMA)
|
||||
* @retval 无
|
||||
*/
|
||||
void DMA0_Channel5_IRQHandler(void) {
|
||||
if (dma_interrupt_flag_get(DMA0, DMA_CH5, DMA_INT_FLAG_FTF)) {
|
||||
// 清除DMA传输完成中断标志
|
||||
dma_interrupt_flag_clear(DMA0, DMA_CH5, DMA_INT_FLAG_G);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
#ifndef _CAN_H
|
||||
#define _CAN_H
|
||||
|
||||
#include <stdint.h>
|
||||
#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发送和接收功能
|
||||
*/
|
||||
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接收标志
|
||||
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);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,109 @@
|
||||
#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执行一次的操作
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#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
|
||||
@@ -0,0 +1,40 @@
|
||||
#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
|
||||
@@ -0,0 +1,306 @@
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#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
|
||||
@@ -0,0 +1,38 @@
|
||||
#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); }
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef _MOTOR_H
|
||||
#define _MOTOR_H
|
||||
|
||||
|
||||
void motor_init(void);
|
||||
void motor_reset(void);
|
||||
void motor_resume(void);
|
||||
void motor_sleep(void);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
#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();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "Can.h"
|
||||
#include "gd32c10x.h"
|
||||
#include "gd32c10x_can.h"
|
||||
#include "sys/OTA.h"
|
||||
#include "sys/config.h"
|
||||
#include "sys/systick.h"
|
||||
|
||||
class BootloaderSystem {
|
||||
private:
|
||||
OTAHandler ota;
|
||||
|
||||
public:
|
||||
void initHardware() {
|
||||
extern CAN_transmiter CAN0_transmiter; // CAN初始化
|
||||
systick_config(); // 系统时钟初始化
|
||||
SystemCoreClockUpdate(); // 更新系统时钟变量
|
||||
CAN0_transmiter.init();
|
||||
}
|
||||
|
||||
void run() {
|
||||
// 检查是否触发OTA模式
|
||||
if (1) {
|
||||
// OTA模式
|
||||
while (1) {
|
||||
ota.process();
|
||||
for (volatile int i = 0; i < 500000; i++)
|
||||
; // 简单延时
|
||||
}
|
||||
} else {
|
||||
// 正常模式:跳转到APP
|
||||
ota.jumpToApplication();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
BootloaderSystem sys;
|
||||
sys.initHardware();
|
||||
sys.run();
|
||||
|
||||
while (1)
|
||||
; // 不应该执行到这里
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*!
|
||||
\file main.h
|
||||
\brief the header file of main
|
||||
|
||||
\version 2025-06-20, V1.5.1, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2024, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
#include "stdint.h"
|
||||
|
||||
void do_task(u32 currentTasks);
|
||||
|
||||
#endif /* MAIN_H */
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "OTA.h"
|
||||
#include "gd32c10x_fmc.h"
|
||||
#include <cstring>
|
||||
|
||||
extern CAN_transmiter CAN0_transmiter; // CAN初始化
|
||||
extern "C" {
|
||||
void canfd_rx_irq_handler(void);
|
||||
}
|
||||
|
||||
OTAHandler::OTAHandler() : ota_active(false), received_size(0) {}
|
||||
|
||||
void OTAHandler::init() {
|
||||
// 初始化CANFD接收中断
|
||||
nvic_irq_enable(CAN0_RX0_IRQn, 1, 1);
|
||||
}
|
||||
|
||||
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;
|
||||
eraseApplicationArea();
|
||||
ota_active = true;
|
||||
sendACK(0xFFFFFFFF); // 确认开始
|
||||
}
|
||||
} else if (id == CANFD_OTA_DATA_ID && ota_active) {
|
||||
// 数据包格式:[4字节包序号][实际数据]
|
||||
if (len >= 4) {
|
||||
uint32_t packet_num = *(uint32_t *)data;
|
||||
uint32_t offset = packet_num * (len - 4);
|
||||
|
||||
if (offset < expected_size) {
|
||||
writeApplicationData(offset, &data[4], len - 4);
|
||||
received_size += (len - 4);
|
||||
sendACK(packet_num);
|
||||
|
||||
// 检查是否完成
|
||||
if (received_size >= expected_size) {
|
||||
ota_active = false;
|
||||
// 跳转前延时让ACK发出
|
||||
for (volatile int i = 0; i < 100000; i++)
|
||||
;
|
||||
jumpToApplication();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OTAHandler::sendACK(uint32_t packet_num) {
|
||||
CAN0_transmiter.sendACK(CANFD_OTA_ACK_ID, packet_num);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef __OTA_H
|
||||
#define __OTA_H
|
||||
|
||||
#include "Can.h"
|
||||
#include "config.h"
|
||||
#include "gd32c10x.h"
|
||||
|
||||
class OTAHandler {
|
||||
public:
|
||||
bool ota_active;
|
||||
uint32_t received_size;
|
||||
uint32_t expected_size;
|
||||
|
||||
OTAHandler();
|
||||
void init();
|
||||
void process();
|
||||
bool isActive() const { return ota_active; }
|
||||
|
||||
void handleOTAMessage(uint32_t id, uint8_t *data, uint8_t len);
|
||||
void jumpToApplication();
|
||||
|
||||
private:
|
||||
bool validateApplication();
|
||||
void eraseApplicationArea();
|
||||
void writeApplicationData(uint32_t offset, uint8_t *data, uint32_t size);
|
||||
void sendACK(uint32_t packet_num);
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "stdint.h"
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
@@ -0,0 +1,453 @@
|
||||
#include "flash.h"
|
||||
#include "gd32c10x.h"
|
||||
#include "gd32c10x_crc.h"
|
||||
#include "gd32c10x_fmc.h"
|
||||
#include "math.h"
|
||||
#include <Can.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#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() {
|
||||
// 构造函数可以为空,或者做一些初始化工作
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化Flash EEPROM模拟
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 格式化Flash EEPROM页面
|
||||
* @param None
|
||||
* @retval FlashEepromStatus: 操作状态
|
||||
*/
|
||||
FlashEepromStatus FlashEEPROM::format() {
|
||||
fmc_state_enum fmc_status;
|
||||
#if EEPDEBUG
|
||||
printf("擦除页面\r\n");
|
||||
#endif
|
||||
|
||||
fmc_unlock();
|
||||
fmc_status = fmc_page_erase(EEPROM_START_ADDRESS); // 擦除第一页
|
||||
if (fmc_status != FMC_READY) {
|
||||
fmc_lock();
|
||||
return FLASH_EEPROM_ERASE_ERROR;
|
||||
}
|
||||
fmc_status = fmc_page_erase(EEPROM_DATA_PAGE2_ADDRESS); // 擦除第二页
|
||||
if (fmc_status != FMC_READY) {
|
||||
fmc_lock();
|
||||
return FLASH_EEPROM_ERASE_ERROR;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef __FLASH_H
|
||||
#define __FLASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
// 修改后 - 强制4字节对齐
|
||||
#define ALIGN_4BYTE(addr) ((addr) & 0xFFFFFFFC) // 4字节对齐
|
||||
|
||||
// EEPROM操作状态
|
||||
typedef enum {
|
||||
FLASH_EEPROM_OK = 0, // 操作成功
|
||||
FLASH_EEPROM_WRITE_ERROR, // 写入错误
|
||||
FLASH_EEPROM_READ_ERROR, // 读取错误
|
||||
FLASH_EEPROM_ERASE_ERROR, // 擦除错误
|
||||
FLASH_EEPROM_INVALID_ADDR, // 无效地址
|
||||
FLASH_EEPROM_DATA_NOT_FOUND, // 找不到数据
|
||||
FLASH_EEPROM_CRC_ERROR, // CRC错误
|
||||
FLASH_EEPROM_ALIGNMENT_ERROR, // 对齐错误
|
||||
} FlashEepromStatus;
|
||||
|
||||
// Flash EEPROM类
|
||||
class FlashEEPROM {
|
||||
public:
|
||||
// EEPROM emulation constants
|
||||
static constexpr u32 EEPROM_START_ADDRESS = 0x0801F800; // 第一页(1KB)
|
||||
static constexpr u32 EEPROM_DATA_PAGE2_ADDRESS = 0x801FC00; // 第二页(1KB)
|
||||
static constexpr u32 EEPROM_END_ADDRESS = 0x08020000; // Flash结束地址
|
||||
static constexpr u32 EEPROM_MAX_SIZE = 0x800; // EEPROM最大容量
|
||||
static constexpr u32 EEPROM_DATA_START_ADDRESS =
|
||||
0x0801F900; // DATA段开始地址
|
||||
static constexpr u32 DATA_FLOAT_MASK = 0xFFFFFF00; // float存储地址掩码
|
||||
static constexpr u32 DATA_U16_MASK = 0xFFFF0000; // u16存储地址掩码
|
||||
static constexpr u32 DATA_ADDR_MASK = 0x000000FF; // 虚拟地址掩码
|
||||
|
||||
// 定义用户自定义的虚拟地址
|
||||
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();
|
||||
|
||||
// 初始化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();
|
||||
|
||||
private:
|
||||
FlashEepromStatus writeCRC(u32 CRC_NUM, bool saved);
|
||||
};
|
||||
|
||||
void flash_eeprom_example_main(void);
|
||||
#endif /* __FLASH_H */
|
||||
@@ -0,0 +1,103 @@
|
||||
#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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#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
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "initial.h"
|
||||
#include "gd32c10x.h"
|
||||
#include "gd32c10x_gpio.h"
|
||||
#include "gd32c10x_rcu.h"
|
||||
#include <cstdio>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* 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))
|
||||
;
|
||||
return ch;
|
||||
}
|
||||
|
||||
void unused_pin_init() {
|
||||
rcu_periph_clock_enable(RCU_GPIOA); // 使能GPIOA时钟
|
||||
rcu_periph_clock_enable(RCU_GPIOB); // 使能GPIOB时钟
|
||||
rcu_periph_clock_enable(RCU_GPIOC); // 使能GPIOC时钟
|
||||
gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ,
|
||||
GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12);
|
||||
gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ,
|
||||
GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_15);
|
||||
gpio_init(GPIOC, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ,
|
||||
GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
|
||||
gpio_bit_reset(GPIOA, GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12);
|
||||
gpio_bit_reset(GPIOB, GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_15);
|
||||
gpio_bit_reset(GPIOC, GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief 检测并打印复位源信息
|
||||
\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;
|
||||
}
|
||||
|
||||
if (RESET != rcu_flag_get(RCU_FLAG_PORRST)) {
|
||||
// printf("Power Reset\r\n");
|
||||
cause = RCU_FLAG_PORRST;
|
||||
}
|
||||
|
||||
if (RESET != rcu_flag_get(RCU_FLAG_WWDGTRST)) {
|
||||
// printf("Window Watchdog Timer Reset\r\n");
|
||||
cause = RCU_FLAG_WWDGTRST;
|
||||
}
|
||||
|
||||
if (RESET != rcu_flag_get(RCU_FLAG_LPRST)) {
|
||||
// printf("Low Power Reset\r\n");
|
||||
cause = RCU_FLAG_LPRST;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef _INITIAL_H
|
||||
#define _INITIAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "gd32c10x_eval.h"
|
||||
#include "stdint.h"
|
||||
#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();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,117 @@
|
||||
/*!
|
||||
\file systick.c
|
||||
\brief the systick configuration file
|
||||
|
||||
\version 2025-06-20, V1.5.1, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2024, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#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
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void systick_config(void) {
|
||||
/* setup systick timer for 1000Hz interrupts */
|
||||
if (SysTick_Config(SystemCoreClock / 1000U)) {
|
||||
/* capture error */
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
/* configure the systick handler priority */
|
||||
NVIC_SetPriority(SysTick_IRQn, 0x00U);
|
||||
}
|
||||
/*!
|
||||
\brief delay a time in seconds
|
||||
\param[in] count: count in seconds
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void delay_1s(uint32_t count) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < count; i++) {
|
||||
delay_1ms(1000);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief delay a time in milliseconds
|
||||
\param[in] count: count in milliseconds
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void delay_1ms(uint32_t count) {
|
||||
delay = count;
|
||||
while (0U != delay) {
|
||||
fwdgt_counter_reload();
|
||||
fwdgt_counter_reload();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief delay decrement
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void delay_decrement(void) {
|
||||
if (0U != delay) {
|
||||
delay--;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief system soft reset
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void system_soft_reset(void) {
|
||||
/* Set the software reset bit */
|
||||
SCB->AIRCR = (0x05FA0000U | (SCB->AIRCR & (0x700U)) | (1U << 2));
|
||||
|
||||
/* Data Synchronization Barrier */
|
||||
__DSB();
|
||||
|
||||
/* Wait for reset */
|
||||
while (1) {
|
||||
__NOP();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*!
|
||||
\file systick.h
|
||||
\brief the header file of systick
|
||||
|
||||
\version 2025-06-20, V1.5.1, firmware for GD32C10x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2024, GigaDevice Semiconductor Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SYSTICK_H
|
||||
#define SYSTICK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
/* configure systick */
|
||||
void systick_config(void);
|
||||
/* delay a time in milliseconds */
|
||||
void delay_1ms(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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SYSTICK_H */
|
||||
@@ -0,0 +1,44 @@
|
||||
cbuild-run:
|
||||
generated-by: csolution version 2.12.0+p41-gfeadfc5e
|
||||
solution: ../Robot_V2.csolution.yml
|
||||
target-type: GD32C103CB
|
||||
target-set: <default>
|
||||
compiler: AC6
|
||||
device: GigaDevice::GD32C103CB
|
||||
device-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
output:
|
||||
- file: Robot_V2/GD32C103CB/Release/Robot_V2.axf
|
||||
info: generate by Robot_V2.Release+GD32C103CB
|
||||
type: elf
|
||||
load: symbols
|
||||
- file: Robot_V2/GD32C103CB/Release/Robot_V2.hex
|
||||
info: generate by Robot_V2.Release+GD32C103CB
|
||||
type: hex
|
||||
load: image
|
||||
system-resources:
|
||||
memory:
|
||||
- name: IROM1
|
||||
access: rx
|
||||
start: 0x08000000
|
||||
size: 0x00020000
|
||||
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
- name: IRAM1
|
||||
access: rwx
|
||||
start: 0x20000000
|
||||
size: 0x00008000
|
||||
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
system-descriptions:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/SVD/GD32C10x.svd
|
||||
type: svd
|
||||
debugger:
|
||||
name: ST-Link@pyOCD
|
||||
protocol: swd
|
||||
clock: 10000000
|
||||
gdbserver:
|
||||
- port: 3333
|
||||
programming:
|
||||
- algorithm: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Flash/GD32C10x.FLM
|
||||
start: 0x08000000
|
||||
size: 0x00020000
|
||||
ram-start: 0x20000000
|
||||
ram-size: 0x00008000
|
||||
@@ -0,0 +1,406 @@
|
||||
build:
|
||||
generated-by: csolution version 2.12.0
|
||||
solution: ../../../../Robot_V2.csolution.yml
|
||||
project: ../../../../Robot_V2/Robot_V2.cproject.yml
|
||||
context: Robot_V2.Debug+GD32C103CB
|
||||
compiler: AC6
|
||||
device: GigaDevice::GD32C103CB
|
||||
device-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
processor:
|
||||
endian: little
|
||||
fpu: sp
|
||||
core: Cortex-M4
|
||||
packs:
|
||||
- pack: ARM::CMSIS@4.5.0
|
||||
path: ${CMSIS_PACK_ROOT}/ARM/CMSIS/4.5.0
|
||||
- pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
path: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1
|
||||
optimize: none
|
||||
debug: on
|
||||
misc:
|
||||
ASM:
|
||||
- -D__packed=packed
|
||||
- -D__MICROLIB
|
||||
- -gdwarf-5
|
||||
- -masm=auto
|
||||
C:
|
||||
- -D__packed=packed
|
||||
- -fshort-enums
|
||||
- -fshort-wchar
|
||||
- -D__MICROLIB
|
||||
- -Wno-register
|
||||
- -gdwarf-5
|
||||
- -std=gnu11
|
||||
- -Wno-macro-redefined
|
||||
- -Wno-pragma-pack
|
||||
- -Wno-parentheses-equality
|
||||
- -Wno-license-management
|
||||
CPP:
|
||||
- -fshort-enums
|
||||
- -fshort-wchar
|
||||
- -D__MICROLIB
|
||||
- -Wno-register
|
||||
- -gdwarf-5
|
||||
- -Wno-macro-redefined
|
||||
- -Wno-pragma-pack
|
||||
- -Wno-parentheses-equality
|
||||
- -Wno-license-management
|
||||
Link:
|
||||
- --library_type=microlib
|
||||
- --entry=Reset_Handler
|
||||
- --info=summarysizes
|
||||
- --summary_stderr
|
||||
- --diag_suppress=L6314W
|
||||
define:
|
||||
- GD32C10x
|
||||
- _RTE_
|
||||
define-asm:
|
||||
- GD32C10x
|
||||
- _RTE_
|
||||
add-path:
|
||||
- ../../../../Robot_V2/RTE/_Debug_GD32C103CB
|
||||
- ${CMSIS_PACK_ROOT}/ARM/CMSIS/4.5.0/CMSIS/Include
|
||||
- ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc
|
||||
- ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Include
|
||||
- ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Utilities
|
||||
add-path-asm:
|
||||
- ../../../../Robot_V2/RTE/_Debug_GD32C103CB
|
||||
- ${CMSIS_PACK_ROOT}/ARM/CMSIS/4.5.0/CMSIS/Include
|
||||
- ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc
|
||||
- ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Include
|
||||
- ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Utilities
|
||||
output-dirs:
|
||||
intdir: ../../../../tmp
|
||||
outdir: .
|
||||
rtedir: ../../../../Robot_V2/RTE
|
||||
output:
|
||||
- type: elf
|
||||
file: Robot_V2.axf
|
||||
- type: hex
|
||||
file: Robot_V2.hex
|
||||
- type: map
|
||||
file: Robot_V2.axf.map
|
||||
components:
|
||||
- component: ARM::CMSIS:CORE@4.3.0
|
||||
condition: Cortex-M Device
|
||||
from-pack: ARM::CMSIS@4.5.0
|
||||
selected-by: ARM::CMSIS:CORE
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/ARM/CMSIS/4.5.0/CMSIS/Documentation/Core/html/index.html
|
||||
category: doc
|
||||
version: 4.3.0
|
||||
- file: ${CMSIS_PACK_ROOT}/ARM/CMSIS/4.5.0/CMSIS/Include
|
||||
category: include
|
||||
version: 4.3.0
|
||||
- component: GigaDevice::Device:EVAL:GD32C10x@1.0.0
|
||||
condition: GD32C10x STDPERIPHERALS EVAL
|
||||
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
selected-by: Device:EVAL:GD32C10x
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Utilities/gd32c10x_eval.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_eval.c
|
||||
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
|
||||
selected-by: Device:GD32C10x_StdPeripherals:CAN
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_can.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_can.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
|
||||
selected-by: Device:GD32C10x_StdPeripherals:DBG
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_dbg.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_dbg.c
|
||||
category: source
|
||||
attr: config
|
||||
version: 1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:DMA@1.0.0
|
||||
condition: GD32C10x STDPERIPHERALS RCU
|
||||
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
selected-by: Device:GD32C10x_StdPeripherals:DMA
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_dma.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_dma.c
|
||||
category: source
|
||||
attr: config
|
||||
version: 1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:EXTI@1.0.0
|
||||
condition: GD32C10x STDPERIPHERALS RCU
|
||||
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
selected-by: Device:GD32C10x_StdPeripherals:EXTI
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_exti.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_exti.c
|
||||
category: source
|
||||
attr: config
|
||||
version: 1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:FMC@1.0.0
|
||||
condition: GD32C10x STDPERIPHERALS RCU
|
||||
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
selected-by: Device:GD32C10x_StdPeripherals:FMC
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_fmc.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_fmc.c
|
||||
category: source
|
||||
attr: config
|
||||
version: 1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:FWDGT@1.0.0
|
||||
condition: GD32C10x STDPERIPHERALS RCU
|
||||
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
selected-by: Device:GD32C10x_StdPeripherals:FWDGT
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_fwdgt.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_fwdgt.c
|
||||
category: source
|
||||
attr: config
|
||||
version: 1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:GPIO@1.0.0
|
||||
condition: GD32C10x STDPERIPHERALS RCU
|
||||
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
selected-by: Device:GD32C10x_StdPeripherals:GPIO
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_gpio.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_gpio.c
|
||||
category: source
|
||||
attr: config
|
||||
version: 1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:MISC@1.0.0
|
||||
condition: GD32C10x CMSIS
|
||||
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
selected-by: Device:GD32C10x_StdPeripherals:MISC
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_misc.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_misc.c
|
||||
category: source
|
||||
attr: config
|
||||
version: 1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:PMU@1.0.0
|
||||
condition: GD32C10x STDPERIPHERALS RCU
|
||||
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
selected-by: Device:GD32C10x_StdPeripherals:PMU
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_pmu.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_pmu.c
|
||||
category: source
|
||||
attr: config
|
||||
version: 1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:RCU@1.0.0
|
||||
condition: GD32C10x STDPERIPHERALS MISC
|
||||
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
selected-by: Device:GD32C10x_StdPeripherals:RCU
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_rcu.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_rcu.c
|
||||
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
|
||||
selected-by: Device:GD32C10x_StdPeripherals:USART
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Firmware/Peripherals/inc/gd32c10x_usart.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/gd32c10x_usart.c
|
||||
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
|
||||
selected-by: Device:GD32C10x_libopt
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Include/gd32c10x_libopt.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- component: GigaDevice::Device:Startup@1.0.0
|
||||
condition: GD32C10x
|
||||
from-pack: GigaDevice::GD32C10x_DFP@1.0.1
|
||||
selected-by: Device:Startup
|
||||
files:
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Include
|
||||
category: include
|
||||
version: 1.0.0
|
||||
- file: ${CMSIS_PACK_ROOT}/GigaDevice/GD32C10x_DFP/1.0.1/Device/Include/gd32c10x.h
|
||||
category: header
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/startup_gd32c10x.s
|
||||
category: source
|
||||
attr: config
|
||||
version: 1.0.0
|
||||
- file: ../../../../Robot_V2/RTE/Device/GD32C103CB/system_gd32c10x.c
|
||||
category: source
|
||||
attr: config
|
||||
version: 1.0.0
|
||||
linker:
|
||||
script: ../../../../Robot_V2/RTE/Device/GD32C103CB/ac6_linker_script.sct.src
|
||||
regions: ../../../../Robot_V2/RTE/Device/GD32C103CB/regions_GD32C103CB.h
|
||||
groups:
|
||||
- group: Source Files
|
||||
files:
|
||||
- file: ../../../../Robot_V2/main.h
|
||||
category: header
|
||||
- file: ../../../../Robot_V2/main.cpp
|
||||
category: sourceCpp
|
||||
- group: sys
|
||||
files:
|
||||
- file: ../../../../Robot_V2/sys/systick.cpp
|
||||
category: sourceCpp
|
||||
- file: ../../../../Robot_V2/sys/systick.h
|
||||
category: header
|
||||
- file: ../../../../Robot_V2/sys/initial.cpp
|
||||
category: sourceCpp
|
||||
- file: ../../../../Robot_V2/sys/initial.h
|
||||
category: header
|
||||
- file: ../../../../Robot_V2/sys/health.h
|
||||
category: header
|
||||
- file: ../../../../Robot_V2/sys/health.cpp
|
||||
category: sourceCpp
|
||||
- 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
|
||||
licenses:
|
||||
- license: <unknown>
|
||||
packs:
|
||||
- pack: ARM::CMSIS@4.5.0
|
||||
components:
|
||||
- component: ARM::CMSIS:CORE@4.3.0
|
||||
- license: <unknown>
|
||||
packs:
|
||||
- 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:DBG@1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:DMA@1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:EXTI@1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:FMC@1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:FWDGT@1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:GPIO@1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:MISC@1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:PMU@1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:RCU@1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:SPI_I2S@1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:TIMER@1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:USART@1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_StdPeripherals:WWDGT@1.0.0
|
||||
- component: GigaDevice::Device:GD32C10x_libopt@1.0.0
|
||||
- component: GigaDevice::Device:Startup@1.0.0
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user