This commit is contained in:
2026-03-31 23:30:33 +08:00
commit 760043c8e7
1615 changed files with 1406836 additions and 0 deletions

10
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,10 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 已忽略包含查询文件的默认文件夹
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/

2
.idea/ARES.iml generated Normal file
View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CIDR" type="CPP_MODULE" version="4" />

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Ask2AgentMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

3
.idea/debugServers/Config.xml generated Normal file
View File

@@ -0,0 +1,3 @@
<component name="DebugServers">
<config name="Config" force-enabled="true" />
</component>

13
.idea/debugServers/ST_LINK.xml generated Normal file
View File

@@ -0,0 +1,13 @@
<component name="DebugServers">
<stlink-debug-target name="ST-LINK" uniqueID="a007a660-e7df-4b71-8410-a35cf770706c" selected="true">
<debugger version="1">
<debugger kind="GDB" isBundled="true" />
<env />
</debugger>
<gdbserver exe="D:\ST\STM32CubeCLT_1.20.0\STLink-gdb-server\bin\ST-LINK_gdbserver.exe" programmer="D:\ST\STM32CubeCLT_1.20.0\STM32CubeProgrammer\bin" />
<st-link />
<device interface="SWD" />
<connection extended-remote="false" port="61234" warmup-ms="500" />
<swo enabled="false" port="61235" />
</stlink-debug-target>
</component>

349
.idea/editor.xml generated Normal file
View File

@@ -0,0 +1,349 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="BackendCodeEditorSettings">
<option name="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=Component_0020Designer_0020generated_0020code/@EntryIndexedValue" value="Component Designer generated code" type="string" />
<option name="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=Designer_0020generated_0020code/@EntryIndexedValue" value="Designer generated code" type="string" />
<option name="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=Web_0020Form_0020Designer_0020generated_0020code/@EntryIndexedValue" value="Web Form Designer generated code" type="string" />
<option name="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=Windows_0020Form_0020Designer_0020generated_0020code/@EntryIndexedValue" value="Windows Form Designer generated code" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CDeclarationWithImplicitIntType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConstevalIfIsAlwaysConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractClassWithoutSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractVirtualFunctionCallInCtor/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAccessSpecifierWithNoDeclarations/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAwaiterTypeIsNotClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBooleanIncrementExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatBadCode/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatLegacyCode/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatMixedArgs/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooFewArgs/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooManyArgs/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCVQualifierCanNotBeAppliedToReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassIsIncomplete/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeedsConstructorBecauseOfUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCompileTimeConstantCanBeReplacedWithBooleanConstant/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConceptNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConditionalExpressionCanBeSimplified/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstValueFunctionReturnType/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCoroutineCallResolveError/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAArrayIndexOutOfBounds/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantConditions/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantFunctionResult/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantParameter/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFADeletedPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAEndlessLoop/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInfiniteRecursion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInvalidatedMemory/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesScope/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALoopConditionNotUpdated/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAMemoryLeak/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANotInitializedField/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANullDereference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFATimeOver/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableCode/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableFunctionCall/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreadVariable/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnusedValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesLocal/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesUncapturedLocal/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationSpecifierWithoutDeclarators/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorDisambiguatedAsFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorUsedBeforeInitialization/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultCaseNotHandledInSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultInitializationWithNoUserConstructor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultIsUsedAsIdentifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultedSpecialMemberFunctionIsImplicitlyDeleted/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefinitionsOrder/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeletingVoidPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTemplateWithoutTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTypeWithoutTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedEntity/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedOverridenMethod/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedRegisterStorageClassSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDereferenceOperatorLimitExceeded/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDiscardedPostfixOperatorResult/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenSyntaxError/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUndocumentedParameter/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUnresolvedReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEmptyDeclaration/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersOrder/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersPlacement/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceDoStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceForStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceFunctionDeclarationStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceIfStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceNestedNamespacesStyle/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingDestructorStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingFunctionStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceTypeAliasCodeStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceWhileStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityAssignedButNoRead/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityUsedOnlyInUnevaluatedContext/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnumeratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEqualOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEvaluationFailure/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExplicitSpecializationInNonNamespaceScope/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExpressionWithoutSideEffects/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalFunctionInFinalClass/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalNonOverridingVirtualFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForLoopCanBeReplacedWithWhile/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForwardEnumDeclarationWithoutUnderlyingType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionDoesntReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionResultShouldBeUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionalStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHeaderHasBeenAlreadyIncluded/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHiddenFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHidingFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIdenticalOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIfCanBeReplacedByConstexprIf/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppImplicitDefaultConstructorNotAvailable/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompatiblePointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompleteSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInconsistentNaming/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIntegralToPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInvalidLineContinuation/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppJoinDeclarationAndAssignment/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLambdaCaptureNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberInitializersOrder/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMismatchedClassTags/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingIncludeGuard/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingKeywordThrow/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppModulePartitionWithSeveralPartitionUnits/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtAddressOfClassRValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtBindingRValueToLvalueReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtCopyElisionInCopyInitDeclarator/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtDoubleUserConversionInCopyInit/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtNotInitializedStaticConstLocalVar/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtReinterpretCastFromNullptr/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterLiteral/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterWideLiteral/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMustBePublicVirtualToImplementInterface/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMutableSpecifierOnReferenceMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNoDiscardExpression/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNodiscardFunctionWithoutReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExceptionSafeResourceAcquisition/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConversionOperator/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConvertingConstructor/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineFunctionDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineVariableDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNotAllPathsReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppObjectMemberMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppOutParameterMustBeWritten/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConstPtrOrRef/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNamesMismatch/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPassValueParameterByConstReference/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerConversionDropsQualifiers/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerToIntegralConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPolymorphicClassWithNonVirtualPublicDestructor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyErroneousEmptyStatements/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUnintendedObjectSlicing/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderIsNotIncluded/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderNotFound/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfBadFormat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfExtraArg/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfMissedArg/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfRiskyFormat/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrivateSpecialMemberFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRangeBasedForIncompatibleReference/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedefinitionOfDefaultArgumentInOverrideFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBooleanExpressionArgument/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantCastExpression/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantComplexityInComparison/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConditionalExpression/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConstSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantControlFlowJump/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantDereferencingAndTakingAddress/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElaboratedTypeSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeyword/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeywordInsideCompoundStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyDeclaration/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantExportKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantFwdClassOrEnumSpecifier/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantInlineSpecifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantLambdaParameterList/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantMemberInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantNamespaceDefinition/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantParentheses/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifier/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifierADL/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnMemberAllocationFunction/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnThreadLocalLocalVariable/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateArguments/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantVoidArgumentList/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantZeroInitializerInAggregateInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReinterpretCastFromVoidPtr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRemoveRedundantBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceMemsetWithZeroInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceTieWithStructuredBinding/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReturnNoValueInNonVoidFunction/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSmartPointerVsMakeFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSomeObjectMembersMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSpecialFunctionWithoutNoexceptSpecification/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticAssertFailure/@EntryIndexedValue" value="ERROR" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticDataMemberInUnnamedStruct/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticSpecifierOnAnonymousNamespaceMember/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStringLiteralToCharPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTabsAreDisallowed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateArgumentsCanBeDeduced/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterShadowing/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppThrowExpressionCanBeReplacedWithRethrow/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScope/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScopeInitStatement/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTypeAliasNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedDependentBaseClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedNonStaticDataMember/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnionMemberOfReferenceType/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaEndRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnamedNamespaceInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnecessaryWhitespace/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnsignedZeroComparison/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnusedIncludeDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAlgorithmWithCount/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAssociativeContains/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAuto/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAutoForNumeric/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseElementsView/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseEraseAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseFamiliarTemplateSyntaxForGenericLambdas/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseRangeAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStdSize/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStructuredBinding/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseTypeTraitAlias/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUserDefinedLiteralSuffixDoesNotStartWithUnderscore/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUsingResultOfAssignmentAsCondition/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVariableCanBeMadeConstexpr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionCallInsideCtor/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionInFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVolatileParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWarningDirective/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongIncludesOrder/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongSlashesInIncludeDirective/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroConstantCanBeReplacedWithNullptr/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroValuedExpressionUsedAsNullPointer/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="2" type="long" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="2" type="long" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
</component>
</project>

7
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakePythonSetting">
<option name="pythonIntegrationState" value="YES" />
</component>
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/ARES.iml" filepath="$PROJECT_DIR$/.idea/ARES.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

52
.mxproject Normal file

File diff suppressed because one or more lines are too long

1
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1 @@
{}

460
ARES.ioc Normal file
View File

@@ -0,0 +1,460 @@
#MicroXplorer Configuration settings - do not modify
CAD.formats=
CAD.pinconfig=
CAD.provider=
CORTEX_M7.AccessPermission_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=MPU_REGION_FULL_ACCESS
CORTEX_M7.BaseAddress_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=0x30000000
CORTEX_M7.DisableExec_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=MPU_INSTRUCTION_ACCESS_DISABLE
CORTEX_M7.Enable_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=MPU_REGION_ENABLE
CORTEX_M7.IPParameters=default_mode_Activation,Enable_S-Cortex_Memory_Protection_Unit_Region1_Settings_S,BaseAddress_S-Cortex_Memory_Protection_Unit_Region1_Settings_S,Size_S-Cortex_Memory_Protection_Unit_Region1_Settings_S,AccessPermission_S-Cortex_Memory_Protection_Unit_Region1_Settings_S,DisableExec_S-Cortex_Memory_Protection_Unit_Region1_Settings_S,IsShareable_S-Cortex_Memory_Protection_Unit_Region1_Settings_S
CORTEX_M7.IsShareable_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=MPU_ACCESS_SHAREABLE
CORTEX_M7.Size_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=MPU_REGION_SIZE_32KB
CORTEX_M7.default_mode_Activation=1
Dma.Request0=USART2_RX
Dma.Request1=UART4_RX
Dma.Request2=USART3_RX
Dma.Request3=USART6_RX
Dma.Request4=UART7_RX
Dma.RequestsNb=5
Dma.UART4_RX.1.Direction=DMA_PERIPH_TO_MEMORY
Dma.UART4_RX.1.EventEnable=DISABLE
Dma.UART4_RX.1.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.UART4_RX.1.Instance=DMA1_Stream1
Dma.UART4_RX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.UART4_RX.1.MemInc=DMA_MINC_ENABLE
Dma.UART4_RX.1.Mode=DMA_CIRCULAR
Dma.UART4_RX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.UART4_RX.1.PeriphInc=DMA_PINC_DISABLE
Dma.UART4_RX.1.Polarity=HAL_DMAMUX_REQ_GEN_RISING
Dma.UART4_RX.1.Priority=DMA_PRIORITY_HIGH
Dma.UART4_RX.1.RequestNumber=1
Dma.UART4_RX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber
Dma.UART4_RX.1.SignalID=NONE
Dma.UART4_RX.1.SyncEnable=DISABLE
Dma.UART4_RX.1.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT
Dma.UART4_RX.1.SyncRequestNumber=1
Dma.UART4_RX.1.SyncSignalID=NONE
Dma.UART7_RX.4.Direction=DMA_PERIPH_TO_MEMORY
Dma.UART7_RX.4.EventEnable=DISABLE
Dma.UART7_RX.4.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.UART7_RX.4.Instance=DMA1_Stream4
Dma.UART7_RX.4.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.UART7_RX.4.MemInc=DMA_MINC_ENABLE
Dma.UART7_RX.4.Mode=DMA_CIRCULAR
Dma.UART7_RX.4.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.UART7_RX.4.PeriphInc=DMA_PINC_DISABLE
Dma.UART7_RX.4.Polarity=HAL_DMAMUX_REQ_GEN_RISING
Dma.UART7_RX.4.Priority=DMA_PRIORITY_HIGH
Dma.UART7_RX.4.RequestNumber=1
Dma.UART7_RX.4.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber
Dma.UART7_RX.4.SignalID=NONE
Dma.UART7_RX.4.SyncEnable=DISABLE
Dma.UART7_RX.4.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT
Dma.UART7_RX.4.SyncRequestNumber=1
Dma.UART7_RX.4.SyncSignalID=NONE
Dma.USART2_RX.0.Direction=DMA_PERIPH_TO_MEMORY
Dma.USART2_RX.0.EventEnable=DISABLE
Dma.USART2_RX.0.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.USART2_RX.0.Instance=DMA1_Stream0
Dma.USART2_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.USART2_RX.0.MemInc=DMA_MINC_ENABLE
Dma.USART2_RX.0.Mode=DMA_CIRCULAR
Dma.USART2_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.USART2_RX.0.PeriphInc=DMA_PINC_DISABLE
Dma.USART2_RX.0.Polarity=HAL_DMAMUX_REQ_GEN_RISING
Dma.USART2_RX.0.Priority=DMA_PRIORITY_HIGH
Dma.USART2_RX.0.RequestNumber=1
Dma.USART2_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber
Dma.USART2_RX.0.SignalID=NONE
Dma.USART2_RX.0.SyncEnable=DISABLE
Dma.USART2_RX.0.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT
Dma.USART2_RX.0.SyncRequestNumber=1
Dma.USART2_RX.0.SyncSignalID=NONE
Dma.USART3_RX.2.Direction=DMA_PERIPH_TO_MEMORY
Dma.USART3_RX.2.EventEnable=DISABLE
Dma.USART3_RX.2.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.USART3_RX.2.Instance=DMA1_Stream2
Dma.USART3_RX.2.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.USART3_RX.2.MemInc=DMA_MINC_ENABLE
Dma.USART3_RX.2.Mode=DMA_CIRCULAR
Dma.USART3_RX.2.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.USART3_RX.2.PeriphInc=DMA_PINC_DISABLE
Dma.USART3_RX.2.Polarity=HAL_DMAMUX_REQ_GEN_RISING
Dma.USART3_RX.2.Priority=DMA_PRIORITY_HIGH
Dma.USART3_RX.2.RequestNumber=1
Dma.USART3_RX.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber
Dma.USART3_RX.2.SignalID=NONE
Dma.USART3_RX.2.SyncEnable=DISABLE
Dma.USART3_RX.2.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT
Dma.USART3_RX.2.SyncRequestNumber=1
Dma.USART3_RX.2.SyncSignalID=NONE
Dma.USART6_RX.3.Direction=DMA_PERIPH_TO_MEMORY
Dma.USART6_RX.3.EventEnable=DISABLE
Dma.USART6_RX.3.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.USART6_RX.3.Instance=DMA1_Stream3
Dma.USART6_RX.3.MemDataAlignment=DMA_MDATAALIGN_BYTE
Dma.USART6_RX.3.MemInc=DMA_MINC_ENABLE
Dma.USART6_RX.3.Mode=DMA_CIRCULAR
Dma.USART6_RX.3.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
Dma.USART6_RX.3.PeriphInc=DMA_PINC_DISABLE
Dma.USART6_RX.3.Polarity=HAL_DMAMUX_REQ_GEN_RISING
Dma.USART6_RX.3.Priority=DMA_PRIORITY_HIGH
Dma.USART6_RX.3.RequestNumber=1
Dma.USART6_RX.3.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber
Dma.USART6_RX.3.SignalID=NONE
Dma.USART6_RX.3.SyncEnable=DISABLE
Dma.USART6_RX.3.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT
Dma.USART6_RX.3.SyncRequestNumber=1
Dma.USART6_RX.3.SyncSignalID=NONE
FDCAN1.AutoRetransmission=ENABLE
FDCAN1.CalculateBaudRateNominal=1000000
FDCAN1.CalculateTimeBitNominal=1000
FDCAN1.CalculateTimeQuantumNominal=62.5
FDCAN1.IPParameters=CalculateTimeQuantumNominal,CalculateTimeBitNominal,CalculateBaudRateNominal,NominalPrescaler,NominalTimeSeg1,NominalTimeSeg2,Mode,TxFifoQueueElmtsNbr,RxFifo1ElmtsNbr,StdFiltersNbr,RxFifo0ElmtsNbr,AutoRetransmission
FDCAN1.Mode=FDCAN_MODE_NORMAL
FDCAN1.NominalPrescaler=4
FDCAN1.NominalTimeSeg1=13
FDCAN1.NominalTimeSeg2=2
FDCAN1.RxFifo0ElmtsNbr=16
FDCAN1.RxFifo1ElmtsNbr=0
FDCAN1.StdFiltersNbr=5
FDCAN1.TxFifoQueueElmtsNbr=8
FREERTOS.FootprintOK=true
FREERTOS.IPParameters=Tasks01,FootprintOK,Mutexes01,configTOTAL_HEAP_SIZE
FREERTOS.Mutexes01=logMutex,Dynamic,NULL,Available
FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;canTxTask,32,512,StartCanTxTask,Default,NULL,Dynamic,NULL,NULL;monitorTask,24,1024,StartMonitorTask,Default,NULL,Dynamic,NULL,NULL;laserTestTask,24,4096,AppTasks_RunLaserTestTask,Default,NULL,Dynamic,NULL,NULL;vl53Task,24,1024,StartVl53Task,Default,NULL,Dynamic,NULL,NULL;imuTask,16,512,StartImuTask,Default,NULL,Dynamic,NULL,NULL
FREERTOS.configTOTAL_HEAP_SIZE=65536
File.Version=6
GPIO.groupedBy=Group By Peripherals
I2C1.IPParameters=Timing
I2C1.Timing=0x307075B1
I2C2.IPParameters=Timing
I2C2.Timing=0x307075B1
KeepUserPlacement=false
MMTAppRegionsCount=0
MMTConfigApplied=false
Mcu.CPN=STM32H743VIT6
Mcu.Family=STM32H7
Mcu.IP0=CORTEX_M7
Mcu.IP1=DEBUG
Mcu.IP10=SYS
Mcu.IP11=TIM6
Mcu.IP12=UART4
Mcu.IP13=UART5
Mcu.IP14=UART7
Mcu.IP15=USART1
Mcu.IP16=USART2
Mcu.IP17=USART3
Mcu.IP18=USART6
Mcu.IP19=USB_DEVICE
Mcu.IP2=DMA
Mcu.IP20=USB_OTG_FS
Mcu.IP3=FDCAN1
Mcu.IP4=FREERTOS
Mcu.IP5=I2C1
Mcu.IP6=I2C2
Mcu.IP7=MEMORYMAP
Mcu.IP8=NVIC
Mcu.IP9=RCC
Mcu.IPNb=21
Mcu.Name=STM32H743VITx
Mcu.Package=LQFP100
Mcu.Pin0=PE3
Mcu.Pin1=PE4
Mcu.Pin10=PC5
Mcu.Pin11=PB1
Mcu.Pin12=PB2
Mcu.Pin13=PE7
Mcu.Pin14=PE8
Mcu.Pin15=PB10
Mcu.Pin16=PB11
Mcu.Pin17=PB13
Mcu.Pin18=PB14
Mcu.Pin19=PB15
Mcu.Pin2=PC14-OSC32_IN (OSC32_IN)
Mcu.Pin20=PD8
Mcu.Pin21=PD9
Mcu.Pin22=PD11
Mcu.Pin23=PD12
Mcu.Pin24=PD13
Mcu.Pin25=PD14
Mcu.Pin26=PC6
Mcu.Pin27=PC7
Mcu.Pin28=PA11
Mcu.Pin29=PA12
Mcu.Pin3=PC15-OSC32_OUT (OSC32_OUT)
Mcu.Pin30=PA13 (JTMS/SWDIO)
Mcu.Pin31=PA14 (JTCK/SWCLK)
Mcu.Pin32=PD0
Mcu.Pin33=PD1
Mcu.Pin34=PB6
Mcu.Pin35=PB7
Mcu.Pin36=VP_FREERTOS_VS_CMSIS_V2
Mcu.Pin37=VP_SYS_VS_tim7
Mcu.Pin38=VP_TIM6_VS_ClockSourceINT
Mcu.Pin39=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS
Mcu.Pin4=PH0-OSC_IN (PH0)
Mcu.Pin40=VP_MEMORYMAP_VS_MEMORYMAP
Mcu.Pin5=PH1-OSC_OUT (PH1)
Mcu.Pin6=PA0
Mcu.Pin7=PA1
Mcu.Pin8=PA2
Mcu.Pin9=PA3
Mcu.PinsNb=41
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32H743VITx
MxCube.Version=6.15.0
MxDb.Version=DB.6.0.150
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
NVIC.DMA1_Stream0_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
NVIC.DMA1_Stream1_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
NVIC.DMA1_Stream2_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
NVIC.DMA1_Stream3_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
NVIC.DMA1_Stream4_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
NVIC.FDCAN1_IT0_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true\:true
NVIC.ForceEnableDMAVector=true
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
NVIC.OTG_FS_IRQn=true\:5\:0\:true\:false\:true\:true\:false\:true\:true
NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:false\:false
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false\:false
NVIC.SavedPendsvIrqHandlerGenerated=true
NVIC.SavedSvcallIrqHandlerGenerated=true
NVIC.SavedSystickIrqHandlerGenerated=true
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:true\:false
NVIC.TIM6_DAC_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
NVIC.TIM7_IRQn=true\:15\:0\:false\:false\:true\:false\:false\:true\:true
NVIC.TimeBase=TIM7_IRQn
NVIC.TimeBaseIP=TIM7
NVIC.UART4_IRQn=true\:6\:0\:true\:false\:true\:true\:true\:true\:true
NVIC.UART7_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
NVIC.USART2_IRQn=true\:6\:0\:true\:false\:true\:true\:true\:true\:true
NVIC.USART3_IRQn=true\:6\:0\:true\:false\:true\:true\:true\:true\:true
NVIC.USART6_IRQn=true\:6\:0\:true\:false\:true\:true\:true\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
PA0.Mode=Asynchronous
PA0.Signal=UART4_TX
PA1.Mode=Asynchronous
PA1.Signal=UART4_RX
PA11.Mode=Device_Only
PA11.Signal=USB_OTG_FS_DM
PA12.Mode=Device_Only
PA12.Signal=USB_OTG_FS_DP
PA13\ (JTMS/SWDIO).Mode=Serial_Wire
PA13\ (JTMS/SWDIO).Signal=DEBUG_JTMS-SWDIO
PA14\ (JTCK/SWCLK).Mode=Serial_Wire
PA14\ (JTCK/SWCLK).Signal=DEBUG_JTCK-SWCLK
PA2.Mode=Asynchronous
PA2.Signal=USART2_TX
PA3.Mode=Asynchronous
PA3.Signal=USART2_RX
PB1.Locked=true
PB1.Signal=GPIO_Output
PB10.Mode=I2C
PB10.Signal=I2C2_SCL
PB11.Mode=I2C
PB11.Signal=I2C2_SDA
PB13.Mode=Half_duplex(single_wire_mode)
PB13.Signal=UART5_TX
PB14.Mode=Asynchronous
PB14.Signal=USART1_TX
PB15.Mode=Asynchronous
PB15.Signal=USART1_RX
PB2.Locked=true
PB2.Signal=GPIO_Output
PB6.Mode=I2C
PB6.Signal=I2C1_SCL
PB7.Mode=I2C
PB7.Signal=I2C1_SDA
PC14-OSC32_IN\ (OSC32_IN).Mode=LSE-External-Oscillator
PC14-OSC32_IN\ (OSC32_IN).Signal=RCC_OSC32_IN
PC15-OSC32_OUT\ (OSC32_OUT).Mode=LSE-External-Oscillator
PC15-OSC32_OUT\ (OSC32_OUT).Signal=RCC_OSC32_OUT
PC5.Locked=true
PC5.Signal=GPIO_Output
PC6.Mode=Asynchronous
PC6.Signal=USART6_TX
PC7.Mode=Asynchronous
PC7.Signal=USART6_RX
PD0.GPIOParameters=GPIO_Speed
PD0.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
PD0.Mode=FDCAN_Activate
PD0.Signal=FDCAN1_RX
PD1.GPIOParameters=GPIO_Speed
PD1.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
PD1.Mode=FDCAN_Activate
PD1.Signal=FDCAN1_TX
PD11.Locked=true
PD11.Signal=GPIO_Output
PD12.Locked=true
PD12.Signal=GPIO_Output
PD13.Locked=true
PD13.Signal=GPIO_Output
PD14.Locked=true
PD14.Signal=GPIO_Output
PD8.Mode=Asynchronous
PD8.Signal=USART3_TX
PD9.Mode=Asynchronous
PD9.Signal=USART3_RX
PE3.Locked=true
PE3.Signal=GPIO_Output
PE4.Locked=true
PE4.Signal=GPIO_Output
PE7.Mode=Asynchronous
PE7.Signal=UART7_RX
PE8.Mode=Asynchronous
PE8.Signal=UART7_TX
PH0-OSC_IN\ (PH0).Mode=HSE-External-Oscillator
PH0-OSC_IN\ (PH0).Signal=RCC_OSC_IN
PH1-OSC_OUT\ (PH1).Mode=HSE-External-Oscillator
PH1-OSC_OUT\ (PH1).Signal=RCC_OSC_OUT
PinOutPanel.RotationAngle=0
ProjectManager.AskForMigrate=true
ProjectManager.BackupPrevious=false
ProjectManager.CompilerLinker=GCC
ProjectManager.CompilerOptimize=6
ProjectManager.ComputerToolchain=false
ProjectManager.CoupleFile=true
ProjectManager.CustomerFirmwarePackage=
ProjectManager.DefaultFWLocation=true
ProjectManager.DeletePrevious=true
ProjectManager.DeviceId=STM32H743VITx
ProjectManager.FirmwarePackage=STM32Cube FW_H7 V1.12.1
ProjectManager.FreePins=false
ProjectManager.HalAssertFull=false
ProjectManager.HeapSize=0x1000
ProjectManager.KeepUserCode=true
ProjectManager.LastFirmware=true
ProjectManager.LibraryCopy=0
ProjectManager.MainLocation=Core/Src
ProjectManager.NoMain=false
ProjectManager.PreviousToolchain=
ProjectManager.ProjectBuild=false
ProjectManager.ProjectFileName=ARES.ioc
ProjectManager.ProjectName=ARES
ProjectManager.ProjectStructure=
ProjectManager.RegisterCallBack=
ProjectManager.StackSize=0x400
ProjectManager.TargetToolchain=CMake
ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath=
ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_FDCAN1_Init-FDCAN1-false-HAL-true,5-MX_TIM6_Init-TIM6-false-HAL-true,6-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL-false,7-MX_I2C1_Init-I2C1-false-HAL-true,8-MX_I2C2_Init-I2C2-false-HAL-true,9-MX_UART4_Init-UART4-false-HAL-true,10-MX_UART5_Init-UART5-false-HAL-true,11-MX_UART7_Init-UART7-false-HAL-true,12-MX_USART1_UART_Init-USART1-false-HAL-true,13-MX_USART2_UART_Init-USART2-false-HAL-true,14-MX_USART3_UART_Init-USART3-false-HAL-true,15-MX_USART6_UART_Init-USART6-false-HAL-true,0-MX_CORTEX_M7_Init-CORTEX_M7-false-HAL-true
RCC.ADCFreq_Value=50390625
RCC.AHB12Freq_Value=240000000
RCC.AHB4Freq_Value=240000000
RCC.APB1Freq_Value=120000000
RCC.APB2Freq_Value=120000000
RCC.APB3Freq_Value=120000000
RCC.APB4Freq_Value=120000000
RCC.AXIClockFreq_Value=240000000
RCC.CECFreq_Value=32000
RCC.CKPERFreq_Value=64000000
RCC.CortexFreq_Value=480000000
RCC.CpuClockFreq_Value=480000000
RCC.D1CPREFreq_Value=480000000
RCC.D1PPRE=RCC_APB3_DIV2
RCC.D2PPRE1=RCC_APB1_DIV2
RCC.D2PPRE2=RCC_APB2_DIV2
RCC.D3PPRE=RCC_APB4_DIV2
RCC.DFSDMACLkFreq_Value=64000000
RCC.DFSDMFreq_Value=120000000
RCC.DIVM1=5
RCC.DIVN1=192
RCC.DIVP1Freq_Value=480000000
RCC.DIVP2Freq_Value=50390625
RCC.DIVP3Freq_Value=50390625
RCC.DIVQ1=15
RCC.DIVQ1Freq_Value=64000000
RCC.DIVQ2Freq_Value=50390625
RCC.DIVQ3Freq_Value=50390625
RCC.DIVR1Freq_Value=480000000
RCC.DIVR2Freq_Value=50390625
RCC.DIVR3Freq_Value=50390625
RCC.FDCANFreq_Value=64000000
RCC.FMCFreq_Value=240000000
RCC.FamilyName=M
RCC.HCLK3ClockFreq_Value=240000000
RCC.HCLKFreq_Value=240000000
RCC.HPRE=RCC_HCLK_DIV2
RCC.HRTIMFreq_Value=240000000
RCC.I2C123Freq_Value=120000000
RCC.I2C4Freq_Value=120000000
RCC.IPParameters=ADCFreq_Value,AHB12Freq_Value,AHB4Freq_Value,APB1Freq_Value,APB2Freq_Value,APB3Freq_Value,APB4Freq_Value,AXIClockFreq_Value,CECFreq_Value,CKPERFreq_Value,CortexFreq_Value,CpuClockFreq_Value,D1CPREFreq_Value,D1PPRE,D2PPRE1,D2PPRE2,D3PPRE,DFSDMACLkFreq_Value,DFSDMFreq_Value,DIVM1,DIVN1,DIVP1Freq_Value,DIVP2Freq_Value,DIVP3Freq_Value,DIVQ1,DIVQ1Freq_Value,DIVQ2Freq_Value,DIVQ3Freq_Value,DIVR1Freq_Value,DIVR2Freq_Value,DIVR3Freq_Value,FDCANFreq_Value,FMCFreq_Value,FamilyName,HCLK3ClockFreq_Value,HCLKFreq_Value,HPRE,HRTIMFreq_Value,I2C123Freq_Value,I2C4Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPTIM345Freq_Value,LPUART1Freq_Value,LTDCFreq_Value,MCO1PinFreq_Value,MCO2PinFreq_Value,PLL1_VCI_Range,PLL2FRACN,PLL3FRACN,PLLFRACN,PLLSourceVirtual,QSPIFreq_Value,RNGFreq_Value,RTCFreq_Value,SAI1Freq_Value,SAI23Freq_Value,SAI4AFreq_Value,SAI4BFreq_Value,SDMMCFreq_Value,SPDIFRXFreq_Value,SPI123Freq_Value,SPI45Freq_Value,SPI6Freq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,Tim1OutputFreq_Value,Tim2OutputFreq_Value,TraceFreq_Value,USART16Freq_Value,USART234578Freq_Value,USBCLockSelection,USBFreq_Value,VCO1OutputFreq_Value,VCO2OutputFreq_Value,VCO3OutputFreq_Value,VCOInput1Freq_Value,VCOInput2Freq_Value,VCOInput3Freq_Value
RCC.LPTIM1Freq_Value=120000000
RCC.LPTIM2Freq_Value=120000000
RCC.LPTIM345Freq_Value=120000000
RCC.LPUART1Freq_Value=120000000
RCC.LTDCFreq_Value=50390625
RCC.MCO1PinFreq_Value=64000000
RCC.MCO2PinFreq_Value=480000000
RCC.PLL1_VCI_Range=RCC_PLL1VCIRANGE_3
RCC.PLL2FRACN=0
RCC.PLL3FRACN=0
RCC.PLLFRACN=0
RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE
RCC.QSPIFreq_Value=240000000
RCC.RNGFreq_Value=48000000
RCC.RTCFreq_Value=32000
RCC.SAI1Freq_Value=64000000
RCC.SAI23Freq_Value=64000000
RCC.SAI4AFreq_Value=64000000
RCC.SAI4BFreq_Value=64000000
RCC.SDMMCFreq_Value=64000000
RCC.SPDIFRXFreq_Value=64000000
RCC.SPI123Freq_Value=64000000
RCC.SPI45Freq_Value=120000000
RCC.SPI6Freq_Value=120000000
RCC.SWPMI1Freq_Value=120000000
RCC.SYSCLKFreq_VALUE=480000000
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
RCC.Tim1OutputFreq_Value=240000000
RCC.Tim2OutputFreq_Value=240000000
RCC.TraceFreq_Value=480000000
RCC.USART16Freq_Value=120000000
RCC.USART234578Freq_Value=120000000
RCC.USBCLockSelection=RCC_USBCLKSOURCE_HSI48
RCC.USBFreq_Value=48000000
RCC.VCO1OutputFreq_Value=960000000
RCC.VCO2OutputFreq_Value=100781250
RCC.VCO3OutputFreq_Value=100781250
RCC.VCOInput1Freq_Value=5000000
RCC.VCOInput2Freq_Value=781250
RCC.VCOInput3Freq_Value=781250
TIM6.IPParameters=Prescaler,Period
TIM6.Period=100 - 1
TIM6.Prescaler=24000 - 1
UART4.BaudRate=230400
UART4.IPParameters=BaudRate
USART1.IPParameters=VirtualMode-Asynchronous
USART1.VirtualMode-Asynchronous=VM_ASYNC
USART2.BaudRate=230400
USART2.IPParameters=VirtualMode-Asynchronous,BaudRate
USART2.VirtualMode-Asynchronous=VM_ASYNC
USART3.IPParameters=VirtualMode-Asynchronous
USART3.VirtualMode-Asynchronous=VM_ASYNC
USART6.IPParameters=VirtualMode
USART6.VirtualMode=VM_ASYNC
USB_DEVICE.CLASS_NAME_FS=CDC
USB_DEVICE.IPParameters=VirtualMode-CDC_FS,VirtualModeFS,CLASS_NAME_FS
USB_DEVICE.VirtualMode-CDC_FS=Cdc
USB_DEVICE.VirtualModeFS=Cdc_FS
USB_OTG_FS.IPParameters=VirtualMode
USB_OTG_FS.VirtualMode=Device_Only
VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2
VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2
VP_MEMORYMAP_VS_MEMORYMAP.Mode=CurAppReg
VP_MEMORYMAP_VS_MEMORYMAP.Signal=MEMORYMAP_VS_MEMORYMAP
VP_SYS_VS_tim7.Mode=TIM7
VP_SYS_VS_tim7.Signal=SYS_VS_tim7
VP_TIM6_VS_ClockSourceINT.Mode=Enable_Timer
VP_TIM6_VS_ClockSourceINT.Signal=TIM6_VS_ClockSourceINT
VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Mode=CDC_FS
VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Signal=USB_DEVICE_VS_USB_DEVICE_CDC_FS
board=custom
rtos.0.ip=FREERTOS

BIN
ARES.zip Normal file

Binary file not shown.

483
App/Can/snc_can_app.c Normal file
View File

@@ -0,0 +1,483 @@
#include "snc_can_app.h"
#include <string.h>
#include <math.h>
#include "FreeRTOS.h"
#include "task.h"
/* ========================= 外部句柄 ========================= */
extern FDCAN_HandleTypeDef hfdcan1;
/* ========================= 在线判定参数 ========================= */
#define SNC_STATUS_TIMEOUT_MS 200U
#define SNC_ACTUAL_RPM_TIMEOUT_MS 200U
#define SNC_TARGET_RPM_TIMEOUT_MS 200U
#define SNC_COMM_DIAG_TIMEOUT_MS 300U
/* ========================= FDCAN 过滤器索引 ========================= */
#define SNC_FILTER_INDEX_STATUS 0U
#define SNC_FILTER_INDEX_ACTUAL_RPM 1U
#define SNC_FILTER_INDEX_TARGET_RPM 2U
#define SNC_FILTER_INDEX_COMM_DIAG 3U
#define SNC_FILTER_INDEX_ODOM 4U
SNC_CAN_AppContext_t g_snc_can_app;
/* ========================= CRC8-SAE J1850 查表 ========================= */
static const uint8_t s_crc8_j1850_table[256] =
{
0x00U, 0x1DU, 0x3AU, 0x27U, 0x74U, 0x69U, 0x4EU, 0x53U, 0xE8U, 0xF5U, 0xD2U, 0xCFU, 0x9CU, 0x81U, 0xA6U, 0xBBU,
0xCDU, 0xD0U, 0xF7U, 0xEAU, 0xB9U, 0xA4U, 0x83U, 0x9EU, 0x25U, 0x38U, 0x1FU, 0x02U, 0x51U, 0x4CU, 0x6BU, 0x76U,
0x87U, 0x9AU, 0xBDU, 0xA0U, 0xF3U, 0xEEU, 0xC9U, 0xD4U, 0x6FU, 0x72U, 0x55U, 0x48U, 0x1BU, 0x06U, 0x21U, 0x3CU,
0x4AU, 0x57U, 0x70U, 0x6DU, 0x3EU, 0x23U, 0x04U, 0x19U, 0xA2U, 0xBFU, 0x98U, 0x85U, 0xD6U, 0xCBU, 0xECU, 0xF1U,
0x13U, 0x0EU, 0x29U, 0x34U, 0x67U, 0x7AU, 0x5DU, 0x40U, 0xFBU, 0xE6U, 0xC1U, 0xDCU, 0x8FU, 0x92U, 0xB5U, 0xA8U,
0xDEU, 0xC3U, 0xE4U, 0xF9U, 0xAAU, 0xB7U, 0x90U, 0x8DU, 0x36U, 0x2BU, 0x0CU, 0x11U, 0x42U, 0x5FU, 0x78U, 0x65U,
0x94U, 0x89U, 0xAEU, 0xB3U, 0xE0U, 0xFDU, 0xDAU, 0xC7U, 0x7CU, 0x61U, 0x46U, 0x5BU, 0x08U, 0x15U, 0x32U, 0x2FU,
0x59U, 0x44U, 0x63U, 0x7EU, 0x2DU, 0x30U, 0x17U, 0x0AU, 0xB1U, 0xACU, 0x8BU, 0x96U, 0xC5U, 0xD8U, 0xFFU, 0xE2U,
0x26U, 0x3BU, 0x1CU, 0x01U, 0x52U, 0x4FU, 0x68U, 0x75U, 0xCEU, 0xD3U, 0xF4U, 0xE9U, 0xBAU, 0xA7U, 0x80U, 0x9DU,
0xEBU, 0xF6U, 0xD1U, 0xCCU, 0x9FU, 0x82U, 0xA5U, 0xB8U, 0x03U, 0x1EU, 0x39U, 0x24U, 0x77U, 0x6AU, 0x4DU, 0x50U,
0xA1U, 0xBCU, 0x9BU, 0x86U, 0xD5U, 0xC8U, 0xEFU, 0xF2U, 0x49U, 0x54U, 0x73U, 0x6EU, 0x3DU, 0x20U, 0x07U, 0x1AU,
0x6CU, 0x71U, 0x56U, 0x4BU, 0x18U, 0x05U, 0x22U, 0x3FU, 0x84U, 0x99U, 0xBEU, 0xA3U, 0xF0U, 0xEDU, 0xCAU, 0xD7U,
0x35U, 0x28U, 0x0FU, 0x12U, 0x41U, 0x5CU, 0x7BU, 0x66U, 0xDDU, 0xC0U, 0xE7U, 0xFAU, 0xA9U, 0xB4U, 0x93U, 0x8EU,
0xF8U, 0xE5U, 0xC2U, 0xDFU, 0x8CU, 0x91U, 0xB6U, 0xABU, 0x10U, 0x0DU, 0x2AU, 0x37U, 0x64U, 0x79U, 0x5EU, 0x43U,
0xB2U, 0xAFU, 0x88U, 0x95U, 0xC6U, 0xDBU, 0xFCU, 0xE1U, 0x5AU, 0x47U, 0x60U, 0x7DU, 0x2EU, 0x33U, 0x14U, 0x09U,
0x7FU, 0x62U, 0x45U, 0x58U, 0x0BU, 0x16U, 0x31U, 0x2CU, 0x97U, 0x8AU, 0xADU, 0xB0U, 0xE3U, 0xFEU, 0xD9U, 0xC4U
};
static inline int16_t snc_read_i16_le(uint8_t lo, uint8_t hi)
{
return (int16_t)((uint16_t)lo | ((uint16_t)hi << 8));
}
static inline void snc_write_i16_le(uint8_t *dst, int16_t val)
{
dst[0] = (uint8_t)(val & 0xFF);
dst[1] = (uint8_t)((uint16_t)val >> 8);
}
static int16_t snc_saturate_float_to_i16(float x)
{
if (x > 32767.0f) return 32767;
if (x < -32768.0f) return -32768;
// 手动实现四舍五入,避免调用 lroundf 库函数
return (int16_t)(x >= 0.0f ? (x + 0.5f) : (x - 0.5f));
}
uint8_t SNC_CAN_Crc8J1850(const uint8_t *data, uint16_t len)
{
uint8_t crc = 0xFFU;
while (len-- > 0U)
{
crc = s_crc8_j1850_table[(uint8_t)(crc ^ *data++)];
}
return (uint8_t)(crc ^ 0xFFU);
}
static uint32_t snc_fdcan_dlc_from_bytes(uint8_t dlc_bytes)
{
switch (dlc_bytes)
{
case 0: return FDCAN_DLC_BYTES_0;
case 1: return FDCAN_DLC_BYTES_1;
case 2: return FDCAN_DLC_BYTES_2;
case 3: return FDCAN_DLC_BYTES_3;
case 4: return FDCAN_DLC_BYTES_4;
case 5: return FDCAN_DLC_BYTES_5;
case 6: return FDCAN_DLC_BYTES_6;
case 7: return FDCAN_DLC_BYTES_7;
case 8: return FDCAN_DLC_BYTES_8;
default: return FDCAN_DLC_BYTES_8;
}
}
static HAL_StatusTypeDef snc_fdcan_add_tx_std(uint16_t std_id, const uint8_t *data, uint8_t dlc_bytes)
{
FDCAN_TxHeaderTypeDef txHeader;
memset(&txHeader, 0, sizeof(txHeader));
txHeader.Identifier = std_id;
txHeader.IdType = FDCAN_STANDARD_ID;
txHeader.TxFrameType = FDCAN_DATA_FRAME;
txHeader.DataLength = snc_fdcan_dlc_from_bytes(dlc_bytes);
txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
txHeader.BitRateSwitch = FDCAN_BRS_OFF;
txHeader.FDFormat = FDCAN_CLASSIC_CAN;
txHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
txHeader.MessageMarker = 0U;
/* 先判断 TX FIFO/Queue 是否有空位,避免异常状态下继续硬塞 */
if (HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) == 0U)
{
return HAL_BUSY;
}
return HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, (uint8_t *)data);
}
static void snc_fdcan_config_filter(uint32_t index, uint16_t std_id)
{
FDCAN_FilterTypeDef sFilter;
sFilter.IdType = FDCAN_STANDARD_ID;
sFilter.FilterIndex = index;
sFilter.FilterType = FDCAN_FILTER_MASK;
sFilter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilter.FilterID1 = std_id;
sFilter.FilterID2 = 0x7FFU; /* 完全匹配 11-bit ID */
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilter) != HAL_OK)
{
Error_Handler();
}
}
static void snc_parse_status(const uint8_t *d)
{
g_snc_can_app.status.state = d[0];
g_snc_can_app.status.health = d[1];
g_snc_can_app.status.diag_bits =
((uint32_t)d[2]) |
((uint32_t)d[3] << 8) |
((uint32_t)d[4] << 16) |
((uint32_t)d[5] << 24);
g_snc_can_app.status.cmd_age_10ms = d[6];
g_snc_can_app.status.status_counter = d[7];
g_snc_can_app.status.last_update_ms = HAL_GetTick();
g_snc_can_app.status.online = true;
}
static void snc_parse_actual_rpm(const uint8_t *d)
{
g_snc_can_app.actual_rpm.fl = snc_read_i16_le(d[0], d[1]);
g_snc_can_app.actual_rpm.rl = snc_read_i16_le(d[2], d[3]);
g_snc_can_app.actual_rpm.fr = snc_read_i16_le(d[4], d[5]);
g_snc_can_app.actual_rpm.rr = snc_read_i16_le(d[6], d[7]);
g_snc_can_app.actual_rpm.last_update_ms = HAL_GetTick();
}
static void snc_parse_target_rpm(const uint8_t *d)
{
g_snc_can_app.target_rpm.fl = snc_read_i16_le(d[0], d[1]);
g_snc_can_app.target_rpm.rl = snc_read_i16_le(d[2], d[3]);
g_snc_can_app.target_rpm.fr = snc_read_i16_le(d[4], d[5]);
g_snc_can_app.target_rpm.rr = snc_read_i16_le(d[6], d[7]);
g_snc_can_app.target_rpm.last_update_ms = HAL_GetTick();
}
static void snc_parse_comm_diag(const uint8_t *d)
{
g_snc_can_app.comm_diag.valid_cmd_total_lsb = d[0];
g_snc_can_app.comm_diag.crc_error_total_lsb = d[1];
g_snc_can_app.comm_diag.counter_reject_total_lsb = d[2];
g_snc_can_app.comm_diag.can_tx_drop_total_lsb = d[3];
g_snc_can_app.comm_diag.busoff_total_lsb = d[4];
g_snc_can_app.comm_diag.rx_overrun_total_lsb = d[5];
g_snc_can_app.comm_diag.last_accepted_counter = d[6];
g_snc_can_app.comm_diag.consecutive_counter_errors = (uint8_t)((d[7] >> 4) & 0x0F);
g_snc_can_app.comm_diag.consecutive_crc_errors = (uint8_t)(d[7] & 0x0F);
g_snc_can_app.comm_diag.last_update_ms = HAL_GetTick();
}
static void snc_parse_odom_delta(const uint8_t *d)
{
uint32_t now = HAL_GetTick();
uint32_t prev_update_ms = g_snc_can_app.odom_delta.last_update_ms;
/* 保留最近一帧快照(兼容性,调试用) */
g_snc_can_app.odom_delta.fl_delta = snc_read_i16_le(d[0], d[1]);
g_snc_can_app.odom_delta.rl_delta = snc_read_i16_le(d[2], d[3]);
g_snc_can_app.odom_delta.fr_delta = snc_read_i16_le(d[4], d[5]);
g_snc_can_app.odom_delta.rr_delta = snc_read_i16_le(d[6], d[7]);
g_snc_can_app.odom_delta.last_update_ms = now;
/* ---- 累加到待消费缓冲区,解决漏积分问题 ---- */
SNC_OdomDeltaAccum_t *acc = &g_snc_can_app.odom_accum;
acc->fl_accum += (int32_t)snc_read_i16_le(d[0], d[1]);
acc->rl_accum += (int32_t)snc_read_i16_le(d[2], d[3]);
acc->fr_accum += (int32_t)snc_read_i16_le(d[4], d[5]);
acc->rr_accum += (int32_t)snc_read_i16_le(d[6], d[7]);
if (acc->frame_count == 0U) {
acc->first_frame_ms = now;
}
acc->last_frame_ms = now;
/*
* 累加增量真实覆盖的时间窗。
* 每个 0x200 帧表示“自上一帧以来”的编码器增量,
* 因此应累加相邻帧之间的时间差,而不是简单用 last-first。
*/
if (prev_update_ms != 0U) {
uint32_t frame_dt_ms = now - prev_update_ms;
if (frame_dt_ms <= 1000U) {
acc->span_ms += frame_dt_ms;
}
}
if (acc->frame_count < 255U) {
acc->frame_count++;
}
}
void SNC_CAN_AppInit(void)
{
memset(&g_snc_can_app, 0, sizeof(g_snc_can_app));
/* 配置 5 个标准滤波器,只接收协议相关 ID */
snc_fdcan_config_filter(SNC_FILTER_INDEX_STATUS, SNC_CAN_ID_STATUS);
snc_fdcan_config_filter(SNC_FILTER_INDEX_ACTUAL_RPM, SNC_CAN_ID_ACTUAL_RPM);
snc_fdcan_config_filter(SNC_FILTER_INDEX_TARGET_RPM, SNC_CAN_ID_TARGET_RPM);
snc_fdcan_config_filter(SNC_FILTER_INDEX_COMM_DIAG, SNC_CAN_ID_COMM_DIAG);
snc_fdcan_config_filter(SNC_FILTER_INDEX_ODOM, SNC_CAN_ID_ODOM);
/* 其余标准帧/扩展帧全部拒收 */
if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1,
FDCAN_REJECT,
FDCAN_REJECT,
FDCAN_REJECT_REMOTE,
FDCAN_REJECT_REMOTE) != HAL_OK)
{
Error_Handler();
}
if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
if (HAL_FDCAN_ActivateNotification(&hfdcan1,
FDCAN_IT_RX_FIFO0_NEW_MESSAGE,
0U) != HAL_OK)
{
Error_Handler();
}
}
HAL_StatusTypeDef SNC_CAN_SendHeartbeat(void)
{
uint8_t data[0];
HAL_StatusTypeDef ret = snc_fdcan_add_tx_std(SNC_CAN_ID_HEARTBEAT, data, 0U);
if (ret == HAL_OK)
{
g_snc_can_app.tx_total++;
}
else
{
g_snc_can_app.tx_fail_total++;
}
return ret;
}
HAL_StatusTypeDef SNC_CAN_SendCmdVel(float vx_mps, float wz_radps, uint8_t ctrl_flags)
{
uint8_t data[8];
int16_t vx_i16 = snc_saturate_float_to_i16(vx_mps * 1000.0f);
int16_t wz_i16 = snc_saturate_float_to_i16(wz_radps * 1000.0f);
HAL_StatusTypeDef ret;
g_snc_can_app.tx_counter = (uint8_t)(g_snc_can_app.tx_counter + 1U);
g_snc_can_app.tx_ctrl_flags = ctrl_flags;
snc_write_i16_le(&data[0], vx_i16);
snc_write_i16_le(&data[2], wz_i16);
data[4] = ctrl_flags;
data[5] = 0U;
data[6] = g_snc_can_app.tx_counter;
data[7] = SNC_CAN_Crc8J1850(data, 7U);
ret = snc_fdcan_add_tx_std(SNC_CAN_ID_CMD_VEL, data, 8U);
if (ret == HAL_OK)
{
g_snc_can_app.tx_total++;
}
else
{
g_snc_can_app.tx_fail_total++;
}
return ret;
}
void SNC_CAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t rxFifo0ITs)
{
FDCAN_RxHeaderTypeDef rxHeader;
uint8_t data[8];
if (hfdcan != &hfdcan1)
{
return;
}
if ((rxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) == 0U)
{
return;
}
while (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO0) > 0U)
{
if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &rxHeader, data) != HAL_OK)
{
break;
}
if ((rxHeader.IdType != FDCAN_STANDARD_ID) ||
(rxHeader.RxFrameType != FDCAN_DATA_FRAME))
{
continue;
}
g_snc_can_app.rx_total++;
switch (rxHeader.Identifier)
{
case SNC_CAN_ID_STATUS:
if (rxHeader.DataLength == FDCAN_DLC_BYTES_8)
{
snc_parse_status(data);
}
break;
case SNC_CAN_ID_ACTUAL_RPM:
if (rxHeader.DataLength == FDCAN_DLC_BYTES_8)
{
snc_parse_actual_rpm(data);
}
break;
case SNC_CAN_ID_TARGET_RPM:
if (rxHeader.DataLength == FDCAN_DLC_BYTES_8)
{
snc_parse_target_rpm(data);
}
break;
case SNC_CAN_ID_COMM_DIAG:
if (rxHeader.DataLength == FDCAN_DLC_BYTES_8)
{
snc_parse_comm_diag(data);
}
break;
case SNC_CAN_ID_ODOM:
if (rxHeader.DataLength == FDCAN_DLC_BYTES_8)
{
snc_parse_odom_delta(data);
}
break;
default:
break;
}
}
}
void SNC_CAN_20msTask(void)
{
/* 这里默认发心跳。
速度命令建议由你的上层控制逻辑每 20ms 调 SNC_CAN_SendCmdVel()。 */
(void)SNC_CAN_SendHeartbeat();
}
void SNC_CAN_100msTask(void)
{
/* 使用静态变量记录上一次的接收总数 */
static uint32_t last_rx_total = 0;
/* 如果当前总数和上次记录的总数不一致,说明这 100ms 内成功收到了新消息 */
if (g_snc_can_app.rx_total != last_rx_total)
{
last_rx_total = g_snc_can_app.rx_total;
// 翻转 PE2 电平,产生肉眼可见的闪烁效果
HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_3);
}
else
{
/* 如果 100ms 内没有收到任何新消息CAN 断开或下位机死机)
强制关闭 LED。
注意:这里假设高电平 (SET) 是熄灭。如果是低电平熄灭,请改为 GPIO_PIN_RESET */
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
}
}
void SNC_CAN_PollOnlineState(uint32_t now_ms)
{
if ((now_ms - g_snc_can_app.status.last_update_ms) > SNC_STATUS_TIMEOUT_MS)
{
g_snc_can_app.status.online = false;
}
}
const SNC_CAN_AppContext_t *SNC_CAN_GetContext(void)
{
return &g_snc_can_app;
}
uint8_t SNC_CAN_ConsumeOdomDelta(int16_t *fl, int16_t *rl,
int16_t *fr, int16_t *rr,
uint32_t *dt_ms)
{
/*
* 原子取走累加器内容并清零。
*
* 本函数由 monitorTask (普通任务上下文) 调用,
* 而写端 snc_parse_odom_delta() 运行在 CAN Rx ISR 中。
*
* 用 taskENTER_CRITICAL / taskEXIT_CRITICAL 保证取走 + 清零
* 的原子性:临界区会关中断,防止 ISR 在取走过程中写入新增量。
*/
SNC_OdomDeltaAccum_t snapshot;
uint8_t count;
taskENTER_CRITICAL();
{
snapshot = g_snc_can_app.odom_accum; /* 结构体拷贝 */
/* 清零累加器,等待下一批帧 */
g_snc_can_app.odom_accum.fl_accum = 0;
g_snc_can_app.odom_accum.rl_accum = 0;
g_snc_can_app.odom_accum.fr_accum = 0;
g_snc_can_app.odom_accum.rr_accum = 0;
g_snc_can_app.odom_accum.first_frame_ms = 0U;
g_snc_can_app.odom_accum.last_frame_ms = 0U;
g_snc_can_app.odom_accum.span_ms = 0U;
g_snc_can_app.odom_accum.frame_count = 0U;
}
taskEXIT_CRITICAL();
count = snapshot.frame_count;
if (count == 0U) {
/* 期间没有新帧到达 */
*fl = 0; *rl = 0; *fr = 0; *rr = 0;
*dt_ms = 0U;
return 0U;
}
/* int32 → int16 饱和截断(正常工况下不会溢出) */
*fl = (int16_t)((snapshot.fl_accum > 32767) ? 32767 :
(snapshot.fl_accum < -32768) ? -32768 : snapshot.fl_accum);
*rl = (int16_t)((snapshot.rl_accum > 32767) ? 32767 :
(snapshot.rl_accum < -32768) ? -32768 : snapshot.rl_accum);
*fr = (int16_t)((snapshot.fr_accum > 32767) ? 32767 :
(snapshot.fr_accum < -32768) ? -32768 : snapshot.fr_accum);
*rr = (int16_t)((snapshot.rr_accum > 32767) ? 32767 :
(snapshot.rr_accum < -32768) ? -32768 : snapshot.rr_accum);
/* 实际累计时间窗 */
if (snapshot.span_ms == 0U) {
/* 首帧或刚恢复时无法可靠计算,返回 0 让调用方使用保底值 */
*dt_ms = 0U;
} else {
*dt_ms = snapshot.span_ms;
}
return count;
}

183
App/Can/snc_can_app.h Normal file
View File

@@ -0,0 +1,183 @@
#ifndef __SNC_CAN_APP_H
#define __SNC_CAN_APP_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include "fdcan.h"
#define SNC_ODOM_TIMEOUT_MS 300U
/* ========================= 协议 CAN ID ========================= */
#define SNC_CAN_ID_HEARTBEAT 0x080U
#define SNC_CAN_ID_CMD_VEL 0x100U
#define SNC_CAN_ID_STATUS 0x181U
#define SNC_CAN_ID_ACTUAL_RPM 0x182U
#define SNC_CAN_ID_TARGET_RPM 0x183U
#define SNC_CAN_ID_COMM_DIAG 0x184U
#define SNC_CAN_ID_ODOM 0x200U
/* ========================= 系统状态定义 ========================= */
typedef enum
{
SNC_SYSTEM_BOOTING = 0,
SNC_SYSTEM_OPERATIONAL = 1,
SNC_SYSTEM_SAFE_FAULT = 2
} SNC_SystemState_t;
typedef enum
{
SNC_SYSTEM_HEALTH_OK = 0,
SNC_SYSTEM_HEALTH_WARNING = 1,
SNC_SYSTEM_HEALTH_FAULT = 2
} SNC_SystemHealth_t;
/* ========================= 诊断位定义 ========================= */
typedef enum
{
SNC_DIAG_COMM_TIMEOUT = (1UL << 0),
SNC_DIAG_CAN_BUS_OFF = (1UL << 1),
SNC_DIAG_CMD_CRC_STORM = (1UL << 2),
SNC_DIAG_CMD_CNT_STORM = (1UL << 3),
SNC_DIAG_MOTOR_FL_STALL = (1UL << 4),
SNC_DIAG_MOTOR_RL_STALL = (1UL << 5),
SNC_DIAG_MOTOR_FR_STALL = (1UL << 6),
SNC_DIAG_MOTOR_RR_STALL = (1UL << 7),
SNC_DIAG_CONTROL_SATURATION = (1UL << 8)
} SNC_DiagBits_t;
/* ========================= 下位机状态快照 ========================= */
typedef struct
{
uint8_t state;
uint8_t health;
uint32_t diag_bits;
uint8_t cmd_age_10ms;
uint8_t status_counter;
uint32_t last_update_ms;
bool online;
} SNC_ChassisStatus_t;
/* ========================= 轮速数据 ========================= */
typedef struct
{
int16_t fl;
int16_t rl;
int16_t fr;
int16_t rr;
uint32_t last_update_ms;
} SNC_WheelRpmFrame_t;
/* ========================= 里程增量 ========================= */
typedef struct
{
int16_t fl_delta;
int16_t rl_delta;
int16_t fr_delta;
int16_t rr_delta;
uint32_t last_update_ms;
} SNC_OdomDeltaFrame_t;
/**
* @brief 里程增量累加器
*
* 解决 0x200 增量帧的"漏积分/重复积分"问题:
* - ISR 收到每帧 0x200 时,将增量**累加**到此结构体(不覆盖)
* - 消费者调用 SNC_CAN_ConsumeOdomDelta() 原子取走累计值并清零
*
* 这样即使消费者频率 (100ms) 低于帧到达频率 (~60ms)
* 也不会丢失任何增量;也不会重复消费同一份增量。
*/
typedef struct
{
int32_t fl_accum; /**< 左前轮累计增量 ticks (int32 防溢出) */
int32_t rl_accum; /**< 左后轮累计增量 ticks */
int32_t fr_accum; /**< 右前轮累计增量 ticks */
int32_t rr_accum; /**< 右后轮累计增量 ticks */
uint32_t first_frame_ms; /**< 本次累加窗口内第一帧的时间戳 [ms] */
uint32_t last_frame_ms; /**< 本次累加窗口内最后一帧的时间戳 [ms] */
uint32_t span_ms; /**< 本次累计增量实际覆盖的时间窗 [ms] */
uint8_t frame_count; /**< 本次累加窗口内收到的帧数 */
} SNC_OdomDeltaAccum_t;
/* ========================= 通信诊断 ========================= */
typedef struct
{
uint8_t valid_cmd_total_lsb;
uint8_t crc_error_total_lsb;
uint8_t counter_reject_total_lsb;
uint8_t can_tx_drop_total_lsb;
uint8_t busoff_total_lsb;
uint8_t rx_overrun_total_lsb;
uint8_t last_accepted_counter;
uint8_t consecutive_counter_errors;
uint8_t consecutive_crc_errors;
uint32_t last_update_ms;
} SNC_CommDiagFrame_t;
/* ========================= 上位机应用层总状态 ========================= */
typedef struct
{
SNC_ChassisStatus_t status;
SNC_WheelRpmFrame_t actual_rpm;
SNC_WheelRpmFrame_t target_rpm;
SNC_OdomDeltaFrame_t odom_delta; /**< 最近一帧快照 (保留兼容性, 勿用于积分) */
SNC_OdomDeltaAccum_t odom_accum; /**< 里程增量累加器 (正确消费入口) */
SNC_CommDiagFrame_t comm_diag;
uint8_t tx_counter;
uint8_t tx_ctrl_flags;
uint32_t tx_total;
uint32_t tx_fail_total;
uint32_t rx_total;
} SNC_CAN_AppContext_t;
/* ========================= 全局上下文 ========================= */
extern SNC_CAN_AppContext_t g_snc_can_app;
/* ========================= 初始化与任务 ========================= */
void SNC_CAN_AppInit(void);
void SNC_CAN_20msTask(void);
void SNC_CAN_100msTask(void);
void SNC_CAN_PollOnlineState(uint32_t now_ms);
/* ========================= 发送接口 ========================= */
HAL_StatusTypeDef SNC_CAN_SendHeartbeat(void);
HAL_StatusTypeDef SNC_CAN_SendCmdVel(float vx_mps, float wz_radps, uint8_t ctrl_flags);
/* ========================= 接收回调 ========================= */
void SNC_CAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t rxFifo0ITs);
/* ========================= 数据读取接口 ========================= */
const SNC_CAN_AppContext_t *SNC_CAN_GetContext(void);
/**
* @brief 原子取走并清零里程增量累加器
*
* 消费者monitorTask每周期调用一次取走自上次消费以来
* ISR 累积的全部增量帧总和。返回后累加器归零,等待下一批帧。
*
* @param[out] fl 左前轮累计增量 ticks (截断为 int16)
* @param[out] rl 左后轮累计增量 ticks
* @param[out] fr 右前轮累计增量 ticks
* @param[out] rr 右后轮累计增量 ticks
* @param[out] dt_ms 累加增量实际覆盖的时间窗 [ms]
* 若无法可靠计算(如系统首帧)则为 0可用默认帧间隔替代
* @return 本次取走的帧数0 表示期间没有新帧到达
*/
uint8_t SNC_CAN_ConsumeOdomDelta(int16_t *fl, int16_t *rl,
int16_t *fr, int16_t *rr,
uint32_t *dt_ms);
/* ========================= 工具接口 ========================= */
uint8_t SNC_CAN_Crc8J1850(const uint8_t *data, uint16_t len);
#ifdef __cplusplus
}
#endif
#endif /* __SNC_CAN_APP_H */

View File

@@ -0,0 +1,68 @@
#ifndef CHASSIS_CAN_MSG_H
#define CHASSIS_CAN_MSG_H
#include <stdint.h>
/* 强制 1 字节对齐,完美匹配物理总线上的 8 字节数据帧 */
#pragma pack(push, 1)
/* =========================================================
* TX: 上位机 (H743) -> 底盘 (F407)
* ========================================================= */
/**
* @brief 0x100 速度控制帧 (建议 20ms 发送周期) [cite: 608-612, 624]
*/
typedef struct {
int16_t vx_x1000; // Byte 0-1: 线速度 m/s * 1000 (小端) [cite: 612]
int16_t wz_x1000; // Byte 2-3: 角速度 rad/s * 1000 (小端) [cite: 612]
uint8_t ctrl_flags; // Byte 4: 控制标志位 [cite: 612]
uint8_t reserved; // Byte 5: 预留,固定填 0 [cite: 612]
uint8_t rolling_counter; // Byte 6: 滚动计数器 (新counter相对上一帧差值必须在1..3之间) [cite: 612, 622]
uint8_t crc8; // Byte 7: 对 Byte0~6 做的 CRC8-SAE J1850 [cite: 612]
} CanMsg_CmdVel_0x100_t;
/* =========================================================
* RX: 底盘 (F407) -> 上位机 (H743)
* ========================================================= */
/**
* @brief 0x181 底盘状态帧 (20ms 发送周期) [cite: 633-637]
*/
typedef struct {
uint8_t system_state; // Byte 0: 0=BOOTING, 1=OPERATIONAL, 2=SAFE_FAULT [cite: 636, 665]
uint8_t system_health; // Byte 1: 0=OK, 1=WARNING, 2=FAULT [cite: 636, 667]
uint32_t diag_bits; // Byte 2-5: 诊断位图 (小端) [cite: 637, 669]
uint8_t cmd_age_10ms; // Byte 6: 距最近一次合法 0x100 过去多少个 10ms [cite: 637]
uint8_t status_counter; // Byte 7: 状态帧发送计数器 [cite: 637]
} CanMsg_Status_0x181_t;
/**
* @brief 0x200 里程增量帧 (约 60ms 轮询周期) [cite: 655-658]
* @note 这是时间窗内的脉冲增量,上位机需自行累加积分以推算里程 [cite: 660-662]
*/
typedef struct {
int16_t fl_delta_ticks; // Byte 0-1: 左前轮增量 [cite: 658]
int16_t rl_delta_ticks; // Byte 2-3: 左后轮增量 [cite: 658]
int16_t fr_delta_ticks; // Byte 4-5: 右前轮增量 [cite: 658]
int16_t rr_delta_ticks; // Byte 6-7: 右后轮增量 [cite: 658]
} CanMsg_OdomDelta_0x200_t;
/**
* @brief 0x184 通信诊断帧 (100ms 发送周期) [cite: 651-653]
*/
typedef struct {
uint8_t valid_cmd_total; // Byte 0: 合法命令累计 [cite: 653]
uint8_t crc_error_total; // Byte 1: CRC 错误累计 [cite: 653]
uint8_t counter_reject_total; // Byte 2: Counter 拒收累计 [cite: 653]
uint8_t can_tx_drop_total; // Byte 3: CAN 发送丢帧累计 [cite: 653]
uint8_t busoff_total; // Byte 4: Bus-Off 累计 [cite: 653]
uint8_t rx_overrun_total; // Byte 5: FIFO overrun 累计 [cite: 653]
uint8_t last_accepted_counter; // Byte 6: 最近一次接受的 counter [cite: 653]
uint8_t err_nibbles; // Byte 7: 高4位=连续counter错低4位=连续CRC错 [cite: 653]
} CanMsg_CommDiag_0x184_t;
#pragma pack(pop)
#endif // CHASSIS_CAN_MSG_H

View File

@@ -0,0 +1,111 @@
#include "robot_blackboard.h"
#include "FreeRTOS.h"
#include "task.h"
#include <string.h>
/* 全局唯一的黑板实例 */
static RobotBlackboard_t g_blackboard = {0};
/* =========================================================
* 生产者 API 实现
* ========================================================= */
void Blackboard_UpdateIMU(const HWT101_Data_t *imu_data) {
if (imu_data == NULL) return;
taskENTER_CRITICAL();
// 更新原始航向角 ([-180, +180) 度)
g_blackboard.imu_yaw.value = imu_data->yaw;
g_blackboard.imu_yaw.timestamp_ms = imu_data->last_update;
g_blackboard.imu_yaw.is_valid = (imu_data->online != 0);
// 更新 unwrap 后的连续航向角 (无跳变, 度)
g_blackboard.imu_yaw_continuous.value = imu_data->yaw_continuous;
g_blackboard.imu_yaw_continuous.timestamp_ms = imu_data->last_update;
g_blackboard.imu_yaw_continuous.is_valid = (imu_data->online != 0);
// 更新角速度 (deg/s)
g_blackboard.imu_wz.value = imu_data->wz;
g_blackboard.imu_wz.timestamp_ms = imu_data->last_update;
g_blackboard.imu_wz.is_valid = (imu_data->online != 0);
taskEXIT_CRITICAL();
}
void Blackboard_UpdateVl53(const Vl53BoardSnapshot_t *vl_data) {
if (vl_data == NULL) return;
taskENTER_CRITICAL();
// 约定: [0]左前, [1]左后, [2]右前, [3]右后
g_blackboard.dist_left_f.value = vl_data->range_mm_filtered[0];
g_blackboard.dist_left_f.is_valid = (vl_data->valid_mask & (1 << 0)) != 0;
g_blackboard.dist_left_f.timestamp_ms = vl_data->tick_ms;
g_blackboard.dist_left_r.value = vl_data->range_mm_filtered[1];
g_blackboard.dist_left_r.is_valid = (vl_data->valid_mask & (1 << 1)) != 0;
g_blackboard.dist_left_r.timestamp_ms = vl_data->tick_ms;
g_blackboard.dist_right_f.value = vl_data->range_mm_filtered[2];
g_blackboard.dist_right_f.is_valid = (vl_data->valid_mask & (1 << 2)) != 0;
g_blackboard.dist_right_f.timestamp_ms = vl_data->tick_ms;
g_blackboard.dist_right_r.value = vl_data->range_mm_filtered[3];
g_blackboard.dist_right_r.is_valid = (vl_data->valid_mask & (1 << 3)) != 0;
g_blackboard.dist_right_r.timestamp_ms = vl_data->tick_ms;
taskEXIT_CRITICAL();
}
void Blackboard_UpdateLaser(const laser_simple_snapshot_t *ls_data) {
if (ls_data == NULL) return;
taskENTER_CRITICAL();
// 1. 前方 STP
g_blackboard.dist_front_stp.value = ls_data->ch[LASER_CH_FRONT_STP].distance_mm;
g_blackboard.dist_front_stp.is_valid = ls_data->ch[LASER_CH_FRONT_STP].valid;
g_blackboard.dist_front_stp.timestamp_ms = ls_data->ch[LASER_CH_FRONT_STP].update_tick_ms;
// 2. 前方 ATK
g_blackboard.dist_front_atk.value = ls_data->ch[LASER_CH_FRONT_ATK].distance_mm;
g_blackboard.dist_front_atk.is_valid = ls_data->ch[LASER_CH_FRONT_ATK].valid;
g_blackboard.dist_front_atk.timestamp_ms = ls_data->ch[LASER_CH_FRONT_ATK].update_tick_ms;
// 3. 后方 STP
g_blackboard.dist_rear_stp.value = ls_data->ch[LASER_CH_REAR_STP].distance_mm;
g_blackboard.dist_rear_stp.is_valid = ls_data->ch[LASER_CH_REAR_STP].valid;
g_blackboard.dist_rear_stp.timestamp_ms = ls_data->ch[LASER_CH_REAR_STP].update_tick_ms;
// 4. 后方 ATK
g_blackboard.dist_rear_atk.value = ls_data->ch[LASER_CH_REAR_ATK].distance_mm;
g_blackboard.dist_rear_atk.is_valid = ls_data->ch[LASER_CH_REAR_ATK].valid;
g_blackboard.dist_rear_atk.timestamp_ms = ls_data->ch[LASER_CH_REAR_ATK].update_tick_ms;
taskEXIT_CRITICAL();
}
void Blackboard_UpdateOdom(float vx, float wz) {
taskENTER_CRITICAL();
g_blackboard.odom_vx = vx;
g_blackboard.odom_wz = wz;
taskEXIT_CRITICAL();
}
void Blackboard_UpdateChassisState(uint8_t state, uint32_t diag, bool online) {
taskENTER_CRITICAL();
g_blackboard.chassis_state = state;
g_blackboard.chassis_diag = diag;
g_blackboard.chassis_online = online;
taskEXIT_CRITICAL();
}
/* =========================================================
* 消费者 API 实现
* ========================================================= */
void Blackboard_GetSnapshot(RobotBlackboard_t *out_snapshot) {
if (out_snapshot == NULL) return;
// 关中断拷贝整个结构体,保证上层算法拿到的数据处于同一个时间切片
taskENTER_CRITICAL();
*out_snapshot = g_blackboard;
taskEXIT_CRITICAL();
}

View File

@@ -0,0 +1,74 @@
#ifndef ROBOT_BLACKBOARD_H
#define ROBOT_BLACKBOARD_H
#include <stdint.h>
#include <stdbool.h>
#include "IMU/hwt101.h" // 引用 IMU 接口
#include "laser/laser_manager.h" // 引用前后雷达接口
#include "vl53_board.h" // 引用侧向雷达接口
/**
* @brief 标准原子数据,自带时间戳,专治“传感器偷偷掉线”
*/
typedef struct {
float value; // 数据本体 (距离、角度、速度等)
uint32_t timestamp_ms; // 数据更新时的系统时间 (HAL_GetTick)
bool is_valid; // 驱动层判定的有效性 (如是否超量程、是否报警)
} SensorItem_t;
/**
* @brief 机器人全局情报中心 (System Context)
* @note 对齐抽象后的数据,算法层不需要再关心这是 1 号雷达还是 2 号雷达
*/
typedef struct {
/* --- 1. 空间姿态 (整合自 HWT101) --- */
SensorItem_t imu_yaw; // 原始航向角 (deg),范围 [-180, +180),跨界时跳变
SensorItem_t imu_yaw_continuous; // unwrap 后的连续航向角 (deg),无跳变,可直接做差计算转角
SensorItem_t imu_wz; // Z轴角速度 (deg/s上层使用前需转 rad/s)
/* --- 2. 侧向走廊观测 (整合自 Vl53Board) --- */
SensorItem_t dist_left_f; // 左前侧向距离 (mm)
SensorItem_t dist_left_r; // 左后侧向距离 (mm)
SensorItem_t dist_right_f; // 右前侧向距离 (mm)
SensorItem_t dist_right_r; // 右后侧向距离 (mm)
/* --- 3. 前后到端/防撞观测 (整合自 Laser Manager) --- */
SensorItem_t dist_front_stp; // 前方 STP 激光测距 (mm)
SensorItem_t dist_front_atk; // 前方 ATK 激光测距 (mm)
SensorItem_t dist_rear_stp; // 后方 STP 激光测距 (mm)
SensorItem_t dist_rear_atk; // 后方 ATK 激光测距 (mm)
/* --- 4. 底盘反馈 (整合自 CAN 0x181 & 0x200) --- */
float odom_vx; // 基于 ticks 积分推算的当前线速度 (m/s)
float odom_wz; // 基于 ticks 积分推算的当前角速度 (rad/s)
uint32_t chassis_diag; // 底盘硬诊断位图 [cite: 669]
uint8_t chassis_state; // 0=BOOTING, 1=OPERATIONAL, 2=SAFE_FAULT [cite: 665]
bool chassis_online; // 底盘 CAN 通讯是否正常
} RobotBlackboard_t;
/* =========================================================
* 生产者 API (各种中断/驱动采集任务调用)
* ========================================================= */
void Blackboard_UpdateIMU(const HWT101_Data_t *imu_data);
void Blackboard_UpdateVl53(const Vl53BoardSnapshot_t *vl_data);
void Blackboard_UpdateLaser(const laser_simple_snapshot_t *ls_data);
// 由你的里程计解算函数调用 (传入算好的实时速度)
void Blackboard_UpdateOdom(float vx, float wz);
// 由 CAN 0x181 接收回调调用
void Blackboard_UpdateChassisState(uint8_t state, uint32_t diag, bool online);
/* =========================================================
* 消费者 API (算法/控制任务调用)
* ========================================================= */
/**
* @brief 拍一张极速快照,获取全部对齐的传感器数据
* @note 内部自带临界区保护,绝对防撕裂
*/
void Blackboard_GetSnapshot(RobotBlackboard_t *out_snapshot);
#endif // ROBOT_BLACKBOARD_H

View File

@@ -0,0 +1,44 @@
#include "robot_cmd_slot.h"
#include "FreeRTOS.h"
#include "task.h"
#include "main.h" // 提供 HAL_GetTick()
/* 全局唯一的指令槽实例 */
static RobotTargetCmd_t g_cmd_slot = {0};
void CmdSlot_Push(float vx, float wz, uint8_t flags)
{
// 1. 获取当前系统时间作为时间戳
uint32_t now_ms = HAL_GetTick();
// 2. 进入临界区,关中断,防止写入一半时被高优先级任务或中断打断(防数据撕裂)
taskENTER_CRITICAL();
g_cmd_slot.target_vx = vx;
g_cmd_slot.target_wz = wz;
g_cmd_slot.ctrl_flags = flags;
g_cmd_slot.gen_tick_ms = now_ms;
taskEXIT_CRITICAL();
}
bool CmdSlot_Pop(RobotTargetCmd_t *out_cmd, uint32_t timeout_ms)
{
if (out_cmd == NULL) {
return false;
}
// 1. 进入临界区,安全地拷贝走整个结构体
taskENTER_CRITICAL();
*out_cmd = g_cmd_slot;
taskEXIT_CRITICAL();
// 2. 计算指令老化时间 (利用无符号整型减法自然处理溢出回绕)
uint32_t now_ms = HAL_GetTick();
uint32_t age_ms = now_ms - out_cmd->gen_tick_ms;
// 3. 判定是否超时
if (age_ms > timeout_ms) {
return false; // 🚨 指令太老了,算法层可能死机了!
}
return true; // ✅ 指令新鲜,可以发送
}

View File

@@ -0,0 +1,37 @@
#ifndef ROBOT_CMD_SLOT_H
#define ROBOT_CMD_SLOT_H
#include <stdint.h>
#include <stdbool.h>
/**
* @brief 算法层生成的抽象目标指令
*/
typedef struct {
float target_vx; // 目标线速度 (m/s)
float target_wz; // 目标角速度 (rad/s)
uint8_t ctrl_flags; // 控制模式/标志
uint32_t gen_tick_ms; // 指令生成时的系统时间 (用于底层判断算法是否卡死)
} RobotTargetCmd_t;
/* =========================================================
* API 接口
* ========================================================= */
/**
* @brief 写入接口:由主导航/控制任务调用
* @param vx 期望线速度 (m/s)
* @param wz 期望角速度 (rad/s)
* @param flags 扩展控制标志
*/
void CmdSlot_Push(float vx, float wz, uint8_t flags);
/**
* @brief 读取接口:由 20ms 的 CAN Tx 任务专属调用
* @param out_cmd 获取到的指令拷贝
* @param timeout_ms 容忍算法不更新的最大时间 (推荐 100ms)
* @return true: 指令新鲜可用; false: 算法超时太久,建议强制发 0 停车保护
*/
bool CmdSlot_Pop(RobotTargetCmd_t *out_cmd, uint32_t timeout_ms);
#endif // ROBOT_CMD_SLOT_H

287
App/Contract/robot_odom.c Normal file
View File

@@ -0,0 +1,287 @@
/**
* @file robot_odom.c
* @brief 里程计积分实现:消费 CAN 0x200 轮增量帧,
* 经差分驱动运动学转换为机体速度并推送黑板。
*
* 调用链monitorTask 100ms 周期):
* CAN Rx ISR ──> snc_parse_odom_delta() [snc_can_app.c]
* │ (每帧累加到 odom_accum不覆盖)
* v
* monitorTask ──> SNC_CAN_ConsumeOdomDelta() [snc_can_app.c]
* │ (原子取走累计增量并清零)
* v
* Odom_Update() [robot_odom.c]
* │ (仅在有新帧时调用,杜绝重复积分)
* v
* Blackboard_UpdateOdom(vx, wz) [robot_blackboard.c]
* │
* v
* navTask ──> Blackboard_GetSnapshot() ──> CorridorFilter_Update()
*
* 运动学公式:
* v_left = (fl_delta + rl_delta) / 2 * TICKS_TO_M / dt
* v_right = (fr_delta + rr_delta) / 2 * TICKS_TO_M / dt
* vx = (v_left + v_right) / 2 [m/s]
* wz = (v_right - v_left) / track [rad/s]
*
* 里程累加(用于沿程 s 估计):
* s += |vx| * dt [m]
*/
#include "robot_odom.h"
#include "robot_blackboard.h"
#include "FreeRTOS.h"
#include "task.h"
#include <math.h>
/* =========================================================
* 内部静态状态
* ========================================================= */
/** @brief 里程计运行时数据(全部由临界区保护) */
static struct {
float vx; /**< 机体线速度 [m/s] */
float wz; /**< 机体角速度 [rad/s] */
float distance; /**< 累计行驶距离 [m](从 init 复位后积分) */
bool online; /**< 里程计有效标志 */
uint32_t last_update_ms; /**< 上次有效更新时的系统时间 [ms] */
uint16_t zero_cnt; /**< 连续收到零增量的帧数 */
bool initialized; /**< 是否已完成初始化 */
} s_odom = {
.vx = 0.0f,
.wz = 0.0f,
.distance = 0.0f,
.online = false,
.last_update_ms = 0U,
.zero_cnt = 0U,
.initialized = false,
};
/* =========================================================
* 内部辅助函数
* ========================================================= */
/**
* @brief 内部临界区读写接口(使用 taskENTER/EXIT_CRITICAL
*/
static inline void lock_odom(void)
{
taskENTER_CRITICAL();
}
static inline void unlock_odom(void)
{
taskEXIT_CRITICAL();
}
/**
* @brief 差分驱动运动学核心
*
* @param fl 左前轮增量 ticks
* @param rl 左后轮增量 ticks
* @param fr 右前轮增量 ticks
* @param rr 右后轮增量 ticks
* @param dt 采样周期 [s]
* @param out_vx 输出线速度 [m/s]
* @param out_wz 输出角速度 [rad/s]
*
* @note 内部使用均值滤波:同侧前后轮求平均后再做差速,
* 这样可以抑制单轮打滑对整体估计的影响。
*/
static void differential_kinematics(int16_t fl, int16_t rl,
int16_t fr, int16_t rr,
float dt,
float *out_vx, float *out_wz)
{
/* 1. 同侧均值滤波(抵消前后轮差分) */
float v_left_ticks = 0.5f * ((float)fl + (float)rl); /* [ticks/period] */
float v_right_ticks = 0.5f * ((float)fr + (float)rr); /* [ticks/period] */
/* 2. tick -> m/s */
float v_left = v_left_ticks * ODOM_TICKS_TO_M / dt; /* [m/s] */
float v_right = v_right_ticks * ODOM_TICKS_TO_M / dt; /* [m/s] */
/* 3. 差分驱动运动学逆解 */
/* vx = (vL + vR) / 2 */
/* wz = (vR - vL) / track */
*out_vx = 0.5f * (v_left + v_right);
*out_wz = (v_right - v_left) * ODOM_WHEEL_TRACK_INV;
/* 4. 合理性检查:物理约束限幅
* H743 主频 480MHzdt 最小约 1ms
* 若单帧 tick 绝对值超过 65535/dt说明增量帧发生异常合并/撕裂。 */
const float MAX_VX_PERIOD = 5.0f; /* 允许的最大瞬时线速度 [m/s](车辆标称最高 1m/s */
const float MAX_WZ_PERIOD = 20.0f; /* 允许的最大瞬时角速度 [rad/s](极端原地转向) */
if (fabsf(*out_vx) > MAX_VX_PERIOD) {
*out_vx = (*out_vx > 0.0f) ? MAX_VX_PERIOD : -MAX_VX_PERIOD;
}
if (fabsf(*out_wz) > MAX_WZ_PERIOD) {
*out_wz = (*out_wz > 0.0f) ? MAX_WZ_PERIOD : -MAX_WZ_PERIOD;
}
}
/* =========================================================
* 公共 API 实现
* ========================================================= */
void Odom_Init(void)
{
lock_odom();
s_odom.vx = 0.0f;
s_odom.wz = 0.0f;
s_odom.distance = 0.0f;
s_odom.online = false;
s_odom.last_update_ms = 0U;
s_odom.zero_cnt = 0U;
s_odom.initialized = true;
unlock_odom();
}
void Odom_Update(uint32_t now_ms,
int16_t fl_delta, int16_t rl_delta,
int16_t fr_delta, int16_t rr_delta,
uint32_t odom_span_ms)
{
if (!s_odom.initialized) {
Odom_Init();
}
/* 计算采样周期 dt
*
* 优先使用 odom_span_msCAN 0x200 帧的真实时间跨度),
* 这是编码器增量实际覆盖的时间窗,不受 monitorTask 调度抖动影响。
*
* 退化策略:
* - odom_span_ms > 0 → 直接使用(最精确)
* - odom_span_ms == 0 → 仅收到一帧,无法算帧间 dt
* 退化为 now_ms - last_update_ms兼容旧行为
* - 首帧last_update_ms == 0 且 odom_span_ms == 0→ 默认 60ms
* 0x200 帧典型间隔)
*/
float dt;
if (odom_span_ms > 0U && odom_span_ms <= 1000U) {
/* 有真实帧时间跨度,优先使用 */
dt = (float)odom_span_ms / 1000.0f;
} else if (s_odom.last_update_ms == 0U || !s_odom.online) {
/*
* 系统首帧,或 odom 刚从断流中恢复但当前只有一帧时,
* 无法可靠反推出这份增量覆盖的真实时间窗,退化为典型帧间隔。
*/
dt = 0.06f;
} else {
uint32_t dt_ms = now_ms - s_odom.last_update_ms;
if (dt_ms == 0U || dt_ms > 1000U) {
/* 超时(超过 1 秒没有新数据)视为里程计离线 */
dt = 0.0f;
} else {
dt = (float)dt_ms / 1000.0f;
}
}
/* 检测零增量:四轮全 0 可能是底盘未动或通信丢失 */
bool is_zero_delta = (fl_delta == 0 && rl_delta == 0 &&
fr_delta == 0 && rr_delta == 0);
if (dt <= 0.0f) {
/* 非法 dt强制离线 */
lock_odom();
s_odom.online = false;
unlock_odom();
return;
}
/* 计算差分运动学 */
float vx_local, wz_local;
differential_kinematics(fl_delta, rl_delta, fr_delta, rr_delta,
dt, &vx_local, &wz_local);
/* 零速度保护:连续多帧零增量后,强制归零(防止漂移) */
lock_odom();
if (is_zero_delta) {
s_odom.zero_cnt++;
if (s_odom.zero_cnt >= 3U) {
/* 连续 3 帧零增量(~180ms @ 60ms 帧率),认为机器人静止 */
s_odom.vx = 0.0f;
s_odom.wz = 0.0f;
s_odom.online = true;
}
} else {
s_odom.zero_cnt = 0U;
s_odom.vx = vx_local;
s_odom.wz = wz_local;
s_odom.online = true;
/* 积分累积里程(取线速度的绝对值,保证后退也累加) */
s_odom.distance += fabsf(s_odom.vx) * dt;
}
s_odom.last_update_ms = now_ms;
unlock_odom();
/* 推送黑板(黑板内部自带临界区保护) */
Blackboard_UpdateOdom(s_odom.vx, s_odom.wz);
}
void Odom_HandleTimeout(uint32_t now_ms, uint32_t timeout_ms)
{
bool timed_out = false;
if (!s_odom.initialized || timeout_ms == 0U) {
return;
}
lock_odom();
if (s_odom.online &&
s_odom.last_update_ms != 0U &&
(now_ms - s_odom.last_update_ms) > timeout_ms) {
s_odom.vx = 0.0f;
s_odom.wz = 0.0f;
s_odom.online = false;
s_odom.zero_cnt = 0U;
timed_out = true;
}
unlock_odom();
if (timed_out) {
Blackboard_UpdateOdom(0.0f, 0.0f);
}
}
void Odom_GetSpeed(float *out_vx, float *out_wz, OdomStatus_t *out_status)
{
if (out_vx != NULL) *out_vx = s_odom.vx;
if (out_wz != NULL) *out_wz = s_odom.wz;
if (out_status != NULL) {
lock_odom();
out_status->online = s_odom.online;
out_status->zero_delta_count = s_odom.zero_cnt;
out_status->last_update_ms = s_odom.last_update_ms;
unlock_odom();
}
}
float Odom_GetDistance(void)
{
float d;
lock_odom();
d = s_odom.distance;
unlock_odom();
return d;
}
void Odom_Reset(void)
{
lock_odom();
s_odom.vx = 0.0f;
s_odom.wz = 0.0f;
s_odom.distance = 0.0f;
s_odom.online = false;
s_odom.last_update_ms = 0U;
s_odom.zero_cnt = 0U;
unlock_odom();
Blackboard_UpdateOdom(0.0f, 0.0f);
}

115
App/Contract/robot_odom.h Normal file
View File

@@ -0,0 +1,115 @@
/**
* @file robot_odom.h
* @brief 里程计积分模块:从 CAN 0x200 轮增量帧累加积分,
* 经差分驱动运动学转换为机体线速度 vx 与角速度 wz
* 最终通过 Blackboard_UpdateOdom() 推送给导航流水线。
*
* @note 本模块不依赖任何传感器,只消费 CAN 协议层已有的 odom_delta 数据。
* 所有标定参数统一在 robot_params.h 中管理。
*
* 运动学模型(差分驱动):
* v_left = (fl_delta + rl_delta) / 2
* v_right = (fr_delta + rr_delta) / 2
* vx = (v_left + v_right) / 2 [m/s]
* wz = (v_right - v_left) / wheel_track [rad/s]
*/
#ifndef ROBOT_ODOM_H
#define ROBOT_ODOM_H
#include <stdint.h>
#include <stdbool.h>
#include "robot_params.h" /* 统一参数头文件 */
/* =========================================================
* 标定参数(从 robot_params.h 引入,勿在此文件重复定义)
* ========================================================= */
#define ODOM_TICKS_PER_REV PARAM_ENCODER_CPR
#define ODOM_WHEEL_DIAMETER PARAM_WHEEL_DIAMETER
#define ODOM_WHEEL_TRACK PARAM_WHEEL_TRACK
/* =========================================================
* 预计算常数(自动生成,勿手动修改)
* ========================================================= */
#define ODOM_TICKS_TO_M (3.14159265358979f * (ODOM_WHEEL_DIAMETER) / (ODOM_TICKS_PER_REV))
/**< @brief 每 tick 对应的轮缘弧长 [m],即 PI*D / CPR */
#define ODOM_WHEEL_TRACK_INV (1.0f / (ODOM_WHEEL_TRACK))
/**< @brief 轮距倒数 [1/m],用于快速计算角速度 */
/* =========================================================
* 配置结构
* ========================================================= */
typedef struct {
/** @brief 里程计有效标志false 时 vx/wz 强制为 0 */
bool online;
/** @brief 里程计在线但 Tick 增量为 0 的连续帧数(用于检测卡死) */
uint16_t zero_delta_count;
/** @brief 上次更新时的系统时间 [ms] */
uint32_t last_update_ms;
} OdomStatus_t;
/* =========================================================
* API 接口
* ========================================================= */
/**
* @brief 里程计模块初始化
* @note 重置内部累加器,建议在系统启动阶段调用一次
*/
void Odom_Init(void);
/**
* @brief 里程计更新主函数
* @param now_ms 当前系统时间 [ms],由 HAL_GetTick() 提供
* @param fl_delta 左前轮增量 ticks本周期内编码器增量可为负
* @param rl_delta 左后轮增量 ticks
* @param fr_delta 右前轮增量 ticks
* @param rr_delta 右后轮增量 ticks
* @param odom_span_ms 本批次增量帧的真实时间跨度 [ms],由
* SNC_CAN_ConsumeOdomDelta() 返回。
* 传 0 表示无法计算(如仅一帧),此时退化为
* now_ms - last_update_ms。
*
* @note 由调用方(本例中 monitorTask 或 navTask定期轮询 CAN 上下文
* 中的 odom_delta 数据后主动调用,推荐调用周期 20~100ms。
* 函数内部完成:均值滤波 -> 差分运动学 -> Blackboard 更新。
*/
void Odom_Update(uint32_t now_ms,
int16_t fl_delta, int16_t rl_delta,
int16_t fr_delta, int16_t rr_delta,
uint32_t odom_span_ms);
/**
* @brief odom 断流超时处理
* @param now_ms 当前系统时间 [ms]
* @param timeout_ms 允许的最大无更新时长 [ms]
*
* @note 超时后会将 vx/wz 清零、标记离线,并同步刷新黑板,
* 防止导航层继续使用最后一次有效速度。
*/
void Odom_HandleTimeout(uint32_t now_ms, uint32_t timeout_ms);
/**
* @brief 读取当前里程计状态快照(供外部任务消费)
* @param out_status 输出状态结构体
* @param out_vx 输出线速度 [m/s]
* @param out_wz 输出角速度 [rad/s]
*
* @note 内部使用临界区保护,调用方可在任何上下文安全使用。
*/
void Odom_GetSpeed(float *out_vx, float *out_wz, OdomStatus_t *out_status);
/**
* @brief 获取累积里程(沿程 s
* @return 累计行驶距离 [m](从 Odom_Init 复位后开始积分)
*
* @note 由走廊状态机用于段落终止判断。也可用于比赛计时参考。
*/
float Odom_GetDistance(void);
/**
* @brief 复位里程计(清零累积距离和状态)
*/
void Odom_Reset(void);
#endif /* ROBOT_ODOM_H */

183
App/IMU/hwt101.c Normal file
View File

@@ -0,0 +1,183 @@
#include "hwt101.h"
#include <stdbool.h>
#include "cmsis_os2.h"
#include "FreeRTOS.h"
#include "stm32h7xx_hal_uart.h"
#include "task.h"
/* 寄存器地址 */
#define REG_SAVE 0x00
#define REG_RRATE 0x03
#define REG_BAUD 0x04
#define REG_KEY 0x69
#define REG_CALIYAW 0x76
/* D2 域特区分配 */
__attribute__((section(".dma_buffer"))) __attribute__((aligned(32)))
static uint8_t s_dma_buf[HWT101_DMA_BUF_SIZE];
/* 内部静态变量 */
static UART_HandleTypeDef *s_huart = NULL;
static HWT101_Data_t s_data = {0};
static uint16_t s_read_ptr = 0;
static uint8_t s_frame[11];
static uint8_t s_frame_idx = 0;
/* yaw unwrap 状态:将 [-180, +180) 的原始 yaw 转为连续角度 */
static float s_yaw_prev = 0.0f; // 上一次原始 yaw (deg)
static float s_yaw_continuous = 0.0f; // 累计连续角度 (deg)
static bool s_yaw_initialized = false; // 首次标记
void HWT101_Init(UART_HandleTypeDef *huart) {
if (huart == NULL) return;
s_huart = huart;
s_read_ptr = 0;
// 【终极修复 1】强制使用 32 位指针,将这块 (NOLOAD) 内存全部写 0。
// 必须是 32 位写入!这会彻底激活 RAM_D2 的硬件 ECC消灭上电时的随机乱码防止 DMA 单字节写入引发总线错误。
uint32_t *p32 = (uint32_t *)s_dma_buf;
for (uint32_t i = 0; i < (HWT101_DMA_BUF_SIZE / 4); i++) {
p32[i] = 0;
}
// ⚠️ 【终极修复 2】因为 .dma_buffer 所在的 0x30000000 已被 MPU 配置为 Device/Non-Cacheable 内存,
// 绝对不能调用 SCB_InvalidateDCache_by_Addr否则 Cortex-M7 会判定越权操作直接进入 HardFault 死机!
// (已删除原有的 SCB_InvalidateDCache_by_Addr 代码)
HAL_UART_Receive_DMA(s_huart, s_dma_buf, HWT101_DMA_BUF_SIZE);
}
void HWT101_Process(void) {
if (s_huart == NULL) return;
// 获取当前 DMA 写指针
uint16_t write_ptr = HWT101_DMA_BUF_SIZE - (uint16_t)__HAL_DMA_GET_COUNTER(s_huart->hdmarx);
// ⚠️ 【终极修复 3】删除原有的刷 Cache 代码。
// 依靠硬件 MPU 免 Cache 机制CPU 读到的必定是 DMA 搬运过来的最新数据,不会有数据一致性问题。
while (s_read_ptr != write_ptr) {
uint8_t byte = s_dma_buf[s_read_ptr];
s_read_ptr = (s_read_ptr + 1) % HWT101_DMA_BUF_SIZE;
// 状态机加速:如果不是帧头,直接跳过,不用进入后续逻辑
if (s_frame_idx == 0 && byte != 0x55) continue;
s_frame[s_frame_idx++] = byte;
if (s_frame_idx >= 11) {
uint8_t sum = 0;
for (int i = 0; i < 10; i++) sum += s_frame[i];
if (sum == s_frame[10]) {
// 更新全局变量时使用临界区保护,防止数据撕裂
taskENTER_CRITICAL();
if (s_frame[1] == 0x52) {
int16_t wz_raw = (int16_t)((s_frame[7] << 8) | s_frame[6]);
s_data.wz = (float)wz_raw / 32768.0f * 2000.0f;
} else if (s_frame[1] == 0x53) {
int16_t yaw_raw = (int16_t)((s_frame[7] << 8) | s_frame[6]);
float yaw_deg = (float)yaw_raw / 32768.0f * 180.0f;
/* 保存原始 yaw ([-180, +180) 度) */
s_data.yaw = yaw_deg;
/* ---- yaw unwrap: 消除 ±180° 跳变,生成连续角度 ---- */
if (!s_yaw_initialized) {
s_yaw_continuous = yaw_deg;
s_yaw_prev = yaw_deg;
s_yaw_initialized = true;
} else {
float diff = yaw_deg - s_yaw_prev;
if (diff > 180.0f) diff -= 360.0f;
if (diff < -180.0f) diff += 360.0f;
s_yaw_continuous += diff;
s_yaw_prev = yaw_deg;
}
s_data.yaw_continuous = s_yaw_continuous;
s_data.last_update = HAL_GetTick();
s_data.online = 1;
}
taskEXIT_CRITICAL();
}
s_frame_idx = 0;
}
}
// 超时检测
if (HAL_GetTick() - s_data.last_update > 200) {
s_data.online = 0;
}
}
// 安全的数据获取接口
void HWT101_GetData(HWT101_Data_t *out_data) {
if (out_data == NULL) return;
// 关中断拷贝,绝对防止浮点数撕裂
taskENTER_CRITICAL();
*out_data = s_data;
taskEXIT_CRITICAL();
}
/* ==========================================
* 传感器配置函数 (与原版保持一致)
* ========================================== */
static HAL_StatusTypeDef HWT101_Unlock(void) {
uint8_t cmd[5] = {0xFF, 0xAA, REG_KEY, 0x88, 0xB5};
return HAL_UART_Transmit(s_huart, cmd, 5, 20);
}
static HAL_StatusTypeDef HWT101_Save(void) {
uint8_t cmd[5] = {0xFF, 0xAA, REG_SAVE, 0x00, 0x00};
HAL_StatusTypeDef res = HAL_UART_Transmit(s_huart, cmd, 5, 20);
osDelay(200);
return res;
}
static HAL_StatusTypeDef HWT101_WriteReg(uint8_t reg, int16_t value) {
if (HWT101_Unlock() != HAL_OK) return HAL_ERROR;
osDelay(20);
uint8_t cmd[5] = {0xFF, 0xAA, reg, (uint8_t)(value & 0xFF), (uint8_t)(value >> 8)};
return HAL_UART_Transmit(s_huart, cmd, 5, 20);
}
HAL_StatusTypeDef HWT101_Config(HWT101_Rate_t rate, HWT101_Baud_t baud) {
if (HWT101_WriteReg(REG_RRATE, (int16_t)rate) != HAL_OK) return HAL_ERROR;
osDelay(100);
if (HWT101_WriteReg(REG_BAUD, (int16_t)baud) != HAL_OK) return HAL_ERROR;
osDelay(100);
return HWT101_Save();
}
HAL_StatusTypeDef HWT101_ZeroYaw(void) {
if (HWT101_WriteReg(REG_CALIYAW, 0x0000) != HAL_OK) return HAL_ERROR;
osDelay(500);
/* 重置 unwrap 状态,下次收到帧时重新初始化连续角度 */
taskENTER_CRITICAL();
s_yaw_initialized = false;
s_yaw_continuous = 0.0f;
s_yaw_prev = 0.0f;
s_data.yaw_continuous = 0.0f;
taskEXIT_CRITICAL();
return HWT101_Save();
}
void HWT101_ErrorRecovery(UART_HandleTypeDef *huart) {
if (s_huart != NULL && huart == s_huart) {
HAL_UART_DMAStop(s_huart);
// 暴力清除 ORE/NE/FE/PE 错误标志,防止无限死循环中断风暴
__HAL_UART_CLEAR_FLAG(s_huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF);
// 读取一次 RDR 寄存器,把里面卡住的垃圾字节倒掉
volatile uint32_t dump = s_huart->Instance->RDR;
(void)dump;
// 干净地重新启动 DMA
HAL_UART_Receive_DMA(s_huart, s_dma_buf, HWT101_DMA_BUF_SIZE);
s_read_ptr = 0;
s_frame_idx = 0;
}
}

41
App/IMU/hwt101.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef HWT101_H
#define HWT101_H
#include <stdint.h>
#include "main.h"
#define HWT101_DMA_BUF_SIZE 256 // 必须是 32 的整数倍
typedef enum {
HWT101_RATE_10HZ = 0x06,
HWT101_RATE_50HZ = 0x08,
HWT101_RATE_100HZ = 0x09, // 推荐100Hz
HWT101_RATE_200HZ = 0x0B
} HWT101_Rate_t;
typedef enum {
HWT101_BAUD_9600 = 0x02,
HWT101_BAUD_115200 = 0x06,
HWT101_BAUD_230400 = 0x07
} HWT101_Baud_t;
typedef struct {
float yaw; // 原始偏航角 (deg),范围 [-180, +180),跨界时跳变
float yaw_continuous; // unwrap 后的连续偏航角 (deg),无跳变,可直接做差计算转角
float wz; // Z 轴角速度 (deg/s)
uint32_t last_update;
uint8_t online;
} HWT101_Data_t;
/* API 函数声明 */
void HWT101_Init(UART_HandleTypeDef *huart);
void HWT101_Process(void);
// 【升级 2】改为传入指针安全拷贝数据防止数据撕裂
void HWT101_GetData(HWT101_Data_t *out_data);
// 在末尾 API 声明处加上这句
void HWT101_ErrorRecovery(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HWT101_Config(HWT101_Rate_t rate, HWT101_Baud_t baud);
HAL_StatusTypeDef HWT101_ZeroYaw(void);
#endif /* HWT101_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,85 @@
/*******************************************************************************
* Copyright © 2016, STMicroelectronics International N.V.
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 STMicroelectronics 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, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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 _VL53L0X_API_CALIBRATION_H_
#define _VL53L0X_API_CALIBRATION_H_
#include "vl53l0x_def.h"
#include "vl53l0x_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
VL53L0X_Error VL53L0X_perform_xtalk_calibration(VL53L0X_DEV Dev,
FixPoint1616_t XTalkCalDistance,
FixPoint1616_t *pXTalkCompensationRateMegaCps);
VL53L0X_Error VL53L0X_perform_offset_calibration(VL53L0X_DEV Dev,
FixPoint1616_t CalDistanceMilliMeter,
int32_t *pOffsetMicroMeter);
VL53L0X_Error VL53L0X_set_offset_calibration_data_micro_meter(VL53L0X_DEV Dev,
int32_t OffsetCalibrationDataMicroMeter);
VL53L0X_Error VL53L0X_get_offset_calibration_data_micro_meter(VL53L0X_DEV Dev,
int32_t *pOffsetCalibrationDataMicroMeter);
VL53L0X_Error VL53L0X_apply_offset_adjustment(VL53L0X_DEV Dev);
VL53L0X_Error VL53L0X_perform_ref_spad_management(VL53L0X_DEV Dev,
uint32_t *refSpadCount, uint8_t *isApertureSpads);
VL53L0X_Error VL53L0X_set_reference_spads(VL53L0X_DEV Dev,
uint32_t count, uint8_t isApertureSpads);
VL53L0X_Error VL53L0X_get_reference_spads(VL53L0X_DEV Dev,
uint32_t *pSpadCount, uint8_t *pIsApertureSpads);
VL53L0X_Error VL53L0X_perform_phase_calibration(VL53L0X_DEV Dev,
uint8_t *pPhaseCal, const uint8_t get_data_enable,
const uint8_t restore_config);
VL53L0X_Error VL53L0X_perform_ref_calibration(VL53L0X_DEV Dev,
uint8_t *pVhvSettings, uint8_t *pPhaseCal, uint8_t get_data_enable);
VL53L0X_Error VL53L0X_set_ref_calibration(VL53L0X_DEV Dev,
uint8_t VhvSettings, uint8_t PhaseCal);
VL53L0X_Error VL53L0X_get_ref_calibration(VL53L0X_DEV Dev,
uint8_t *pVhvSettings, uint8_t *pPhaseCal);
#ifdef __cplusplus
}
#endif
#endif /* _VL53L0X_API_CALIBRATION_H_ */

View File

@@ -0,0 +1,113 @@
/*******************************************************************************
* Copyright © 2016, STMicroelectronics International N.V.
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 STMicroelectronics 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, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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 _VL53L0X_API_CORE_H_
#define _VL53L0X_API_CORE_H_
#include "vl53l0x_def.h"
#include "vl53l0x_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
VL53L0X_Error VL53L0X_reverse_bytes(uint8_t *data, uint32_t size);
VL53L0X_Error VL53L0X_measurement_poll_for_completion(VL53L0X_DEV Dev);
uint8_t VL53L0X_encode_vcsel_period(uint8_t vcsel_period_pclks);
uint8_t VL53L0X_decode_vcsel_period(uint8_t vcsel_period_reg);
uint32_t VL53L0X_isqrt(uint32_t num);
uint32_t VL53L0X_quadrature_sum(uint32_t a, uint32_t b);
VL53L0X_Error VL53L0X_get_info_from_device(VL53L0X_DEV Dev, uint8_t option);
VL53L0X_Error VL53L0X_set_vcsel_pulse_period(VL53L0X_DEV Dev,
VL53L0X_VcselPeriod VcselPeriodType, uint8_t VCSELPulsePeriodPCLK);
VL53L0X_Error VL53L0X_get_vcsel_pulse_period(VL53L0X_DEV Dev,
VL53L0X_VcselPeriod VcselPeriodType, uint8_t *pVCSELPulsePeriodPCLK);
uint32_t VL53L0X_decode_timeout(uint16_t encoded_timeout);
VL53L0X_Error get_sequence_step_timeout(VL53L0X_DEV Dev,
VL53L0X_SequenceStepId SequenceStepId,
uint32_t *pTimeOutMicroSecs);
VL53L0X_Error set_sequence_step_timeout(VL53L0X_DEV Dev,
VL53L0X_SequenceStepId SequenceStepId,
uint32_t TimeOutMicroSecs);
VL53L0X_Error VL53L0X_set_measurement_timing_budget_micro_seconds(
VL53L0X_DEV Dev,
uint32_t MeasurementTimingBudgetMicroSeconds);
VL53L0X_Error VL53L0X_get_measurement_timing_budget_micro_seconds(
VL53L0X_DEV Dev,
uint32_t *pMeasurementTimingBudgetMicroSeconds);
VL53L0X_Error VL53L0X_load_tuning_settings(VL53L0X_DEV Dev,
uint8_t *pTuningSettingBuffer);
VL53L0X_Error VL53L0X_calc_sigma_estimate(VL53L0X_DEV Dev,
VL53L0X_RangingMeasurementData_t *pRangingMeasurementData,
FixPoint1616_t *pSigmaEstimate);
VL53L0X_Error VL53L0X_calc_dmax(
VL53L0X_DEV Dev, FixPoint1616_t ambRateMeas, uint32_t *pdmax_mm);
VL53L0X_Error VL53L0X_get_total_xtalk_rate(VL53L0X_DEV Dev,
VL53L0X_RangingMeasurementData_t *pRangingMeasurementData,
FixPoint1616_t *ptotal_xtalk_rate_mcps);
VL53L0X_Error VL53L0X_get_total_signal_rate(VL53L0X_DEV Dev,
VL53L0X_RangingMeasurementData_t *pRangingMeasurementData,
FixPoint1616_t *ptotal_signal_rate_mcps);
VL53L0X_Error VL53L0X_get_pal_range_status(VL53L0X_DEV Dev,
uint8_t DeviceRangeStatus,
FixPoint1616_t SignalRate,
uint16_t EffectiveSpadRtnCount,
VL53L0X_RangingMeasurementData_t *pRangingMeasurementData,
uint8_t *pPalRangeStatus);
uint32_t VL53L0X_calc_timeout_mclks(VL53L0X_DEV Dev,
uint32_t timeout_period_us, uint8_t vcsel_period_pclks);
uint16_t VL53L0X_encode_timeout(uint32_t timeout_macro_clks);
#ifdef __cplusplus
}
#endif
#endif /* _VL53L0X_API_CORE_H_ */

View File

@@ -0,0 +1,47 @@
/*******************************************************************************
* Copyright © 2016, STMicroelectronics International N.V.
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 STMicroelectronics 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, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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 _VL53L0X_API_RANGING_H_
#define _VL53L0X_API_RANGING_H_
#include "vl53l0x_def.h"
#include "vl53l0x_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* _VL53L0X_API_RANGING_H_ */

View File

@@ -0,0 +1,278 @@
/*******************************************************************************
* Copyright © 2016, STMicroelectronics International N.V.
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 STMicroelectronics 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, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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 VL53L0X_API_STRINGS_H_
#define VL53L0X_API_STRINGS_H_
#include "vl53l0x_def.h"
#include "vl53l0x_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
VL53L0X_Error VL53L0X_get_device_info(VL53L0X_DEV Dev,
VL53L0X_DeviceInfo_t *pVL53L0X_DeviceInfo);
VL53L0X_Error VL53L0X_get_device_error_string(VL53L0X_DeviceError ErrorCode,
char *pDeviceErrorString);
VL53L0X_Error VL53L0X_get_range_status_string(uint8_t RangeStatus,
char *pRangeStatusString);
VL53L0X_Error VL53L0X_get_pal_error_string(VL53L0X_Error PalErrorCode,
char *pPalErrorString);
VL53L0X_Error VL53L0X_get_pal_state_string(VL53L0X_State PalStateCode,
char *pPalStateString);
VL53L0X_Error VL53L0X_get_sequence_steps_info(
VL53L0X_SequenceStepId SequenceStepId,
char *pSequenceStepsString);
VL53L0X_Error VL53L0X_get_limit_check_info(VL53L0X_DEV Dev,
uint16_t LimitCheckId,
char *pLimitCheckString);
#ifdef USE_EMPTY_STRING
#define VL53L0X_STRING_DEVICE_INFO_NAME ""
#define VL53L0X_STRING_DEVICE_INFO_NAME_TS0 ""
#define VL53L0X_STRING_DEVICE_INFO_NAME_TS1 ""
#define VL53L0X_STRING_DEVICE_INFO_NAME_TS2 ""
#define VL53L0X_STRING_DEVICE_INFO_NAME_ES1 ""
#define VL53L0X_STRING_DEVICE_INFO_TYPE ""
/* PAL ERROR strings */
#define VL53L0X_STRING_ERROR_NONE ""
#define VL53L0X_STRING_ERROR_CALIBRATION_WARNING ""
#define VL53L0X_STRING_ERROR_MIN_CLIPPED ""
#define VL53L0X_STRING_ERROR_UNDEFINED ""
#define VL53L0X_STRING_ERROR_INVALID_PARAMS ""
#define VL53L0X_STRING_ERROR_NOT_SUPPORTED ""
#define VL53L0X_STRING_ERROR_RANGE_ERROR ""
#define VL53L0X_STRING_ERROR_TIME_OUT ""
#define VL53L0X_STRING_ERROR_MODE_NOT_SUPPORTED ""
#define VL53L0X_STRING_ERROR_BUFFER_TOO_SMALL ""
#define VL53L0X_STRING_ERROR_GPIO_NOT_EXISTING ""
#define VL53L0X_STRING_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED ""
#define VL53L0X_STRING_ERROR_CONTROL_INTERFACE ""
#define VL53L0X_STRING_ERROR_INVALID_COMMAND ""
#define VL53L0X_STRING_ERROR_DIVISION_BY_ZERO ""
#define VL53L0X_STRING_ERROR_REF_SPAD_INIT ""
#define VL53L0X_STRING_ERROR_NOT_IMPLEMENTED ""
#define VL53L0X_STRING_UNKNOW_ERROR_CODE ""
/* Range Status */
#define VL53L0X_STRING_RANGESTATUS_NONE ""
#define VL53L0X_STRING_RANGESTATUS_RANGEVALID ""
#define VL53L0X_STRING_RANGESTATUS_SIGMA ""
#define VL53L0X_STRING_RANGESTATUS_SIGNAL ""
#define VL53L0X_STRING_RANGESTATUS_MINRANGE ""
#define VL53L0X_STRING_RANGESTATUS_PHASE ""
#define VL53L0X_STRING_RANGESTATUS_HW ""
/* Range Status */
#define VL53L0X_STRING_STATE_POWERDOWN ""
#define VL53L0X_STRING_STATE_WAIT_STATICINIT ""
#define VL53L0X_STRING_STATE_STANDBY ""
#define VL53L0X_STRING_STATE_IDLE ""
#define VL53L0X_STRING_STATE_RUNNING ""
#define VL53L0X_STRING_STATE_UNKNOWN ""
#define VL53L0X_STRING_STATE_ERROR ""
/* Device Specific */
#define VL53L0X_STRING_DEVICEERROR_NONE ""
#define VL53L0X_STRING_DEVICEERROR_VCSELCONTINUITYTESTFAILURE ""
#define VL53L0X_STRING_DEVICEERROR_VCSELWATCHDOGTESTFAILURE ""
#define VL53L0X_STRING_DEVICEERROR_NOVHVVALUEFOUND ""
#define VL53L0X_STRING_DEVICEERROR_MSRCNOTARGET ""
#define VL53L0X_STRING_DEVICEERROR_SNRCHECK ""
#define VL53L0X_STRING_DEVICEERROR_RANGEPHASECHECK ""
#define VL53L0X_STRING_DEVICEERROR_SIGMATHRESHOLDCHECK ""
#define VL53L0X_STRING_DEVICEERROR_TCC ""
#define VL53L0X_STRING_DEVICEERROR_PHASECONSISTENCY ""
#define VL53L0X_STRING_DEVICEERROR_MINCLIP ""
#define VL53L0X_STRING_DEVICEERROR_RANGECOMPLETE ""
#define VL53L0X_STRING_DEVICEERROR_ALGOUNDERFLOW ""
#define VL53L0X_STRING_DEVICEERROR_ALGOOVERFLOW ""
#define VL53L0X_STRING_DEVICEERROR_RANGEIGNORETHRESHOLD ""
#define VL53L0X_STRING_DEVICEERROR_UNKNOWN ""
/* Check Enable */
#define VL53L0X_STRING_CHECKENABLE_SIGMA_FINAL_RANGE ""
#define VL53L0X_STRING_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE ""
#define VL53L0X_STRING_CHECKENABLE_SIGNAL_REF_CLIP ""
#define VL53L0X_STRING_CHECKENABLE_RANGE_IGNORE_THRESHOLD ""
/* Sequence Step */
#define VL53L0X_STRING_SEQUENCESTEP_TCC ""
#define VL53L0X_STRING_SEQUENCESTEP_DSS ""
#define VL53L0X_STRING_SEQUENCESTEP_MSRC ""
#define VL53L0X_STRING_SEQUENCESTEP_PRE_RANGE ""
#define VL53L0X_STRING_SEQUENCESTEP_FINAL_RANGE ""
#else
#define VL53L0X_STRING_DEVICE_INFO_NAME "VL53L0X cut1.0"
#define VL53L0X_STRING_DEVICE_INFO_NAME_TS0 "VL53L0X TS0"
#define VL53L0X_STRING_DEVICE_INFO_NAME_TS1 "VL53L0X TS1"
#define VL53L0X_STRING_DEVICE_INFO_NAME_TS2 "VL53L0X TS2"
#define VL53L0X_STRING_DEVICE_INFO_NAME_ES1 "VL53L0X ES1 or later"
#define VL53L0X_STRING_DEVICE_INFO_TYPE "VL53L0X"
/* PAL ERROR strings */
#define VL53L0X_STRING_ERROR_NONE \
"No Error"
#define VL53L0X_STRING_ERROR_CALIBRATION_WARNING \
"Calibration Warning Error"
#define VL53L0X_STRING_ERROR_MIN_CLIPPED \
"Min clipped error"
#define VL53L0X_STRING_ERROR_UNDEFINED \
"Undefined error"
#define VL53L0X_STRING_ERROR_INVALID_PARAMS \
"Invalid parameters error"
#define VL53L0X_STRING_ERROR_NOT_SUPPORTED \
"Not supported error"
#define VL53L0X_STRING_ERROR_RANGE_ERROR \
"Range error"
#define VL53L0X_STRING_ERROR_TIME_OUT \
"Time out error"
#define VL53L0X_STRING_ERROR_MODE_NOT_SUPPORTED \
"Mode not supported error"
#define VL53L0X_STRING_ERROR_BUFFER_TOO_SMALL \
"Buffer too small"
#define VL53L0X_STRING_ERROR_GPIO_NOT_EXISTING \
"GPIO not existing"
#define VL53L0X_STRING_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED \
"GPIO funct not supported"
#define VL53L0X_STRING_ERROR_INTERRUPT_NOT_CLEARED \
"Interrupt not Cleared"
#define VL53L0X_STRING_ERROR_CONTROL_INTERFACE \
"Control Interface Error"
#define VL53L0X_STRING_ERROR_INVALID_COMMAND \
"Invalid Command Error"
#define VL53L0X_STRING_ERROR_DIVISION_BY_ZERO \
"Division by zero Error"
#define VL53L0X_STRING_ERROR_REF_SPAD_INIT \
"Reference Spad Init Error"
#define VL53L0X_STRING_ERROR_NOT_IMPLEMENTED \
"Not implemented error"
#define VL53L0X_STRING_UNKNOW_ERROR_CODE \
"Unknown Error Code"
/* Range Status */
#define VL53L0X_STRING_RANGESTATUS_NONE "No Update"
#define VL53L0X_STRING_RANGESTATUS_RANGEVALID "Range Valid"
#define VL53L0X_STRING_RANGESTATUS_SIGMA "Sigma Fail"
#define VL53L0X_STRING_RANGESTATUS_SIGNAL "Signal Fail"
#define VL53L0X_STRING_RANGESTATUS_MINRANGE "Min Range Fail"
#define VL53L0X_STRING_RANGESTATUS_PHASE "Phase Fail"
#define VL53L0X_STRING_RANGESTATUS_HW "Hardware Fail"
/* Range Status */
#define VL53L0X_STRING_STATE_POWERDOWN "POWERDOWN State"
#define VL53L0X_STRING_STATE_WAIT_STATICINIT \
"Wait for staticinit State"
#define VL53L0X_STRING_STATE_STANDBY "STANDBY State"
#define VL53L0X_STRING_STATE_IDLE "IDLE State"
#define VL53L0X_STRING_STATE_RUNNING "RUNNING State"
#define VL53L0X_STRING_STATE_UNKNOWN "UNKNOWN State"
#define VL53L0X_STRING_STATE_ERROR "ERROR State"
/* Device Specific */
#define VL53L0X_STRING_DEVICEERROR_NONE "No Update"
#define VL53L0X_STRING_DEVICEERROR_VCSELCONTINUITYTESTFAILURE \
"VCSEL Continuity Test Failure"
#define VL53L0X_STRING_DEVICEERROR_VCSELWATCHDOGTESTFAILURE \
"VCSEL Watchdog Test Failure"
#define VL53L0X_STRING_DEVICEERROR_NOVHVVALUEFOUND \
"No VHV Value found"
#define VL53L0X_STRING_DEVICEERROR_MSRCNOTARGET \
"MSRC No Target Error"
#define VL53L0X_STRING_DEVICEERROR_SNRCHECK \
"SNR Check Exit"
#define VL53L0X_STRING_DEVICEERROR_RANGEPHASECHECK \
"Range Phase Check Error"
#define VL53L0X_STRING_DEVICEERROR_SIGMATHRESHOLDCHECK \
"Sigma Threshold Check Error"
#define VL53L0X_STRING_DEVICEERROR_TCC \
"TCC Error"
#define VL53L0X_STRING_DEVICEERROR_PHASECONSISTENCY \
"Phase Consistency Error"
#define VL53L0X_STRING_DEVICEERROR_MINCLIP \
"Min Clip Error"
#define VL53L0X_STRING_DEVICEERROR_RANGECOMPLETE \
"Range Complete"
#define VL53L0X_STRING_DEVICEERROR_ALGOUNDERFLOW \
"Range Algo Underflow Error"
#define VL53L0X_STRING_DEVICEERROR_ALGOOVERFLOW \
"Range Algo Overlow Error"
#define VL53L0X_STRING_DEVICEERROR_RANGEIGNORETHRESHOLD \
"Range Ignore Threshold Error"
#define VL53L0X_STRING_DEVICEERROR_UNKNOWN \
"Unknown error code"
/* Check Enable */
#define VL53L0X_STRING_CHECKENABLE_SIGMA_FINAL_RANGE \
"SIGMA FINAL RANGE"
#define VL53L0X_STRING_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE \
"SIGNAL RATE FINAL RANGE"
#define VL53L0X_STRING_CHECKENABLE_SIGNAL_REF_CLIP \
"SIGNAL REF CLIP"
#define VL53L0X_STRING_CHECKENABLE_RANGE_IGNORE_THRESHOLD \
"RANGE IGNORE THRESHOLD"
#define VL53L0X_STRING_CHECKENABLE_SIGNAL_RATE_MSRC \
"SIGNAL RATE MSRC"
#define VL53L0X_STRING_CHECKENABLE_SIGNAL_RATE_PRE_RANGE \
"SIGNAL RATE PRE RANGE"
/* Sequence Step */
#define VL53L0X_STRING_SEQUENCESTEP_TCC "TCC"
#define VL53L0X_STRING_SEQUENCESTEP_DSS "DSS"
#define VL53L0X_STRING_SEQUENCESTEP_MSRC "MSRC"
#define VL53L0X_STRING_SEQUENCESTEP_PRE_RANGE "PRE RANGE"
#define VL53L0X_STRING_SEQUENCESTEP_FINAL_RANGE "FINAL RANGE"
#endif /* USE_EMPTY_STRING */
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,666 @@
/*******************************************************************************
* Copyright <20> 2016, STMicroelectronics International N.V.
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 STMicroelectronics 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, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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.
*******************************************************************************/
/**
* @file VL53L0X_def.h
*
* @brief Type definitions for VL53L0X API.
*
*/
#ifndef _VL53L0X_DEF_H_
#define _VL53L0X_DEF_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @defgroup VL53L0X_globaldefine_group VL53L0X Defines
* @brief VL53L0X Defines
* @{
*/
/** PAL SPECIFICATION major version */
#define VL53L0X10_SPECIFICATION_VER_MAJOR 1
/** PAL SPECIFICATION minor version */
#define VL53L0X10_SPECIFICATION_VER_MINOR 2
/** PAL SPECIFICATION sub version */
#define VL53L0X10_SPECIFICATION_VER_SUB 7
/** PAL SPECIFICATION sub version */
#define VL53L0X10_SPECIFICATION_VER_REVISION 1440
/** VL53L0X PAL IMPLEMENTATION major version */
#define VL53L0X10_IMPLEMENTATION_VER_MAJOR 1
/** VL53L0X PAL IMPLEMENTATION minor version */
#define VL53L0X10_IMPLEMENTATION_VER_MINOR 0
/** VL53L0X PAL IMPLEMENTATION sub version */
#define VL53L0X10_IMPLEMENTATION_VER_SUB 9
/** VL53L0X PAL IMPLEMENTATION sub version */
#define VL53L0X10_IMPLEMENTATION_VER_REVISION 3673
/** PAL SPECIFICATION major version */
#define VL53L0X_SPECIFICATION_VER_MAJOR 1
/** PAL SPECIFICATION minor version */
#define VL53L0X_SPECIFICATION_VER_MINOR 2
/** PAL SPECIFICATION sub version */
#define VL53L0X_SPECIFICATION_VER_SUB 7
/** PAL SPECIFICATION sub version */
#define VL53L0X_SPECIFICATION_VER_REVISION 1440
/** VL53L0X PAL IMPLEMENTATION major version */
#define VL53L0X_IMPLEMENTATION_VER_MAJOR 1
/** VL53L0X PAL IMPLEMENTATION minor version */
#define VL53L0X_IMPLEMENTATION_VER_MINOR 0
/** VL53L0X PAL IMPLEMENTATION sub version */
#define VL53L0X_IMPLEMENTATION_VER_SUB 4
/** VL53L0X PAL IMPLEMENTATION sub version */
#define VL53L0X_IMPLEMENTATION_VER_REVISION 4960
#define VL53L0X_DEFAULT_MAX_LOOP 2000
#define VL53L0X_MAX_STRING_LENGTH 32
#include "vl53l0x_device.h"
#include "vl53l0x_types.h"
/****************************************
* PRIVATE define do not edit
****************************************/
/** @brief Defines the parameters of the Get Version Functions
*/
typedef struct {
uint32_t revision; /*!< revision number */
uint8_t major; /*!< major number */
uint8_t minor; /*!< minor number */
uint8_t build; /*!< build number */
} VL53L0X_Version_t;
/** @brief Defines the parameters of the Get Device Info Functions
*/
typedef struct {
char Name[VL53L0X_MAX_STRING_LENGTH];
/*!< Name of the Device e.g. Left_Distance */
char Type[VL53L0X_MAX_STRING_LENGTH];
/*!< Type of the Device e.g VL53L0X */
char ProductId[VL53L0X_MAX_STRING_LENGTH];
/*!< Product Identifier String */
uint8_t ProductType;
/*!< Product Type, VL53L0X = 1, VL53L1 = 2 */
uint8_t ProductRevisionMajor;
/*!< Product revision major */
uint8_t ProductRevisionMinor;
/*!< Product revision minor */
} VL53L0X_DeviceInfo_t;
/** @defgroup VL53L0X_define_Error_group Error and Warning code returned by API
* The following DEFINE are used to identify the PAL ERROR
* @{
*/
typedef int8_t VL53L0X_Error;
#define VL53L0X_ERROR_NONE ((VL53L0X_Error) 0)
#define VL53L0X_ERROR_CALIBRATION_WARNING ((VL53L0X_Error) - 1)
/*!< Warning invalid calibration data may be in used
* \a VL53L0X_InitData()
* \a VL53L0X_GetOffsetCalibrationData
* \a VL53L0X_SetOffsetCalibrationData
*/
#define VL53L0X_ERROR_MIN_CLIPPED ((VL53L0X_Error) - 2)
/*!< Warning parameter passed was clipped to min before to be applied */
#define VL53L0X_ERROR_UNDEFINED ((VL53L0X_Error) - 3)
/*!< Unqualified error */
#define VL53L0X_ERROR_INVALID_PARAMS ((VL53L0X_Error) - 4)
/*!< Parameter passed is invalid or out of range */
#define VL53L0X_ERROR_NOT_SUPPORTED ((VL53L0X_Error) - 5)
/*!< Function is not supported in current mode or configuration */
#define VL53L0X_ERROR_RANGE_ERROR ((VL53L0X_Error) - 6)
/*!< Device report a ranging error interrupt status */
#define VL53L0X_ERROR_TIME_OUT ((VL53L0X_Error) - 7)
/*!< Aborted due to time out */
#define VL53L0X_ERROR_MODE_NOT_SUPPORTED ((VL53L0X_Error) - 8)
/*!< Asked mode is not supported by the device */
#define VL53L0X_ERROR_BUFFER_TOO_SMALL ((VL53L0X_Error) - 9)
/*!< ... */
#define VL53L0X_ERROR_GPIO_NOT_EXISTING ((VL53L0X_Error) - 10)
/*!< User tried to setup a non-existing GPIO pin */
#define VL53L0X_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED ((VL53L0X_Error) - 11)
/*!< unsupported GPIO functionality */
#define VL53L0X_ERROR_INTERRUPT_NOT_CLEARED ((VL53L0X_Error) - 12)
/*!< Error during interrupt clear */
#define VL53L0X_ERROR_CONTROL_INTERFACE ((VL53L0X_Error) - 20)
/*!< error reported from IO functions */
#define VL53L0X_ERROR_INVALID_COMMAND ((VL53L0X_Error) - 30)
/*!< The command is not allowed in the current device state
* (power down)
*/
#define VL53L0X_ERROR_DIVISION_BY_ZERO ((VL53L0X_Error) - 40)
/*!< In the function a division by zero occurs */
#define VL53L0X_ERROR_REF_SPAD_INIT ((VL53L0X_Error) - 50)
/*!< Error during reference SPAD initialization */
#define VL53L0X_ERROR_NOT_IMPLEMENTED ((VL53L0X_Error) - 99)
/*!< Tells requested functionality has not been implemented yet or
* not compatible with the device
*/
/** @} VL53L0X_define_Error_group */
/** @defgroup VL53L0X_define_DeviceModes_group Defines Device modes
* Defines all possible modes for the device
* @{
*/
typedef uint8_t VL53L0X_DeviceModes;
#define VL53L0X_DEVICEMODE_SINGLE_RANGING ((VL53L0X_DeviceModes) 0)
#define VL53L0X_DEVICEMODE_CONTINUOUS_RANGING ((VL53L0X_DeviceModes) 1)
#define VL53L0X_DEVICEMODE_SINGLE_HISTOGRAM ((VL53L0X_DeviceModes) 2)
#define VL53L0X_DEVICEMODE_CONTINUOUS_TIMED_RANGING ((VL53L0X_DeviceModes) 3)
#define VL53L0X_DEVICEMODE_SINGLE_ALS ((VL53L0X_DeviceModes) 10)
#define VL53L0X_DEVICEMODE_GPIO_DRIVE ((VL53L0X_DeviceModes) 20)
#define VL53L0X_DEVICEMODE_GPIO_OSC ((VL53L0X_DeviceModes) 21)
/* ... Modes to be added depending on device */
/** @} VL53L0X_define_DeviceModes_group */
/** @defgroup VL53L0X_define_HistogramModes_group Defines Histogram modes
* Defines all possible Histogram modes for the device
* @{
*/
typedef uint8_t VL53L0X_HistogramModes;
#define VL53L0X_HISTOGRAMMODE_DISABLED ((VL53L0X_HistogramModes) 0)
/*!< Histogram Disabled */
#define VL53L0X_HISTOGRAMMODE_REFERENCE_ONLY ((VL53L0X_HistogramModes) 1)
/*!< Histogram Reference array only */
#define VL53L0X_HISTOGRAMMODE_RETURN_ONLY ((VL53L0X_HistogramModes) 2)
/*!< Histogram Return array only */
#define VL53L0X_HISTOGRAMMODE_BOTH ((VL53L0X_HistogramModes) 3)
/*!< Histogram both Reference and Return Arrays */
/* ... Modes to be added depending on device */
/** @} VL53L0X_define_HistogramModes_group */
/** @defgroup VL53L0X_define_PowerModes_group List of available Power Modes
* List of available Power Modes
* @{
*/
typedef uint8_t VL53L0X_PowerModes;
#define VL53L0X_POWERMODE_STANDBY_LEVEL1 ((VL53L0X_PowerModes) 0)
/*!< Standby level 1 */
#define VL53L0X_POWERMODE_STANDBY_LEVEL2 ((VL53L0X_PowerModes) 1)
/*!< Standby level 2 */
#define VL53L0X_POWERMODE_IDLE_LEVEL1 ((VL53L0X_PowerModes) 2)
/*!< Idle level 1 */
#define VL53L0X_POWERMODE_IDLE_LEVEL2 ((VL53L0X_PowerModes) 3)
/*!< Idle level 2 */
/** @} VL53L0X_define_PowerModes_group */
#define VL53L0X_DMAX_LUT_SIZE 7
/*!< Defines the number of items in the DMAX lookup table */
/** @brief Structure defining data pair that makes up the DMAX Lookup table.
*/
typedef struct {
FixPoint1616_t ambRate_mcps[VL53L0X_DMAX_LUT_SIZE];
/*!< Ambient rate (mcps) */
FixPoint1616_t dmax_mm[VL53L0X_DMAX_LUT_SIZE];
/*!< DMAX Value (mm) */
} VL53L0X_DMaxLUT_t;
/** @brief Defines all parameters for the device
*/
typedef struct {
VL53L0X_DeviceModes DeviceMode;
/*!< Defines type of measurement to be done for the next measure */
VL53L0X_HistogramModes HistogramMode;
/*!< Defines type of histogram measurement to be done for the next
* measure
*/
uint32_t MeasurementTimingBudgetMicroSeconds;
/*!< Defines the allowed total time for a single measurement */
uint32_t InterMeasurementPeriodMilliSeconds;
/*!< Defines time between two consecutive measurements (between two
* measurement starts). If set to 0 means back-to-back mode
*/
uint8_t XTalkCompensationEnable;
/*!< Tells if Crosstalk compensation shall be enable or not */
uint16_t XTalkCompensationRangeMilliMeter;
/*!< CrossTalk compensation range in millimeter */
FixPoint1616_t XTalkCompensationRateMegaCps;
/*!< CrossTalk compensation rate in Mega counts per seconds.
* Expressed in 16.16 fixed point format.
*/
int32_t RangeOffsetMicroMeters;
/*!< Range offset adjustment (mm). */
uint8_t LimitChecksEnable[VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS];
/*!< This Array store all the Limit Check enable for this device. */
uint8_t LimitChecksStatus[VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS];
/*!< This Array store all the Status of the check linked to last
* measurement.
*/
FixPoint1616_t LimitChecksValue[VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS];
/*!< This Array store all the Limit Check value for this device */
VL53L0X_DMaxLUT_t dmax_lut;
/*!< Lookup table defining ambient rates and associated
* dmax values.
*/
uint8_t WrapAroundCheckEnable;
/*!< Tells if Wrap Around Check shall be enable or not */
} VL53L0X_DeviceParameters_t;
/** @defgroup VL53L0X_define_State_group Defines the current status
* of the device
* Defines the current status of the device
* @{
*/
typedef uint8_t VL53L0X_State;
#define VL53L0X_STATE_POWERDOWN ((VL53L0X_State) 0)
/*!< Device is in HW reset */
#define VL53L0X_STATE_WAIT_STATICINIT ((VL53L0X_State) 1)
/*!< Device is initialized and wait for static initialization */
#define VL53L0X_STATE_STANDBY ((VL53L0X_State) 2)
/*!< Device is in Low power Standby mode */
#define VL53L0X_STATE_IDLE ((VL53L0X_State) 3)
/*!< Device has been initialized and ready to do measurements */
#define VL53L0X_STATE_RUNNING ((VL53L0X_State) 4)
/*!< Device is performing measurement */
#define VL53L0X_STATE_UNKNOWN ((VL53L0X_State) 98)
/*!< Device is in unknown state and need to be rebooted */
#define VL53L0X_STATE_ERROR ((VL53L0X_State) 99)
/*!< Device is in error state and need to be rebooted */
/** @} VL53L0X_define_State_group */
/**
* @struct VL53L0X_RangeData_t
* @brief Range measurement data.
*/
typedef struct {
uint32_t TimeStamp; /*!< 32-bit time stamp. */
uint32_t MeasurementTimeUsec;
/*!< Give the Measurement time needed by the device to do the
* measurement.
*/
uint16_t RangeMilliMeter; /*!< range distance in millimeter. */
uint16_t RangeDMaxMilliMeter;
/*!< Tells what is the maximum detection distance of the device
* in current setup and environment conditions (Filled when
* applicable)
*/
FixPoint1616_t SignalRateRtnMegaCps;
/*!< Return signal rate (MCPS)\n these is a 16.16 fix point
* value, which is effectively a measure of target
* reflectance.
*/
FixPoint1616_t AmbientRateRtnMegaCps;
/*!< Return ambient rate (MCPS)\n these is a 16.16 fix point
* value, which is effectively a measure of the ambien
* t light.
*/
uint16_t EffectiveSpadRtnCount;
/*!< Return the effective SPAD count for the return signal.
* To obtain Real value it should be divided by 256
*/
uint8_t ZoneId;
/*!< Denotes which zone and range scheduler stage the range
* data relates to.
*/
uint8_t RangeFractionalPart;
/*!< Fractional part of range distance. Final value is a
* FixPoint168 value.
*/
uint8_t RangeStatus;
/*!< Range Status for the current measurement. This is device
* dependent. Value = 0 means value is valid.
* See \ref RangeStatusPage
*/
} VL53L0X_RangingMeasurementData_t;
#define VL53L0X_HISTOGRAM_BUFFER_SIZE 24
/**
* @struct VL53L0X_HistogramData_t
* @brief Histogram measurement data.
*/
typedef struct {
/* Histogram Measurement data */
uint32_t HistogramData[VL53L0X_HISTOGRAM_BUFFER_SIZE];
/*!< Histogram data */
/*!< Indicate the types of histogram data :
*Return only, Reference only, both Return and Reference
*/
uint8_t FirstBin; /*!< First Bin value */
uint8_t BufferSize; /*!< Buffer Size - Set by the user.*/
uint8_t NumberOfBins;
/*!< Number of bins filled by the histogram measurement */
VL53L0X_DeviceError ErrorStatus;
/*!< Error status of the current measurement. \n
* see @a ::VL53L0X_DeviceError @a VL53L0X_GetStatusErrorString()
*/
} VL53L0X_HistogramMeasurementData_t;
#define VL53L0X_REF_SPAD_BUFFER_SIZE 6
/**
* @struct VL53L0X_SpadData_t
* @brief Spad Configuration Data.
*/
typedef struct {
uint8_t RefSpadEnables[VL53L0X_REF_SPAD_BUFFER_SIZE];
/*!< Reference Spad Enables */
uint8_t RefGoodSpadMap[VL53L0X_REF_SPAD_BUFFER_SIZE];
/*!< Reference Spad Good Spad Map */
} VL53L0X_SpadData_t;
typedef struct {
FixPoint1616_t OscFrequencyMHz; /* Frequency used */
uint16_t LastEncodedTimeout;
/* last encoded Time out used for timing budget*/
VL53L0X_GpioFunctionality Pin0GpioFunctionality;
/* store the functionality of the GPIO: pin0 */
uint32_t FinalRangeTimeoutMicroSecs;
/*!< Execution time of the final range*/
uint8_t FinalRangeVcselPulsePeriod;
/*!< Vcsel pulse period (pll clocks) for the final range measurement*/
uint32_t PreRangeTimeoutMicroSecs;
/*!< Execution time of the final range*/
uint8_t PreRangeVcselPulsePeriod;
/*!< Vcsel pulse period (pll clocks) for the pre-range measurement*/
uint16_t SigmaEstRefArray;
/*!< Reference array sigma value in 1/100th of [mm] e.g. 100 = 1mm */
uint16_t SigmaEstEffPulseWidth;
/*!< Effective Pulse width for sigma estimate in 1/100th
* of ns e.g. 900 = 9.0ns
*/
uint16_t SigmaEstEffAmbWidth;
/*!< Effective Ambient width for sigma estimate in 1/100th of ns
* e.g. 500 = 5.0ns
*/
/* Indicate if read from device has been done (==1) or not (==0) */
uint8_t ReadDataFromDeviceDone;
uint8_t ModuleId; /* Module ID */
uint8_t Revision; /* test Revision */
char ProductId[VL53L0X_MAX_STRING_LENGTH];
/* Product Identifier String */
uint8_t ReferenceSpadCount; /* used for ref spad management */
uint8_t ReferenceSpadType; /* used for ref spad management */
uint8_t RefSpadsInitialised; /* reports if ref spads are initialised. */
uint32_t PartUIDUpper; /*!< Unique Part ID Upper */
uint32_t PartUIDLower; /*!< Unique Part ID Lower */
/*!< Peek Signal rate at 400 mm*/
FixPoint1616_t SignalRateMeasFixed400mm;
} VL53L0X_DeviceSpecificParameters_t;
/**
* @struct VL53L0X_DevData_t
*
* @brief VL53L0X PAL device ST private data structure \n
* End user should never access any of these field directly
*
* These must never access directly but only via macro
*/
typedef struct {
int32_t Part2PartOffsetNVMMicroMeter;
/*!< backed up NVM value */
int32_t Part2PartOffsetAdjustmentNVMMicroMeter;
/*!< backed up NVM value representing additional offset adjustment */
VL53L0X_DeviceParameters_t CurrentParameters;
/*!< Current Device Parameter */
VL53L0X_RangingMeasurementData_t LastRangeMeasure;
/*!< Ranging Data */
VL53L0X_HistogramMeasurementData_t LastHistogramMeasure;
/*!< Histogram Data */
VL53L0X_DeviceSpecificParameters_t DeviceSpecificParameters;
/*!< Parameters specific to the device */
VL53L0X_SpadData_t SpadData;
/*!< Spad Data */
uint8_t SequenceConfig;
/*!< Internal value for the sequence config */
uint8_t RangeFractionalEnable;
/*!< Enable/Disable fractional part of ranging data */
VL53L0X_State PalState;
/*!< Current state of the PAL for this device */
VL53L0X_PowerModes PowerMode;
/*!< Current Power Mode */
uint16_t SigmaEstRefArray;
/*!< Reference array sigma value in 1/100th of [mm] e.g. 100 = 1mm */
uint16_t SigmaEstEffPulseWidth;
/*!< Effective Pulse width for sigma estimate in 1/100th
* of ns e.g. 900 = 9.0ns
*/
uint16_t SigmaEstEffAmbWidth;
/*!< Effective Ambient width for sigma estimate in 1/100th of ns
* e.g. 500 = 5.0ns
*/
uint8_t StopVariable;
/*!< StopVariable used during the stop sequence */
uint16_t targetRefRate;
/*!< Target Ambient Rate for Ref spad management */
FixPoint1616_t SigmaEstimate;
/*!< Sigma Estimate - based on ambient & VCSEL rates and
* signal_total_events
*/
FixPoint1616_t SignalEstimate;
/*!< Signal Estimate - based on ambient & VCSEL rates and cross talk */
FixPoint1616_t LastSignalRefMcps;
/*!< Latest Signal ref in Mcps */
uint8_t *pTuningSettingsPointer;
/*!< Pointer for Tuning Settings table */
uint8_t UseInternalTuningSettings;
/*!< Indicate if we use Tuning Settings table */
uint16_t LinearityCorrectiveGain;
/*!< Linearity Corrective Gain value in x1000 */
} VL53L0X_DevData_t;
/** @defgroup VL53L0X_define_InterruptPolarity_group Defines the Polarity
* of the Interrupt
* Defines the Polarity of the Interrupt
* @{
*/
typedef uint8_t VL53L0X_InterruptPolarity;
#define VL53L0X_INTERRUPTPOLARITY_LOW ((VL53L0X_InterruptPolarity) 0)
/*!< Set active low polarity best setup for falling edge. */
#define VL53L0X_INTERRUPTPOLARITY_HIGH ((VL53L0X_InterruptPolarity) 1)
/*!< Set active high polarity best setup for rising edge. */
/** @} VL53L0X_define_InterruptPolarity_group */
/** @defgroup VL53L0X_define_VcselPeriod_group Vcsel Period Defines
* Defines the range measurement for which to access the vcsel period.
* @{
*/
typedef uint8_t VL53L0X_VcselPeriod;
#define VL53L0X_VCSEL_PERIOD_PRE_RANGE ((VL53L0X_VcselPeriod) 0)
/*!<Identifies the pre-range vcsel period. */
#define VL53L0X_VCSEL_PERIOD_FINAL_RANGE ((VL53L0X_VcselPeriod) 1)
/*!<Identifies the final range vcsel period. */
/** @} VL53L0X_define_VcselPeriod_group */
/** @defgroup VL53L0X_define_SchedulerSequence_group Defines the steps
* carried out by the scheduler during a range measurement.
* @{
* Defines the states of all the steps in the scheduler
* i.e. enabled/disabled.
*/
typedef struct {
uint8_t TccOn; /*!<Reports if Target Centre Check On */
uint8_t MsrcOn; /*!<Reports if MSRC On */
uint8_t DssOn; /*!<Reports if DSS On */
uint8_t PreRangeOn; /*!<Reports if Pre-Range On */
uint8_t FinalRangeOn; /*!<Reports if Final-Range On */
} VL53L0X_SchedulerSequenceSteps_t;
/** @} VL53L0X_define_SchedulerSequence_group */
/** @defgroup VL53L0X_define_SequenceStepId_group Defines the Polarity
* of the Interrupt
* Defines the the sequence steps performed during ranging..
* @{
*/
typedef uint8_t VL53L0X_SequenceStepId;
#define VL53L0X_SEQUENCESTEP_TCC ((VL53L0X_VcselPeriod) 0)
/*!<Target CentreCheck identifier. */
#define VL53L0X_SEQUENCESTEP_DSS ((VL53L0X_VcselPeriod) 1)
/*!<Dynamic Spad Selection function Identifier. */
#define VL53L0X_SEQUENCESTEP_MSRC ((VL53L0X_VcselPeriod) 2)
/*!<Minimum Signal Rate Check function Identifier. */
#define VL53L0X_SEQUENCESTEP_PRE_RANGE ((VL53L0X_VcselPeriod) 3)
/*!<Pre-Range check Identifier. */
#define VL53L0X_SEQUENCESTEP_FINAL_RANGE ((VL53L0X_VcselPeriod) 4)
/*!<Final Range Check Identifier. */
#define VL53L0X_SEQUENCESTEP_NUMBER_OF_CHECKS 5
/*!<Number of Sequence Step Managed by the API. */
/** @} VL53L0X_define_SequenceStepId_group */
/* MACRO Definitions */
/** @defgroup VL53L0X_define_GeneralMacro_group General Macro Defines
* General Macro Defines
* @{
*/
/* Defines */
#define VL53L0X_SETPARAMETERFIELD(Dev, field, value) \
PALDevDataSet(Dev, CurrentParameters.field, value)
#define VL53L0X_GETPARAMETERFIELD(Dev, field, variable) \
(variable = ((PALDevDataGet(Dev, CurrentParameters)).field))
#define VL53L0X_SETARRAYPARAMETERFIELD(Dev, field, index, value) \
PALDevDataSet(Dev, CurrentParameters.field[index], value)
#define VL53L0X_GETARRAYPARAMETERFIELD(Dev, field, index, variable) \
(variable = (PALDevDataGet(Dev, CurrentParameters)).field[index])
#define VL53L0X_SETDEVICESPECIFICPARAMETER(Dev, field, value) \
PALDevDataSet(Dev, DeviceSpecificParameters.field, value)
#define VL53L0X_GETDEVICESPECIFICPARAMETER(Dev, field) \
PALDevDataGet(Dev, DeviceSpecificParameters).field
#define VL53L0X_FIXPOINT1616TOFIXPOINT97(Value) \
(uint16_t)((Value>>9)&0xFFFF)
#define VL53L0X_FIXPOINT97TOFIXPOINT1616(Value) \
(FixPoint1616_t)(Value<<9)
#define VL53L0X_FIXPOINT1616TOFIXPOINT88(Value) \
(uint16_t)((Value>>8)&0xFFFF)
#define VL53L0X_FIXPOINT88TOFIXPOINT1616(Value) \
(FixPoint1616_t)(Value<<8)
#define VL53L0X_FIXPOINT1616TOFIXPOINT412(Value) \
(uint16_t)((Value>>4)&0xFFFF)
#define VL53L0X_FIXPOINT412TOFIXPOINT1616(Value) \
(FixPoint1616_t)(Value<<4)
#define VL53L0X_FIXPOINT1616TOFIXPOINT313(Value) \
(uint16_t)((Value>>3)&0xFFFF)
#define VL53L0X_FIXPOINT313TOFIXPOINT1616(Value) \
(FixPoint1616_t)(Value<<3)
#define VL53L0X_FIXPOINT1616TOFIXPOINT08(Value) \
(uint8_t)((Value>>8)&0x00FF)
#define VL53L0X_FIXPOINT08TOFIXPOINT1616(Value) \
(FixPoint1616_t)(Value<<8)
#define VL53L0X_FIXPOINT1616TOFIXPOINT53(Value) \
(uint8_t)((Value>>13)&0x00FF)
#define VL53L0X_FIXPOINT53TOFIXPOINT1616(Value) \
(FixPoint1616_t)(Value<<13)
#define VL53L0X_FIXPOINT1616TOFIXPOINT102(Value) \
(uint16_t)((Value>>14)&0x0FFF)
#define VL53L0X_FIXPOINT102TOFIXPOINT1616(Value) \
(FixPoint1616_t)(Value<<12)
#define VL53L0X_MAKEUINT16(lsb, msb) (uint16_t)((((uint16_t)msb)<<8) + \
(uint16_t)lsb)
/** @} VL53L0X_define_GeneralMacro_group */
/** @} VL53L0X_globaldefine_group */
#ifdef __cplusplus
}
#endif
#define TRACE_MODULE_API 0
#define _LOG_FUNCTION_START(...) (void)0
#define _LOG_FUNCTION_END(...) (void)0
#define _LOG_FUNCTION_END_FMT(...) (void)0
#endif /* _VL53L0X_DEF_H_ */

View File

@@ -0,0 +1,262 @@
/*******************************************************************************
* Copyright © 2016, STMicroelectronics International N.V.
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 STMicroelectronics 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, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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.
*******************************************************************************/
/**
* Device specific defines. To be adapted by implementer for the targeted
* device.
*/
#ifndef _VL53L0X_DEVICE_H_
#define _VL53L0X_DEVICE_H_
#include "vl53l0x_types.h"
/** @defgroup VL53L0X_DevSpecDefines_group VL53L0X cut1.1 Device
* Specific Defines
* @brief VL53L0X cut1.1 Device Specific Defines
* @{
*/
/** @defgroup VL53L0X_DeviceError_group Device Error
* @brief Device Error code
*
* This enum is Device specific it should be updated in the implementation
* Use @a VL53L0X_GetStatusErrorString() to get the string.
* It is related to Status Register of the Device.
* @{
*/
typedef uint8_t VL53L0X_DeviceError;
#define VL53L0X_DEVICEERROR_NONE ((VL53L0X_DeviceError) 0)
/*!< 0 NoError */
#define VL53L0X_DEVICEERROR_VCSELCONTINUITYTESTFAILURE ((VL53L0X_DeviceError) 1)
#define VL53L0X_DEVICEERROR_VCSELWATCHDOGTESTFAILURE ((VL53L0X_DeviceError) 2)
#define VL53L0X_DEVICEERROR_NOVHVVALUEFOUND ((VL53L0X_DeviceError) 3)
#define VL53L0X_DEVICEERROR_MSRCNOTARGET ((VL53L0X_DeviceError) 4)
#define VL53L0X_DEVICEERROR_SNRCHECK ((VL53L0X_DeviceError) 5)
#define VL53L0X_DEVICEERROR_RANGEPHASECHECK ((VL53L0X_DeviceError) 6)
#define VL53L0X_DEVICEERROR_SIGMATHRESHOLDCHECK ((VL53L0X_DeviceError) 7)
#define VL53L0X_DEVICEERROR_TCC ((VL53L0X_DeviceError) 8)
#define VL53L0X_DEVICEERROR_PHASECONSISTENCY ((VL53L0X_DeviceError) 9)
#define VL53L0X_DEVICEERROR_MINCLIP ((VL53L0X_DeviceError) 10)
#define VL53L0X_DEVICEERROR_RANGECOMPLETE ((VL53L0X_DeviceError) 11)
#define VL53L0X_DEVICEERROR_ALGOUNDERFLOW ((VL53L0X_DeviceError) 12)
#define VL53L0X_DEVICEERROR_ALGOOVERFLOW ((VL53L0X_DeviceError) 13)
#define VL53L0X_DEVICEERROR_RANGEIGNORETHRESHOLD ((VL53L0X_DeviceError) 14)
/** @} end of VL53L0X_DeviceError_group */
/** @defgroup VL53L0X_CheckEnable_group Check Enable list
* @brief Check Enable code
*
* Define used to specify the LimitCheckId.
* Use @a VL53L0X_GetLimitCheckInfo() to get the string.
* @{
*/
#define VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE 0
#define VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE 1
#define VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP 2
#define VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD 3
#define VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC 4
#define VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE 5
#define VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS 6
/** @} end of VL53L0X_CheckEnable_group */
/** @defgroup VL53L0X_GpioFunctionality_group Gpio Functionality
* @brief Defines the different functionalities for the device GPIO(s)
* @{
*/
typedef uint8_t VL53L0X_GpioFunctionality;
#define VL53L0X_GPIOFUNCTIONALITY_OFF \
((VL53L0X_GpioFunctionality) 0) /*!< NO Interrupt */
#define VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW \
((VL53L0X_GpioFunctionality) 1) /*!< Level Low (value < thresh_low) */
#define VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_HIGH \
((VL53L0X_GpioFunctionality) 2) /*!< Level High (value>thresh_high) */
#define VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_OUT \
((VL53L0X_GpioFunctionality) 3)
/*!< Out Of Window (value < thresh_low OR value > thresh_high) */
#define VL53L0X_GPIOFUNCTIONALITY_NEW_MEASURE_READY \
((VL53L0X_GpioFunctionality) 4) /*!< New Sample Ready */
/** @} end of VL53L0X_GpioFunctionality_group */
/* Device register map */
/** @defgroup VL53L0X_DefineRegisters_group Define Registers
* @brief List of all the defined registers
* @{
*/
#define VL53L0X_REG_SYSRANGE_START 0x000
/** mask existing bit in #VL53L0X_REG_SYSRANGE_START*/
#define VL53L0X_REG_SYSRANGE_MODE_MASK 0x0F
/** bit 0 in #VL53L0X_REG_SYSRANGE_START write 1 toggle state in
* continuous mode and arm next shot in single shot mode
*/
#define VL53L0X_REG_SYSRANGE_MODE_START_STOP 0x01
/** bit 1 write 0 in #VL53L0X_REG_SYSRANGE_START set single shot mode */
#define VL53L0X_REG_SYSRANGE_MODE_SINGLESHOT 0x00
/** bit 1 write 1 in #VL53L0X_REG_SYSRANGE_START set back-to-back
* operation mode
*/
#define VL53L0X_REG_SYSRANGE_MODE_BACKTOBACK 0x02
/** bit 2 write 1 in #VL53L0X_REG_SYSRANGE_START set timed operation
* mode
*/
#define VL53L0X_REG_SYSRANGE_MODE_TIMED 0x04
/** bit 3 write 1 in #VL53L0X_REG_SYSRANGE_START set histogram operation
* mode
*/
#define VL53L0X_REG_SYSRANGE_MODE_HISTOGRAM 0x08
#define VL53L0X_REG_SYSTEM_THRESH_HIGH 0x000C
#define VL53L0X_REG_SYSTEM_THRESH_LOW 0x000E
#define VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG 0x0001
#define VL53L0X_REG_SYSTEM_RANGE_CONFIG 0x0009
#define VL53L0X_REG_SYSTEM_INTERMEASUREMENT_PERIOD 0x0004
#define VL53L0X_REG_SYSTEM_INTERRUPT_CONFIG_GPIO 0x000A
#define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_DISABLED 0x00
#define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_LEVEL_LOW 0x01
#define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_LEVEL_HIGH 0x02
#define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_OUT_OF_WINDOW 0x03
#define VL53L0X_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY 0x04
#define VL53L0X_REG_GPIO_HV_MUX_ACTIVE_HIGH 0x0084
#define VL53L0X_REG_SYSTEM_INTERRUPT_CLEAR 0x000B
/* Result registers */
#define VL53L0X_REG_RESULT_INTERRUPT_STATUS 0x0013
#define VL53L0X_REG_RESULT_RANGE_STATUS 0x0014
#define VL53L0X_REG_RESULT_CORE_PAGE 1
#define VL53L0X_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN 0x00BC
#define VL53L0X_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_RTN 0x00C0
#define VL53L0X_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_REF 0x00D0
#define VL53L0X_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_REF 0x00D4
#define VL53L0X_REG_RESULT_PEAK_SIGNAL_RATE_REF 0x00B6
/* Algo register */
#define VL53L0X_REG_ALGO_PART_TO_PART_RANGE_OFFSET_MM 0x0028
#define VL53L0X_REG_I2C_SLAVE_DEVICE_ADDRESS 0x008a
/* Check Limit registers */
#define VL53L0X_REG_MSRC_CONFIG_CONTROL 0x0060
#define VL53L0X_REG_PRE_RANGE_CONFIG_MIN_SNR 0X0027
#define VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW 0x0056
#define VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH 0x0057
#define VL53L0X_REG_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT 0x0064
#define VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_SNR 0X0067
#define VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW 0x0047
#define VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH 0x0048
#define VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT 0x0044
#define VL53L0X_REG_PRE_RANGE_CONFIG_SIGMA_THRESH_HI 0X0061
#define VL53L0X_REG_PRE_RANGE_CONFIG_SIGMA_THRESH_LO 0X0062
/* PRE RANGE registers */
#define VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD 0x0050
#define VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI 0x0051
#define VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_LO 0x0052
#define VL53L0X_REG_SYSTEM_HISTOGRAM_BIN 0x0081
#define VL53L0X_REG_HISTOGRAM_CONFIG_INITIAL_PHASE_SELECT 0x0033
#define VL53L0X_REG_HISTOGRAM_CONFIG_READOUT_CTRL 0x0055
#define VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD 0x0070
#define VL53L0X_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI 0x0071
#define VL53L0X_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_LO 0x0072
#define VL53L0X_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS 0x0020
#define VL53L0X_REG_MSRC_CONFIG_TIMEOUT_MACROP 0x0046
#define VL53L0X_REG_SOFT_RESET_GO2_SOFT_RESET_N 0x00bf
#define VL53L0X_REG_IDENTIFICATION_MODEL_ID 0x00c0
#define VL53L0X_REG_IDENTIFICATION_REVISION_ID 0x00c2
#define VL53L0X_REG_OSC_CALIBRATE_VAL 0x00f8
#define VL53L0X_SIGMA_ESTIMATE_MAX_VALUE 65535
/* equivalent to a range sigma of 655.35mm */
#define VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH 0x032
#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_0 0x0B0
#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_1 0x0B1
#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_2 0x0B2
#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_3 0x0B3
#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_4 0x0B4
#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_5 0x0B5
#define VL53L0X_REG_GLOBAL_CONFIG_REF_EN_START_SELECT 0xB6
#define VL53L0X_REG_DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD 0x4E /* 0x14E */
#define VL53L0X_REG_DYNAMIC_SPAD_REF_EN_START_OFFSET 0x4F /* 0x14F */
#define VL53L0X_REG_POWER_MANAGEMENT_GO1_POWER_FORCE 0x80
/*
* Speed of light in um per 1E-10 Seconds
*/
#define VL53L0X_SPEED_OF_LIGHT_IN_AIR 2997
#define VL53L0X_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV 0x0089
#define VL53L0X_REG_ALGO_PHASECAL_LIM 0x0030 /* 0x130 */
#define VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT 0x0030
/** @} VL53L0X_DefineRegisters_group */
/** @} VL53L0X_DevSpecDefines_group */
#endif
/* _VL53L0X_DEVICE_H_ */

View File

@@ -0,0 +1,194 @@
/*******************************************************************************
* Copyright © 2016, STMicroelectronics International N.V.
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 STMicroelectronics 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, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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 _VL53L0X_INTERRUPT_THRESHOLD_SETTINGS_H_
#define _VL53L0X_INTERRUPT_THRESHOLD_SETTINGS_H_
#ifdef __cplusplus
extern "C" {
#endif
uint8_t InterruptThresholdSettings[] = {
/* Start of Interrupt Threshold Settings */
0x1, 0xff, 0x00,
0x1, 0x80, 0x01,
0x1, 0xff, 0x01,
0x1, 0x00, 0x00,
0x1, 0xff, 0x01,
0x1, 0x4f, 0x02,
0x1, 0xFF, 0x0E,
0x1, 0x00, 0x03,
0x1, 0x01, 0x84,
0x1, 0x02, 0x0A,
0x1, 0x03, 0x03,
0x1, 0x04, 0x08,
0x1, 0x05, 0xC8,
0x1, 0x06, 0x03,
0x1, 0x07, 0x8D,
0x1, 0x08, 0x08,
0x1, 0x09, 0xC6,
0x1, 0x0A, 0x01,
0x1, 0x0B, 0x02,
0x1, 0x0C, 0x00,
0x1, 0x0D, 0xD5,
0x1, 0x0E, 0x18,
0x1, 0x0F, 0x12,
0x1, 0x10, 0x01,
0x1, 0x11, 0x82,
0x1, 0x12, 0x00,
0x1, 0x13, 0xD5,
0x1, 0x14, 0x18,
0x1, 0x15, 0x13,
0x1, 0x16, 0x03,
0x1, 0x17, 0x86,
0x1, 0x18, 0x0A,
0x1, 0x19, 0x09,
0x1, 0x1A, 0x08,
0x1, 0x1B, 0xC2,
0x1, 0x1C, 0x03,
0x1, 0x1D, 0x8F,
0x1, 0x1E, 0x0A,
0x1, 0x1F, 0x06,
0x1, 0x20, 0x01,
0x1, 0x21, 0x02,
0x1, 0x22, 0x00,
0x1, 0x23, 0xD5,
0x1, 0x24, 0x18,
0x1, 0x25, 0x22,
0x1, 0x26, 0x01,
0x1, 0x27, 0x82,
0x1, 0x28, 0x00,
0x1, 0x29, 0xD5,
0x1, 0x2A, 0x18,
0x1, 0x2B, 0x0B,
0x1, 0x2C, 0x28,
0x1, 0x2D, 0x78,
0x1, 0x2E, 0x28,
0x1, 0x2F, 0x91,
0x1, 0x30, 0x00,
0x1, 0x31, 0x0B,
0x1, 0x32, 0x00,
0x1, 0x33, 0x0B,
0x1, 0x34, 0x00,
0x1, 0x35, 0xA1,
0x1, 0x36, 0x00,
0x1, 0x37, 0xA0,
0x1, 0x38, 0x00,
0x1, 0x39, 0x04,
0x1, 0x3A, 0x28,
0x1, 0x3B, 0x30,
0x1, 0x3C, 0x0C,
0x1, 0x3D, 0x04,
0x1, 0x3E, 0x0F,
0x1, 0x3F, 0x79,
0x1, 0x40, 0x28,
0x1, 0x41, 0x1E,
0x1, 0x42, 0x2F,
0x1, 0x43, 0x87,
0x1, 0x44, 0x00,
0x1, 0x45, 0x0B,
0x1, 0x46, 0x00,
0x1, 0x47, 0x0B,
0x1, 0x48, 0x00,
0x1, 0x49, 0xA7,
0x1, 0x4A, 0x00,
0x1, 0x4B, 0xA6,
0x1, 0x4C, 0x00,
0x1, 0x4D, 0x04,
0x1, 0x4E, 0x01,
0x1, 0x4F, 0x00,
0x1, 0x50, 0x00,
0x1, 0x51, 0x80,
0x1, 0x52, 0x09,
0x1, 0x53, 0x08,
0x1, 0x54, 0x01,
0x1, 0x55, 0x00,
0x1, 0x56, 0x0F,
0x1, 0x57, 0x79,
0x1, 0x58, 0x09,
0x1, 0x59, 0x05,
0x1, 0x5A, 0x00,
0x1, 0x5B, 0x60,
0x1, 0x5C, 0x05,
0x1, 0x5D, 0xD1,
0x1, 0x5E, 0x0C,
0x1, 0x5F, 0x3C,
0x1, 0x60, 0x00,
0x1, 0x61, 0xD0,
0x1, 0x62, 0x0B,
0x1, 0x63, 0x03,
0x1, 0x64, 0x28,
0x1, 0x65, 0x10,
0x1, 0x66, 0x2A,
0x1, 0x67, 0x39,
0x1, 0x68, 0x0B,
0x1, 0x69, 0x02,
0x1, 0x6A, 0x28,
0x1, 0x6B, 0x10,
0x1, 0x6C, 0x2A,
0x1, 0x6D, 0x61,
0x1, 0x6E, 0x0C,
0x1, 0x6F, 0x00,
0x1, 0x70, 0x0F,
0x1, 0x71, 0x79,
0x1, 0x72, 0x00,
0x1, 0x73, 0x0B,
0x1, 0x74, 0x00,
0x1, 0x75, 0x0B,
0x1, 0x76, 0x00,
0x1, 0x77, 0xA1,
0x1, 0x78, 0x00,
0x1, 0x79, 0xA0,
0x1, 0x7A, 0x00,
0x1, 0x7B, 0x04,
0x1, 0xFF, 0x04,
0x1, 0x79, 0x1D,
0x1, 0x7B, 0x27,
0x1, 0x96, 0x0E,
0x1, 0x97, 0xFE,
0x1, 0x98, 0x03,
0x1, 0x99, 0xEF,
0x1, 0x9A, 0x02,
0x1, 0x9B, 0x44,
0x1, 0x73, 0x07,
0x1, 0x70, 0x01,
0x1, 0xff, 0x01,
0x1, 0x00, 0x01,
0x1, 0xff, 0x00,
0x00, 0x00, 0x00
};
#ifdef __cplusplus
}
#endif
#endif /* _VL53L0X_INTERRUPT_THRESHOLD_SETTINGS_H_ */

View File

@@ -0,0 +1,146 @@
/*******************************************************************************
* Copyright © 2016, STMicroelectronics International N.V.
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 STMicroelectronics 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, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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 _VL53L0X_TUNING_H_
#define _VL53L0X_TUNING_H_
#include "vl53l0x_def.h"
#ifdef __cplusplus
extern "C" {
#endif
uint8_t DefaultTuningSettings[] = {
/* update 02/11/2015_v36 */
0x01, 0xFF, 0x01,
0x01, 0x00, 0x00,
0x01, 0xFF, 0x00,
0x01, 0x09, 0x00,
0x01, 0x10, 0x00,
0x01, 0x11, 0x00,
0x01, 0x24, 0x01,
0x01, 0x25, 0xff,
0x01, 0x75, 0x00,
0x01, 0xFF, 0x01,
0x01, 0x4e, 0x2c,
0x01, 0x48, 0x00,
0x01, 0x30, 0x20,
0x01, 0xFF, 0x00,
0x01, 0x30, 0x09, /* mja changed from 0x64. */
0x01, 0x54, 0x00,
0x01, 0x31, 0x04,
0x01, 0x32, 0x03,
0x01, 0x40, 0x83,
0x01, 0x46, 0x25,
0x01, 0x60, 0x00,
0x01, 0x27, 0x00,
0x01, 0x50, 0x06,
0x01, 0x51, 0x00,
0x01, 0x52, 0x96,
0x01, 0x56, 0x08,
0x01, 0x57, 0x30,
0x01, 0x61, 0x00,
0x01, 0x62, 0x00,
0x01, 0x64, 0x00,
0x01, 0x65, 0x00,
0x01, 0x66, 0xa0,
0x01, 0xFF, 0x01,
0x01, 0x22, 0x32,
0x01, 0x47, 0x14,
0x01, 0x49, 0xff,
0x01, 0x4a, 0x00,
0x01, 0xFF, 0x00,
0x01, 0x7a, 0x0a,
0x01, 0x7b, 0x00,
0x01, 0x78, 0x21,
0x01, 0xFF, 0x01,
0x01, 0x23, 0x34,
0x01, 0x42, 0x00,
0x01, 0x44, 0xff,
0x01, 0x45, 0x26,
0x01, 0x46, 0x05,
0x01, 0x40, 0x40,
0x01, 0x0E, 0x06,
0x01, 0x20, 0x1a,
0x01, 0x43, 0x40,
0x01, 0xFF, 0x00,
0x01, 0x34, 0x03,
0x01, 0x35, 0x44,
0x01, 0xFF, 0x01,
0x01, 0x31, 0x04,
0x01, 0x4b, 0x09,
0x01, 0x4c, 0x05,
0x01, 0x4d, 0x04,
0x01, 0xFF, 0x00,
0x01, 0x44, 0x00,
0x01, 0x45, 0x20,
0x01, 0x47, 0x08,
0x01, 0x48, 0x28,
0x01, 0x67, 0x00,
0x01, 0x70, 0x04,
0x01, 0x71, 0x01,
0x01, 0x72, 0xfe,
0x01, 0x76, 0x00,
0x01, 0x77, 0x00,
0x01, 0xFF, 0x01,
0x01, 0x0d, 0x01,
0x01, 0xFF, 0x00,
0x01, 0x80, 0x01,
0x01, 0x01, 0xF8,
0x01, 0xFF, 0x01,
0x01, 0x8e, 0x01,
0x01, 0x00, 0x01,
0x01, 0xFF, 0x00,
0x01, 0x80, 0x00,
0x00, 0x00, 0x00
};
#ifdef __cplusplus
}
#endif
#endif /* _VL53L0X_TUNING_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,42 @@
/*******************************************************************************
* Copyright © 2016, STMicroelectronics International N.V.
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 STMicroelectronics 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, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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 "vl53l0x_api.h"
#include "vl53l0x_api_core.h"
#ifndef __KERNEL__
#include <stdlib.h>
#endif
#define LOG_FUNCTION_START(fmt, ...) \
_LOG_FUNCTION_START(TRACE_MODULE_API, fmt, ##__VA_ARGS__)
#define LOG_FUNCTION_END(status, ...) \
_LOG_FUNCTION_END(TRACE_MODULE_API, status, ##__VA_ARGS__)
#define LOG_FUNCTION_END_FMT(status, fmt, ...) \
_LOG_FUNCTION_END_FMT(TRACE_MODULE_API, status, fmt, ##__VA_ARGS__)

View File

@@ -0,0 +1,466 @@
/*******************************************************************************
* Copyright © 2016, STMicroelectronics International N.V.
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 STMicroelectronics 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, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED.
IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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 "vl53l0x_api.h"
#include "vl53l0x_api_core.h"
#include "vl53l0x_api_strings.h"
#ifndef __KERNEL__
#include <stdlib.h>
#endif
#define LOG_FUNCTION_START(fmt, ...) \
_LOG_FUNCTION_START(TRACE_MODULE_API, fmt, ##__VA_ARGS__)
#define LOG_FUNCTION_END(status, ...) \
_LOG_FUNCTION_END(TRACE_MODULE_API, status, ##__VA_ARGS__)
#define LOG_FUNCTION_END_FMT(status, fmt, ...) \
_LOG_FUNCTION_END_FMT(TRACE_MODULE_API, status, fmt, ##__VA_ARGS__)
VL53L0X_Error VL53L0X_check_part_used(VL53L0X_DEV Dev,
uint8_t *Revision,
VL53L0X_DeviceInfo_t *pVL53L0X_DeviceInfo)
{
VL53L0X_Error Status = VL53L0X_ERROR_NONE;
uint8_t ModuleIdInt;
char *ProductId_tmp;
LOG_FUNCTION_START("");
Status = VL53L0X_get_info_from_device(Dev, 2);
if (Status == VL53L0X_ERROR_NONE) {
ModuleIdInt = VL53L0X_GETDEVICESPECIFICPARAMETER(Dev, ModuleId);
if (ModuleIdInt == 0) {
*Revision = 0;
VL53L0X_COPYSTRING(pVL53L0X_DeviceInfo->ProductId, "");
} else {
*Revision = VL53L0X_GETDEVICESPECIFICPARAMETER(Dev, Revision);
ProductId_tmp = VL53L0X_GETDEVICESPECIFICPARAMETER(Dev,
ProductId);
VL53L0X_COPYSTRING(pVL53L0X_DeviceInfo->ProductId,
ProductId_tmp);
}
}
LOG_FUNCTION_END(Status);
return Status;
}
VL53L0X_Error VL53L0X_get_device_info(VL53L0X_DEV Dev,
VL53L0X_DeviceInfo_t *pVL53L0X_DeviceInfo)
{
VL53L0X_Error Status = VL53L0X_ERROR_NONE;
uint8_t revision_id;
uint8_t Revision;
Status = VL53L0X_check_part_used(Dev, &Revision, pVL53L0X_DeviceInfo);
if (Status == VL53L0X_ERROR_NONE) {
if (Revision == 0) {
VL53L0X_COPYSTRING(pVL53L0X_DeviceInfo->Name,
VL53L0X_STRING_DEVICE_INFO_NAME_TS0);
} else if ((Revision <= 34) && (Revision != 32)) {
VL53L0X_COPYSTRING(pVL53L0X_DeviceInfo->Name,
VL53L0X_STRING_DEVICE_INFO_NAME_TS1);
} else if (Revision < 39) {
VL53L0X_COPYSTRING(pVL53L0X_DeviceInfo->Name,
VL53L0X_STRING_DEVICE_INFO_NAME_TS2);
} else {
VL53L0X_COPYSTRING(pVL53L0X_DeviceInfo->Name,
VL53L0X_STRING_DEVICE_INFO_NAME_ES1);
}
VL53L0X_COPYSTRING(pVL53L0X_DeviceInfo->Type,
VL53L0X_STRING_DEVICE_INFO_TYPE);
}
if (Status == VL53L0X_ERROR_NONE) {
Status = VL53L0X_RdByte(Dev,
VL53L0X_REG_IDENTIFICATION_MODEL_ID,
&pVL53L0X_DeviceInfo->ProductType);
}
if (Status == VL53L0X_ERROR_NONE) {
Status = VL53L0X_RdByte(Dev,
VL53L0X_REG_IDENTIFICATION_REVISION_ID,
&revision_id);
pVL53L0X_DeviceInfo->ProductRevisionMajor = 1;
pVL53L0X_DeviceInfo->ProductRevisionMinor =
(revision_id & 0xF0) >> 4;
}
return Status;
}
VL53L0X_Error VL53L0X_get_device_error_string(VL53L0X_DeviceError ErrorCode,
char *pDeviceErrorString)
{
VL53L0X_Error Status = VL53L0X_ERROR_NONE;
LOG_FUNCTION_START("");
switch (ErrorCode) {
case VL53L0X_DEVICEERROR_NONE:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_NONE);
break;
case VL53L0X_DEVICEERROR_VCSELCONTINUITYTESTFAILURE:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_VCSELCONTINUITYTESTFAILURE);
break;
case VL53L0X_DEVICEERROR_VCSELWATCHDOGTESTFAILURE:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_VCSELWATCHDOGTESTFAILURE);
break;
case VL53L0X_DEVICEERROR_NOVHVVALUEFOUND:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_NOVHVVALUEFOUND);
break;
case VL53L0X_DEVICEERROR_MSRCNOTARGET:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_MSRCNOTARGET);
break;
case VL53L0X_DEVICEERROR_SNRCHECK:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_SNRCHECK);
break;
case VL53L0X_DEVICEERROR_RANGEPHASECHECK:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_RANGEPHASECHECK);
break;
case VL53L0X_DEVICEERROR_SIGMATHRESHOLDCHECK:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_SIGMATHRESHOLDCHECK);
break;
case VL53L0X_DEVICEERROR_TCC:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_TCC);
break;
case VL53L0X_DEVICEERROR_PHASECONSISTENCY:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_PHASECONSISTENCY);
break;
case VL53L0X_DEVICEERROR_MINCLIP:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_MINCLIP);
break;
case VL53L0X_DEVICEERROR_RANGECOMPLETE:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_RANGECOMPLETE);
break;
case VL53L0X_DEVICEERROR_ALGOUNDERFLOW:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_ALGOUNDERFLOW);
break;
case VL53L0X_DEVICEERROR_ALGOOVERFLOW:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_ALGOOVERFLOW);
break;
case VL53L0X_DEVICEERROR_RANGEIGNORETHRESHOLD:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_DEVICEERROR_RANGEIGNORETHRESHOLD);
break;
default:
VL53L0X_COPYSTRING(pDeviceErrorString,
VL53L0X_STRING_UNKNOW_ERROR_CODE);
}
LOG_FUNCTION_END(Status);
return Status;
}
VL53L0X_Error VL53L0X_get_range_status_string(uint8_t RangeStatus,
char *pRangeStatusString)
{
VL53L0X_Error Status = VL53L0X_ERROR_NONE;
LOG_FUNCTION_START("");
switch (RangeStatus) {
case 0:
VL53L0X_COPYSTRING(pRangeStatusString,
VL53L0X_STRING_RANGESTATUS_RANGEVALID);
break;
case 1:
VL53L0X_COPYSTRING(pRangeStatusString,
VL53L0X_STRING_RANGESTATUS_SIGMA);
break;
case 2:
VL53L0X_COPYSTRING(pRangeStatusString,
VL53L0X_STRING_RANGESTATUS_SIGNAL);
break;
case 3:
VL53L0X_COPYSTRING(pRangeStatusString,
VL53L0X_STRING_RANGESTATUS_MINRANGE);
break;
case 4:
VL53L0X_COPYSTRING(pRangeStatusString,
VL53L0X_STRING_RANGESTATUS_PHASE);
break;
case 5:
VL53L0X_COPYSTRING(pRangeStatusString,
VL53L0X_STRING_RANGESTATUS_HW);
break;
default: /**/
VL53L0X_COPYSTRING(pRangeStatusString,
VL53L0X_STRING_RANGESTATUS_NONE);
}
LOG_FUNCTION_END(Status);
return Status;
}
VL53L0X_Error VL53L0X_get_pal_error_string(VL53L0X_Error PalErrorCode,
char *pPalErrorString)
{
VL53L0X_Error Status = VL53L0X_ERROR_NONE;
LOG_FUNCTION_START("");
switch (PalErrorCode) {
case VL53L0X_ERROR_NONE:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_NONE);
break;
case VL53L0X_ERROR_CALIBRATION_WARNING:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_CALIBRATION_WARNING);
break;
case VL53L0X_ERROR_MIN_CLIPPED:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_MIN_CLIPPED);
break;
case VL53L0X_ERROR_UNDEFINED:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_UNDEFINED);
break;
case VL53L0X_ERROR_INVALID_PARAMS:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_INVALID_PARAMS);
break;
case VL53L0X_ERROR_NOT_SUPPORTED:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_NOT_SUPPORTED);
break;
case VL53L0X_ERROR_INTERRUPT_NOT_CLEARED:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_INTERRUPT_NOT_CLEARED);
break;
case VL53L0X_ERROR_RANGE_ERROR:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_RANGE_ERROR);
break;
case VL53L0X_ERROR_TIME_OUT:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_TIME_OUT);
break;
case VL53L0X_ERROR_MODE_NOT_SUPPORTED:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_MODE_NOT_SUPPORTED);
break;
case VL53L0X_ERROR_BUFFER_TOO_SMALL:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_BUFFER_TOO_SMALL);
break;
case VL53L0X_ERROR_GPIO_NOT_EXISTING:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_GPIO_NOT_EXISTING);
break;
case VL53L0X_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED);
break;
case VL53L0X_ERROR_CONTROL_INTERFACE:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_CONTROL_INTERFACE);
break;
case VL53L0X_ERROR_INVALID_COMMAND:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_INVALID_COMMAND);
break;
case VL53L0X_ERROR_DIVISION_BY_ZERO:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_DIVISION_BY_ZERO);
break;
case VL53L0X_ERROR_REF_SPAD_INIT:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_REF_SPAD_INIT);
break;
case VL53L0X_ERROR_NOT_IMPLEMENTED:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_ERROR_NOT_IMPLEMENTED);
break;
default:
VL53L0X_COPYSTRING(pPalErrorString,
VL53L0X_STRING_UNKNOW_ERROR_CODE);
}
LOG_FUNCTION_END(Status);
return Status;
}
VL53L0X_Error VL53L0X_get_pal_state_string(VL53L0X_State PalStateCode,
char *pPalStateString)
{
VL53L0X_Error Status = VL53L0X_ERROR_NONE;
LOG_FUNCTION_START("");
switch (PalStateCode) {
case VL53L0X_STATE_POWERDOWN:
VL53L0X_COPYSTRING(pPalStateString,
VL53L0X_STRING_STATE_POWERDOWN);
break;
case VL53L0X_STATE_WAIT_STATICINIT:
VL53L0X_COPYSTRING(pPalStateString,
VL53L0X_STRING_STATE_WAIT_STATICINIT);
break;
case VL53L0X_STATE_STANDBY:
VL53L0X_COPYSTRING(pPalStateString,
VL53L0X_STRING_STATE_STANDBY);
break;
case VL53L0X_STATE_IDLE:
VL53L0X_COPYSTRING(pPalStateString,
VL53L0X_STRING_STATE_IDLE);
break;
case VL53L0X_STATE_RUNNING:
VL53L0X_COPYSTRING(pPalStateString,
VL53L0X_STRING_STATE_RUNNING);
break;
case VL53L0X_STATE_UNKNOWN:
VL53L0X_COPYSTRING(pPalStateString,
VL53L0X_STRING_STATE_UNKNOWN);
break;
case VL53L0X_STATE_ERROR:
VL53L0X_COPYSTRING(pPalStateString,
VL53L0X_STRING_STATE_ERROR);
break;
default:
VL53L0X_COPYSTRING(pPalStateString,
VL53L0X_STRING_STATE_UNKNOWN);
}
LOG_FUNCTION_END(Status);
return Status;
}
VL53L0X_Error VL53L0X_get_sequence_steps_info(
VL53L0X_SequenceStepId SequenceStepId,
char *pSequenceStepsString)
{
VL53L0X_Error Status = VL53L0X_ERROR_NONE;
LOG_FUNCTION_START("");
switch (SequenceStepId) {
case VL53L0X_SEQUENCESTEP_TCC:
VL53L0X_COPYSTRING(pSequenceStepsString,
VL53L0X_STRING_SEQUENCESTEP_TCC);
break;
case VL53L0X_SEQUENCESTEP_DSS:
VL53L0X_COPYSTRING(pSequenceStepsString,
VL53L0X_STRING_SEQUENCESTEP_DSS);
break;
case VL53L0X_SEQUENCESTEP_MSRC:
VL53L0X_COPYSTRING(pSequenceStepsString,
VL53L0X_STRING_SEQUENCESTEP_MSRC);
break;
case VL53L0X_SEQUENCESTEP_PRE_RANGE:
VL53L0X_COPYSTRING(pSequenceStepsString,
VL53L0X_STRING_SEQUENCESTEP_PRE_RANGE);
break;
case VL53L0X_SEQUENCESTEP_FINAL_RANGE:
VL53L0X_COPYSTRING(pSequenceStepsString,
VL53L0X_STRING_SEQUENCESTEP_FINAL_RANGE);
break;
default:
Status = VL53L0X_ERROR_INVALID_PARAMS;
}
LOG_FUNCTION_END(Status);
return Status;
}
VL53L0X_Error VL53L0X_get_limit_check_info(VL53L0X_DEV Dev,
uint16_t LimitCheckId,
char *pLimitCheckString)
{
VL53L0X_Error Status = VL53L0X_ERROR_NONE;
LOG_FUNCTION_START("");
switch (LimitCheckId) {
case VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE:
VL53L0X_COPYSTRING(pLimitCheckString,
VL53L0X_STRING_CHECKENABLE_SIGMA_FINAL_RANGE);
break;
case VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE:
VL53L0X_COPYSTRING(pLimitCheckString,
VL53L0X_STRING_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE);
break;
case VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP:
VL53L0X_COPYSTRING(pLimitCheckString,
VL53L0X_STRING_CHECKENABLE_SIGNAL_REF_CLIP);
break;
case VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD:
VL53L0X_COPYSTRING(pLimitCheckString,
VL53L0X_STRING_CHECKENABLE_RANGE_IGNORE_THRESHOLD);
break;
case VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC:
VL53L0X_COPYSTRING(pLimitCheckString,
VL53L0X_STRING_CHECKENABLE_SIGNAL_RATE_MSRC);
break;
case VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE:
VL53L0X_COPYSTRING(pLimitCheckString,
VL53L0X_STRING_CHECKENABLE_SIGNAL_RATE_PRE_RANGE);
break;
default:
VL53L0X_COPYSTRING(pLimitCheckString,
VL53L0X_STRING_UNKNOW_ERROR_CODE);
}
LOG_FUNCTION_END(Status);
return Status;
}

View File

@@ -0,0 +1,55 @@
# VL53L0X 多传感器模板STM32H743 + FreeRTOS
这组模板按固定顺序组织 4 颗 VL53L0X
1. 左上
2. 左下
3. 右上
4. 右下
## 文件说明
- `vl53l0x_platform.h/.c`
- ST 官方 API 的平台适配层
- 不再把 `hi2c1` 硬编码到驱动里
- 读写失败时不会污染 `RdWord/RdDWord` 输出
- `PollingDelay()` 在调度器已启动时使用 `vTaskDelay()`
- `vl53_board.h/.c`
- 4 颗 VL53L0X 的板级管理层
- 负责 `XSHUT` 拉低/逐个拉起/逐个改地址
- 默认运行地址0x54 / 0x56 / 0x58 / 0x5A8-bit 写法)
- `vl53_task.h/.c`
- FreeRTOS 任务骨架
- 10ms 周期轮询一遍 4 颗传感器
- 采集结果写成一个快照,避免上层散读散写
## 你需要改的地方
只要改 `vl53_board.c` 里的 `g_vl53_hw_cfg[]`
- `hi2c`
- `xshut_port`
- `xshut_pin`
- `gpio1_port` / `gpio1_pin`(如果暂时不用中断,可保持 `NULL/0`
## 集成方式
1. 保留 ST 官方 API 的 `vl53l0x_api*.c``vl53l0x_def.h` 等核心文件不动。
2. 用本模板替换你原来的 `vl53l0x_platform.h/.c`
3. 新增 `vl53_board.*``vl53_task.*``App/sensors/` 或你自己的目录。
4. 在 CubeMX 里保留任务壳函数,在任务壳里调用 `AppVl53_TaskLoop()`
5. 不要把 VL53 逻辑塞进你 20ms 的 `canTxTask`
## 建议任务频率
- `canTxTask`: 保持 20ms
- `vl53Task`: 10ms 唤醒,内部读 ready 后取数
- 估计/控制50100Hz
## 备注
- 地址写法用的是 **8-bit**,默认地址是 `0x52`
- 多颗同总线时,必须所有器件先 `XSHUT=RESET`,然后逐个拉起并改地址。
- 这版模板默认走“单任务采集 + 快照共享”,适合你当前的 ASER 架构。

View File

@@ -0,0 +1,166 @@
#include "vl53_board.h"
#include "FreeRTOS.h"
#include "task.h"
#include "robot_params.h"
/* ================= 卡尔曼滤波底层实现 ================= */
static void vl53_kalman_init(Vl53Kalman_t *kf, float q, float r) {
kf->x = 0.0f;
kf->p = 1.0f;
kf->q = q;
kf->r = r;
kf->initialized = 0;
}
static float vl53_kalman_update(Vl53Kalman_t *kf, float measurement) {
if (kf->initialized == 0) {
kf->x = measurement;
kf->initialized = 1;
return kf->x;
}
kf->p = kf->p + kf->q;
float k = kf->p / (kf->p + kf->r);
kf->x = kf->x + k * (measurement - kf->x);
kf->p = (1.0f - k) * kf->p;
return kf->x;
}
/* ================= ST 官方配置序列 ================= */
static VL53L0X_Error vl53_do_static_init(VL53L0X_DEV dev, uint32_t timing_budget_us)
{
VL53L0X_Error status;
uint32_t ref_spad_count = 0u;
uint8_t is_aperture_spads = 0u;
uint8_t vhv_settings = 0u;
uint8_t phase_cal = 0u;
status = VL53L0X_StaticInit(dev);
if (status != VL53L0X_ERROR_NONE) return status;
status = VL53L0X_PerformRefSpadManagement(dev, &ref_spad_count, &is_aperture_spads);
if (status != VL53L0X_ERROR_NONE) return status;
status = VL53L0X_PerformRefCalibration(dev, &vhv_settings, &phase_cal);
if (status != VL53L0X_ERROR_NONE) return status;
status = VL53L0X_SetDeviceMode(dev, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING);
if (status != VL53L0X_ERROR_NONE) return status;
status = VL53L0X_SetMeasurementTimingBudgetMicroSeconds(dev, timing_budget_us);
if (status != VL53L0X_ERROR_NONE) return status;
status = VL53L0X_SetLimitCheckEnable(dev, VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, 1u);
if (status != VL53L0X_ERROR_NONE) return status;
status = VL53L0X_SetLimitCheckEnable(dev, VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, 1u);
if (status != VL53L0X_ERROR_NONE) return status;
return VL53L0X_ERROR_NONE;
}
/* ================= 核心管理器 API ================= */
VL53L0X_Error Vl53Board_Init(Vl53Board_t *board, const Vl53BoardHwCfg_t *hw_cfgs, uint8_t count, uint32_t timing_budget_us)
{
if ((board == NULL) || (hw_cfgs == NULL) || (count == 0) || (count > VL53_MAX_DEVS_PER_BOARD)) {
return VL53L0X_ERROR_INVALID_PARAMS;
}
memset(board, 0, sizeof(Vl53Board_t));
board->dev_count = count;
board->timing_budget_us = (timing_budget_us == 0u) ? 33000u : timing_budget_us;
for (uint8_t i = 0; i < count; i++) {
board->dev[i].name = hw_cfgs[i].name;
board->dev[i].id = hw_cfgs[i].id;
board->dev[i].comms_type = 1u;
board->dev[i].comms_speed_khz = 400u;
board->dev[i].is_present = 0u;
VL53L0X_PlatformAttachBus(&board->dev[i], hw_cfgs[i].hi2c, VL53L0X_DEFAULT_ADDR_8BIT, 100u, NULL);
VL53L0X_PlatformAttachPins(&board->dev[i], hw_cfgs[i].xshut_port, hw_cfgs[i].xshut_pin, NULL, 0);
VL53L0X_PlatformSetXShut(&board->dev[i], GPIO_PIN_RESET);
/* 初始化卡尔曼滤波器Q/R 从 robot_params.h 读取 */
vl53_kalman_init(&board->kf[i], PARAM_VL53_KALMAN_Q, PARAM_VL53_KALMAN_R);
}
vTaskDelay(pdMS_TO_TICKS(10));
for (uint8_t i = 0; i < count; i++) {
if (VL53L0X_PlatformSetXShut(&board->dev[i], GPIO_PIN_SET) != VL53L0X_ERROR_NONE) continue;
vTaskDelay(pdMS_TO_TICKS(20));
board->dev[i].I2cDevAddr = VL53L0X_DEFAULT_ADDR_8BIT;
if (VL53L0X_PlatformChangeAddress(&board->dev[i], hw_cfgs[i].runtime_addr_8bit) != VL53L0X_ERROR_NONE) continue;
if (VL53L0X_DataInit(&board->dev[i]) != VL53L0X_ERROR_NONE) continue;
if (vl53_do_static_init(&board->dev[i], board->timing_budget_us) != VL53L0X_ERROR_NONE) continue;
board->init_mask |= (uint8_t)(1u << i);
board->dev[i].is_present = 1u;
}
return VL53L0X_ERROR_NONE;
}
VL53L0X_Error Vl53Board_StartContinuous(Vl53Board_t *board)
{
if (board == NULL) return VL53L0X_ERROR_INVALID_PARAMS;
for (uint8_t i = 0; i < board->dev_count; i++) {
if (board->init_mask & (1u << i)) VL53L0X_StartMeasurement(&board->dev[i]);
}
return VL53L0X_ERROR_NONE;
}
VL53L0X_Error Vl53Board_StopContinuous(Vl53Board_t *board)
{
if (board == NULL) return VL53L0X_ERROR_INVALID_PARAMS;
for (uint8_t i = 0; i < board->dev_count; i++) {
if (board->init_mask & (1u << i)) VL53L0X_StopMeasurement(&board->dev[i]);
}
return VL53L0X_ERROR_NONE;
}
VL53L0X_Error Vl53Board_ReadAll(Vl53Board_t *board, Vl53BoardSnapshot_t *snapshot)
{
if (board == NULL || snapshot == NULL) return VL53L0X_ERROR_INVALID_PARAMS;
memset(snapshot, 0, sizeof(Vl53BoardSnapshot_t));
snapshot->tick_ms = xTaskGetTickCount() * portTICK_PERIOD_MS;
for (uint8_t i = 0; i < board->dev_count; i++) {
if ((board->init_mask & (1u << i)) == 0u) {
snapshot->range_status[i] = 255u;
continue;
}
uint8_t ready = 0u;
if (VL53L0X_GetMeasurementDataReady(&board->dev[i], &ready) != VL53L0X_ERROR_NONE) continue;
if (ready) {
VL53L0X_RangingMeasurementData_t data;
memset(&data, 0, sizeof(data));
if (VL53L0X_GetRangingMeasurementData(&board->dev[i], &data) == VL53L0X_ERROR_NONE) {
/* 1. 写入原始数据 */
snapshot->range_mm[i] = data.RangeMilliMeter;
snapshot->range_status[i] = data.RangeStatus;
if (data.RangeStatus == 0u) {
/* 2. 标记有效并更新卡尔曼滤波器 */
snapshot->valid_mask |= (1u << i);
snapshot->range_mm_filtered[i] = vl53_kalman_update(&board->kf[i], (float)data.RangeMilliMeter);
} else {
/* 测距失败时,滤波值维持上一次的历史最佳估计不变 */
snapshot->range_mm_filtered[i] = board->kf[i].x;
}
VL53L0X_ClearInterruptMask(&board->dev[i], 0u);
}
} else {
/* 如果没准备好,把上一帧的历史值顺延下来,防止读到 0 */
snapshot->range_mm_filtered[i] = board->kf[i].x;
}
}
return VL53L0X_ERROR_NONE;
}

View File

@@ -0,0 +1,59 @@
#ifndef VL53_BOARD_H
#define VL53_BOARD_H
#include <stdint.h>
#include <string.h>
#include "vl53l0x_api.h"
#include "vl53l0x_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
#define VL53_MAX_DEVS_PER_BOARD 4
typedef struct {
I2C_HandleTypeDef *hi2c;
GPIO_TypeDef *xshut_port;
uint16_t xshut_pin;
uint8_t runtime_addr_8bit;
const char *name;
uint8_t id;
} Vl53BoardHwCfg_t;
/* ================= 内部卡尔曼滤波器结构 ================= */
typedef struct {
float x; // 最优估计值 (滤波后的距离)
float p; // 估计误差协方差
float q; // 过程噪声
float r; // 测量噪声
uint8_t initialized; // 防止第一次开机从0缓慢爬升
} Vl53Kalman_t;
/* ================= 快照数据结构 (对外接口) ================= */
typedef struct {
uint32_t tick_ms;
uint16_t range_mm[VL53_MAX_DEVS_PER_BOARD]; /* 接口1原始硬件数据 */
float range_mm_filtered[VL53_MAX_DEVS_PER_BOARD]; /* 接口2卡尔曼平滑数据 */
uint8_t range_status[VL53_MAX_DEVS_PER_BOARD];
uint8_t valid_mask;
} Vl53BoardSnapshot_t;
typedef struct {
VL53L0X_Dev_t dev[VL53_MAX_DEVS_PER_BOARD];
Vl53Kalman_t kf[VL53_MAX_DEVS_PER_BOARD]; /* 每个传感器配备一个专属卡尔曼滤波器 */
uint8_t init_mask;
uint8_t dev_count;
uint32_t timing_budget_us;
} Vl53Board_t;
VL53L0X_Error Vl53Board_Init(Vl53Board_t *board, const Vl53BoardHwCfg_t *hw_cfgs, uint8_t count, uint32_t timing_budget_us);
VL53L0X_Error Vl53Board_StartContinuous(Vl53Board_t *board);
VL53L0X_Error Vl53Board_StopContinuous(Vl53Board_t *board);
VL53L0X_Error Vl53Board_ReadAll(Vl53Board_t *board, Vl53BoardSnapshot_t *snapshot);
#ifdef __cplusplus
}
#endif
#endif /* VL53_BOARD_H */

View File

@@ -0,0 +1,315 @@
#include "vl53l0x_platform.h"
#include "vl53l0x_api.h"
#if VL53_USE_FREERTOS_DELAY
#include "FreeRTOS.h"
#include "task.h"
#endif
#if defined(configSUPPORT_STATIC_ALLOCATION) || defined(configUSE_MUTEXES)
#include "semphr.h"
#define VL53_USE_FREERTOS_MUTEX 1
#else
#define VL53_USE_FREERTOS_MUTEX 0
#endif
static VL53L0X_Error vl53_hal_to_pal(HAL_StatusTypeDef hal_status)
{
switch (hal_status) {
case HAL_OK:
return VL53L0X_ERROR_NONE;
case HAL_TIMEOUT:
return VL53L0X_ERROR_TIME_OUT;
default:
return VL53L0X_ERROR_CONTROL_INTERFACE;
}
}
static VL53L0X_Error vl53_validate_dev(VL53L0X_DEV Dev)
{
if ((Dev == NULL) || (Dev->hi2c == NULL)) {
return VL53L0X_ERROR_CONTROL_INTERFACE;
}
return VL53L0X_ERROR_NONE;
}
static VL53L0X_Error vl53_bus_lock(VL53L0X_DEV Dev)
{
#if VL53_USE_FREERTOS_MUTEX
if ((Dev != NULL) && (Dev->bus_lock != NULL)) {
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
const TickType_t wait_ticks = pdMS_TO_TICKS((Dev->io_timeout_ms == 0u) ? 10u : Dev->io_timeout_ms);
if (xSemaphoreTake((SemaphoreHandle_t)Dev->bus_lock, wait_ticks) != pdTRUE) {
return VL53L0X_ERROR_TIME_OUT;
}
}
}
#else
(void)Dev;
#endif
return VL53L0X_ERROR_NONE;
}
static void vl53_bus_unlock(VL53L0X_DEV Dev)
{
#if VL53_USE_FREERTOS_MUTEX
if ((Dev != NULL) && (Dev->bus_lock != NULL)) {
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
(void)xSemaphoreGive((SemaphoreHandle_t)Dev->bus_lock);
}
}
#else
(void)Dev;
#endif
}
VL53L0X_Error VL53L0X_LockSequenceAccess(VL53L0X_DEV Dev)
{
(void)Dev;
/* Shared I2C bus is already serialized per I/O transaction below. */
return VL53L0X_ERROR_NONE;
}
VL53L0X_Error VL53L0X_UnlockSequenceAccess(VL53L0X_DEV Dev)
{
(void)Dev;
return VL53L0X_ERROR_NONE;
}
void VL53L0X_PlatformAttachBus(VL53L0X_DEV Dev,
I2C_HandleTypeDef *hi2c,
uint8_t i2c_addr_8bit,
uint16_t io_timeout_ms,
void *bus_lock)
{
if (Dev == NULL) {
return;
}
Dev->hi2c = hi2c;
Dev->I2cDevAddr = i2c_addr_8bit;
Dev->io_timeout_ms = (io_timeout_ms == 0u) ? 100u : io_timeout_ms;
Dev->bus_lock = bus_lock;
}
void VL53L0X_PlatformAttachPins(VL53L0X_DEV Dev,
GPIO_TypeDef *xshut_port,
uint16_t xshut_pin,
GPIO_TypeDef *gpio1_port,
uint16_t gpio1_pin)
{
if (Dev == NULL) {
return;
}
Dev->xshut_port = xshut_port;
Dev->xshut_pin = xshut_pin;
Dev->gpio1_port = gpio1_port;
Dev->gpio1_pin = gpio1_pin;
}
VL53L0X_Error VL53L0X_PlatformSetXShut(VL53L0X_DEV Dev, GPIO_PinState state)
{
if ((Dev == NULL) || (Dev->xshut_port == NULL)) {
return VL53L0X_ERROR_INVALID_PARAMS;
}
HAL_GPIO_WritePin(Dev->xshut_port, Dev->xshut_pin, state);
return VL53L0X_ERROR_NONE;
}
VL53L0X_Error VL53L0X_PlatformBootDevice(VL53L0X_DEV Dev, uint32_t reset_low_ms, uint32_t boot_wait_ms)
{
VL53L0X_Error status = VL53L0X_PlatformSetXShut(Dev, GPIO_PIN_RESET);
if (status != VL53L0X_ERROR_NONE) {
return status;
}
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
vTaskDelay(pdMS_TO_TICKS(reset_low_ms));
} else {
HAL_Delay(reset_low_ms);
}
status = VL53L0X_PlatformSetXShut(Dev, GPIO_PIN_SET);
if (status != VL53L0X_ERROR_NONE) {
return status;
}
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
vTaskDelay(pdMS_TO_TICKS(boot_wait_ms));
} else {
HAL_Delay(boot_wait_ms);
}
return VL53L0X_ERROR_NONE;
}
uint32_t VL53L0X_PlatformGetTick(void)
{
return HAL_GetTick();
}
VL53L0X_Error VL53L0X_WriteMulti(VL53L0X_DEV Dev, uint8_t index, uint8_t *pdata, uint32_t count)
{
HAL_StatusTypeDef hal_status;
VL53L0X_Error status;
if ((pdata == NULL) || (count == 0u) || (count > 255u)) {
return VL53L0X_ERROR_INVALID_PARAMS;
}
status = vl53_validate_dev(Dev);
if (status != VL53L0X_ERROR_NONE) {
return status;
}
status = vl53_bus_lock(Dev);
if (status != VL53L0X_ERROR_NONE) {
return status;
}
hal_status = HAL_I2C_Mem_Write(Dev->hi2c,
Dev->I2cDevAddr,
index,
I2C_MEMADD_SIZE_8BIT,
pdata,
(uint16_t)count,
Dev->io_timeout_ms);
vl53_bus_unlock(Dev);
return vl53_hal_to_pal(hal_status);
}
VL53L0X_Error VL53L0X_ReadMulti(VL53L0X_DEV Dev, uint8_t index, uint8_t *pdata, uint32_t count)
{
HAL_StatusTypeDef hal_status;
VL53L0X_Error status;
if ((pdata == NULL) || (count == 0u) || (count > 255u)) {
return VL53L0X_ERROR_INVALID_PARAMS;
}
status = vl53_validate_dev(Dev);
if (status != VL53L0X_ERROR_NONE) {
return status;
}
status = vl53_bus_lock(Dev);
if (status != VL53L0X_ERROR_NONE) {
return status;
}
hal_status = HAL_I2C_Mem_Read(Dev->hi2c,
Dev->I2cDevAddr,
index,
I2C_MEMADD_SIZE_8BIT,
pdata,
(uint16_t)count,
Dev->io_timeout_ms);
vl53_bus_unlock(Dev);
return vl53_hal_to_pal(hal_status);
}
VL53L0X_Error VL53L0X_WrByte(VL53L0X_DEV Dev, uint8_t index, uint8_t data)
{
return VL53L0X_WriteMulti(Dev, index, &data, 1u);
}
VL53L0X_Error VL53L0X_WrWord(VL53L0X_DEV Dev, uint8_t index, uint16_t data)
{
uint8_t buffer[2];
buffer[0] = (uint8_t)(data >> 8);
buffer[1] = (uint8_t)(data & 0xFFu);
return VL53L0X_WriteMulti(Dev, index, buffer, 2u);
}
VL53L0X_Error VL53L0X_WrDWord(VL53L0X_DEV Dev, uint8_t index, uint32_t data)
{
uint8_t buffer[4];
buffer[0] = (uint8_t)(data >> 24);
buffer[1] = (uint8_t)(data >> 16);
buffer[2] = (uint8_t)(data >> 8);
buffer[3] = (uint8_t)(data & 0xFFu);
return VL53L0X_WriteMulti(Dev, index, buffer, 4u);
}
VL53L0X_Error VL53L0X_RdByte(VL53L0X_DEV Dev, uint8_t index, uint8_t *data)
{
if (data == NULL) {
return VL53L0X_ERROR_INVALID_PARAMS;
}
return VL53L0X_ReadMulti(Dev, index, data, 1u);
}
VL53L0X_Error VL53L0X_RdWord(VL53L0X_DEV Dev, uint8_t index, uint16_t *data)
{
uint8_t buffer[2] = {0u, 0u};
VL53L0X_Error status;
if (data == NULL) {
return VL53L0X_ERROR_INVALID_PARAMS;
}
status = VL53L0X_ReadMulti(Dev, index, buffer, 2u);
if (status == VL53L0X_ERROR_NONE) {
*data = (((uint16_t)buffer[0]) << 8) | buffer[1];
}
return status;
}
VL53L0X_Error VL53L0X_RdDWord(VL53L0X_DEV Dev, uint8_t index, uint32_t *data)
{
uint8_t buffer[4] = {0u, 0u, 0u, 0u};
VL53L0X_Error status;
if (data == NULL) {
return VL53L0X_ERROR_INVALID_PARAMS;
}
status = VL53L0X_ReadMulti(Dev, index, buffer, 4u);
if (status == VL53L0X_ERROR_NONE) {
*data = (((uint32_t)buffer[0]) << 24)
| (((uint32_t)buffer[1]) << 16)
| (((uint32_t)buffer[2]) << 8)
| ((uint32_t)buffer[3]);
}
return status;
}
VL53L0X_Error VL53L0X_UpdateByte(VL53L0X_DEV Dev, uint8_t index, uint8_t AndData, uint8_t OrData)
{
VL53L0X_Error status;
uint8_t data = 0u;
status = VL53L0X_RdByte(Dev, index, &data);
if (status != VL53L0X_ERROR_NONE) {
return status;
}
data = (uint8_t)((data & AndData) | OrData);
return VL53L0X_WrByte(Dev, index, data);
}
VL53L0X_Error VL53L0X_PollingDelay(VL53L0X_DEV Dev)
{
(void)Dev;
#if VL53_USE_FREERTOS_DELAY
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
vTaskDelay(pdMS_TO_TICKS(2u));
} else {
HAL_Delay(2u);
}
#else
HAL_Delay(2u);
#endif
return VL53L0X_ERROR_NONE;
}
VL53L0X_Error VL53L0X_PlatformChangeAddress(VL53L0X_DEV Dev, uint8_t new_addr_8bit)
{
VL53L0X_Error status;
if (new_addr_8bit == 0u) {
return VL53L0X_ERROR_INVALID_PARAMS;
}
status = VL53L0X_SetDeviceAddress(Dev, new_addr_8bit);
if (status == VL53L0X_ERROR_NONE) {
Dev->I2cDevAddr = new_addr_8bit;
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
vTaskDelay(pdMS_TO_TICKS(2u));
} else {
HAL_Delay(2u);
}
}
return status;
}

View File

@@ -0,0 +1,89 @@
#ifndef VL53L0X_PLATFORM_H
#define VL53L0X_PLATFORM_H
#include <stdint.h>
#include <string.h>
#include "main.h"
#ifndef VL53L0X_SINGLE_DEVICE_DRIVER
#define VL53L0X_SINGLE_DEVICE_DRIVER 0
#endif
#include "vl53l0x_def.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef VL53_USE_FREERTOS_DELAY
#define VL53_USE_FREERTOS_DELAY 1
#endif
#ifndef VL53L0X_COPYSTRING
#define VL53L0X_COPYSTRING(dst, src) strcpy((dst), (src))
#endif
#ifndef VL53L0X_DEFAULT_ADDR_8BIT
#define VL53L0X_DEFAULT_ADDR_8BIT 0x52u
#endif
typedef struct {
VL53L0X_DevData_t Data;
uint8_t I2cDevAddr; /* ST API expects 8-bit address, default 0x52 */
uint8_t comms_type;
uint16_t comms_speed_khz;
I2C_HandleTypeDef *hi2c;
GPIO_TypeDef *xshut_port;
uint16_t xshut_pin;
GPIO_TypeDef *gpio1_port; /* optional */
uint16_t gpio1_pin;
void *bus_lock; /* optional shared mutex/lock handle */
const char *name;
uint8_t id; /* user label: 1=左上, 2=左下, 3=右上, 4=右下 */
uint8_t is_present;
uint16_t io_timeout_ms;
} VL53L0X_Dev_t;
typedef VL53L0X_Dev_t* VL53L0X_DEV;
#define PALDevDataGet(Dev, field) ((Dev)->Data.field)
#define PALDevDataSet(Dev, field, data) ((Dev)->Data.field = (data))
VL53L0X_Error VL53L0X_LockSequenceAccess(VL53L0X_DEV Dev);
VL53L0X_Error VL53L0X_UnlockSequenceAccess(VL53L0X_DEV Dev);
VL53L0X_Error VL53L0X_WriteMulti(VL53L0X_DEV Dev, uint8_t index, uint8_t *pdata, uint32_t count);
VL53L0X_Error VL53L0X_ReadMulti(VL53L0X_DEV Dev, uint8_t index, uint8_t *pdata, uint32_t count);
VL53L0X_Error VL53L0X_WrByte(VL53L0X_DEV Dev, uint8_t index, uint8_t data);
VL53L0X_Error VL53L0X_WrWord(VL53L0X_DEV Dev, uint8_t index, uint16_t data);
VL53L0X_Error VL53L0X_WrDWord(VL53L0X_DEV Dev, uint8_t index, uint32_t data);
VL53L0X_Error VL53L0X_RdByte(VL53L0X_DEV Dev, uint8_t index, uint8_t *data);
VL53L0X_Error VL53L0X_RdWord(VL53L0X_DEV Dev, uint8_t index, uint16_t *data);
VL53L0X_Error VL53L0X_RdDWord(VL53L0X_DEV Dev, uint8_t index, uint32_t *data);
VL53L0X_Error VL53L0X_UpdateByte(VL53L0X_DEV Dev, uint8_t index, uint8_t AndData, uint8_t OrData);
VL53L0X_Error VL53L0X_PollingDelay(VL53L0X_DEV Dev);
void VL53L0X_PlatformAttachBus(VL53L0X_DEV Dev,
I2C_HandleTypeDef *hi2c,
uint8_t i2c_addr_8bit,
uint16_t io_timeout_ms,
void *bus_lock);
void VL53L0X_PlatformAttachPins(VL53L0X_DEV Dev,
GPIO_TypeDef *xshut_port,
uint16_t xshut_pin,
GPIO_TypeDef *gpio1_port,
uint16_t gpio1_pin);
VL53L0X_Error VL53L0X_PlatformSetXShut(VL53L0X_DEV Dev, GPIO_PinState state);
VL53L0X_Error VL53L0X_PlatformBootDevice(VL53L0X_DEV Dev, uint32_t reset_low_ms, uint32_t boot_wait_ms);
VL53L0X_Error VL53L0X_PlatformChangeAddress(VL53L0X_DEV Dev, uint8_t new_addr_8bit);
uint32_t VL53L0X_PlatformGetTick(void);
#ifdef __cplusplus
}
#endif
#endif /* VL53L0X_PLATFORM_H */

View File

@@ -0,0 +1,18 @@
#ifndef _VL53L0X_PLATFORM_LOG_H_
#define _VL53L0X_PLATFORM_LOG_H_
/* 1. 解决 TRACE_MODULE_API 未定义的报错 */
#define TRACE_MODULE_API 0
/* 2. 强行屏蔽官方所有【带下划线】的底层日志宏 */
#define _LOG_FUNCTION_START(...) (void)0
#define _LOG_FUNCTION_END(...) (void)0
#define _LOG_FUNCTION_END_FMT(...) (void)0
/* 3. 强行屏蔽官方所有【不带下划线】的普通日志宏 */
#define LOG_FUNCTION_START(...) (void)0
#define LOG_FUNCTION_END(...) (void)0
#define LOG_FUNCTION_END_FMT(...) (void)0
#define VL53L0X_ErrLog(...) (void)0
#endif /* _VL53L0X_PLATFORM_LOG_H_ */

View File

@@ -0,0 +1,15 @@
#ifndef _VL53L0X_TYPES_H_
#define _VL53L0X_TYPES_H_
/* 引入现代 C 语言标准整数类型库 */
#include <stdint.h>
#include <stddef.h>
#ifndef NULL
#define NULL 0
#endif
/* 核心修复:填补 ST 官方定义的定点数类型 */
typedef uint32_t FixPoint1616_t;
#endif /* _VL53L0X_TYPES_H_ */

423
App/app_tasks.c Normal file
View File

@@ -0,0 +1,423 @@
#include "app_tasks.h"
#include "FreeRTOS.h"
#include "cmsis_os.h"
#include "main.h"
#include "snc_can_app.h"
#include "robot_params.h" /* 统一参数配置 */
#include <stdio.h>
#include <string.h>
/* 引入各个传感器和黑板的头文件 */
#include "Contract/robot_blackboard.h"
#include "Contract/robot_odom.h"
#include "laser/laser_manager.h"
#include "IMU/hwt101.h"
#include "vl53_board.h"
#include "Contract/robot_cmd_slot.h"
#include "preproc/corridor_preproc.h"
#include "est/corridor_filter.h"
#include "nav/corridor_ctrl.h"
#include "nav/segment_fsm.h"
#include "nav/nav_script.h"
extern osMutexId_t logMutexHandle;
/* 如果你的项目中没有引入 i2c.h可以通过 extern 声明 I2C 句柄 */
extern I2C_HandleTypeDef hi2c1;
extern I2C_HandleTypeDef hi2c2;
static float g_test_vx = 0.0f;
static float g_test_wz = 0.0f;
static uint32_t AppTasks_MsToTicks(uint32_t ms)
{
uint32_t ticks = pdMS_TO_TICKS(ms);
return (ticks == 0U) ? 1U : ticks;
}
static void App_UpdateTestCommand(void)
{
g_test_vx = 0.0f;
g_test_wz = 0.0f;
}
static void App_PrintStatus(void)
{
// 【新增】静态计数器,由于是 static 修饰,它的值在函数退出后不会丢失
static uint8_t print_divider = 0;
// 假设外部任务是 100ms 调用一次该函数:
// 如果设定 >= 5就是 5 * 100ms = 500ms 打印一次
// 如果设定 >= 10就是 10 * 100ms = 1000ms (1秒) 打印一次
if (++print_divider < 5) {
return; // 还没到设定的次数,直接 return不执行后续获取快照和打印的动作
}
print_divider = 0; // 计数器清零,重新开始下一轮计数
// 1. 获取全局黑板的快照
RobotBlackboard_t snap;
Blackboard_GetSnapshot(&snap);
// 2. 申请串口互斥锁,防止多线程打印打架导致乱码
if (logMutexHandle != NULL) {
(void)osMutexAcquire(logMutexHandle, osWaitForever);
}
// 3. 打印表头和当前系统时间
printf("\r\n========== Robot Status [%lu ms] ==========\r\n", HAL_GetTick());
// 4. 打印 IMU 姿态
if (snap.imu_yaw.is_valid) {
printf("[IMU] Yaw: %7.2f deg | Cont: %7.2f deg | Wz: %7.2f\r\n",
snap.imu_yaw.value, snap.imu_yaw_continuous.value, snap.imu_wz.value);
} else {
printf("[IMU] --- OFFLINE or INVALID ---\r\n");
}
// 5. 打印侧向阵列雷达 (强制转为 int去掉多余的小数点)
printf("[VL53L0X] Left-F : %4d mm | Left-R : %4d mm\r\n",
(int)snap.dist_left_f.value, (int)snap.dist_left_r.value);
printf(" Right-F: %4d mm | Right-R: %4d mm\r\n",
(int)snap.dist_right_f.value, (int)snap.dist_right_r.value);
// 6. 打印前后激光测距雷达 (四个探头独立显示)
printf("[LASER] F-STP: %4d mm | F-ATK: %4d mm\r\n",
(int)snap.dist_front_stp.value, (int)snap.dist_front_atk.value);
printf(" R-STP: %4d mm | R-ATK: %4d mm\r\n",
(int)snap.dist_rear_stp.value, (int)snap.dist_rear_atk.value);
printf("==================================================\r\n");
// 7. 释放锁
if (logMutexHandle != NULL) {
(void)osMutexRelease(logMutexHandle);
}
}
void AppTasks_RunCanTxTask(void *argument)
{
(void)argument;
uint32_t wake_tick = osKernelGetTickCount();
const uint32_t period_ticks = AppTasks_MsToTicks(20U);
// 用于存放从指令槽里取出来的控制指令
RobotTargetCmd_t current_cmd;
for (;;) {
// 维持心跳发送
SNC_CAN_20msTask();
// 从指令槽中获取最新指令,设置 100ms 超时容忍度
if (CmdSlot_Pop(&current_cmd, 100)) {
// 如果算法层在 100ms 内有更新指令,正常下发给底盘
(void)SNC_CAN_SendCmdVel(current_cmd.target_vx, current_cmd.target_wz, current_cmd.ctrl_flags);
} else {
// 🚨 触发安全保护:如果超过 100ms 没收到上层新指令(可能算法死机或网络断开)
// 强制发送 0 速度,让底盘立刻停车,防止飞车撞墙
(void)SNC_CAN_SendCmdVel(0.0f, 0.0f, 0U);
}
wake_tick += period_ticks;
(void)osDelayUntil(wake_tick);
}
}
void AppTasks_RunMonitorTask(void *argument)
{
(void)argument;
uint32_t wake_tick = osKernelGetTickCount();
const uint32_t period_ticks = AppTasks_MsToTicks(100U);
for (;;) {
uint32_t now_ms = HAL_GetTick();
// 1. 执行 CAN 侧的周期性监控 (心跳/超时判断)
SNC_CAN_100msTask();
SNC_CAN_PollOnlineState(now_ms);
// 2. 获取 CAN 数据上下文
const SNC_CAN_AppContext_t *can_ctx = SNC_CAN_GetContext();
// 3. 将底盘的核心状态写入全局黑板
Blackboard_UpdateChassisState(can_ctx->status.state,
can_ctx->status.diag_bits,
can_ctx->status.online);
// 4. 里程计更新:从 CAN 0x200 累加器原子取走增量,积分并推送黑板
// 使用 SNC_CAN_ConsumeOdomDelta() 解决漏积分/重复积分问题:
// - ISR 侧每帧累加,不覆盖
// - 此处原子取走并清零,每份增量恰好消费一次
{
int16_t odom_fl, odom_rl, odom_fr, odom_rr;
uint32_t odom_span_ms;
uint8_t odom_frames = SNC_CAN_ConsumeOdomDelta(
&odom_fl, &odom_rl,
&odom_fr, &odom_rr,
&odom_span_ms);
if (odom_frames > 0U) {
/* 有新的增量帧需要积分 */
Odom_Update(now_ms,
odom_fl, odom_rl,
odom_fr, odom_rr,
odom_span_ms);
} else {
/* odom 断流保护:超过协议允许时间后主动清零黑板里的速度 */
Odom_HandleTimeout(now_ms, SNC_ODOM_TIMEOUT_MS);
}
}
/* 指令下发已由 navTask 接管,此处不再发送测试指令 */
// 调用纯净版播报员 (内部自带分频逻辑)
// App_PrintStatus();
wake_tick += period_ticks;
(void)osDelayUntil(wake_tick);
}
}
/* =========================================================
* 1. 前后激光雷达任务 (Laser Manager)
* ========================================================= */
void AppTasks_RunLaserTestTask_Impl(void *argument)
{
(void)argument;
// 初始化前后防撞雷达
LASER_SIMPLE_Init();
for (;;)
{
// 底层高频巡检
LASER_SIMPLE_Poll(HAL_GetTick());
// 获取无撕裂快照
const laser_simple_snapshot_t *snap = LASER_SIMPLE_GetSnapshot();
// 写入全局数据黑板
Blackboard_UpdateLaser(snap);
// 维持 50ms 巡检频率 (避障数据建议稍快一些)
osDelay(50);
}
}
/* =========================================================
* 2. IMU 姿态传感器任务 (HWT101)
* ========================================================= */
void AppTasks_RunImuTask_Impl(void *argument)
{
(void)argument;
// 初始化 IMU (开启 DMA 接收),使用 UART7
HWT101_Init(&huart7);
osDelay(100);
HWT101_ZeroYaw();
for (;;) {
// 高频解析 DMA 数据
HWT101_Process();
// 安全拷贝 IMU 数据并写入黑板
HWT101_Data_t imu_data;
HWT101_GetData(&imu_data);
Blackboard_UpdateIMU(&imu_data);
osDelay(10); // 10ms 解析与更新周期
}
}
/* =========================================================
* 3. 侧向阵列雷达任务 (VL53L0X 双总线)
* ========================================================= */
void AppTasks_RunVl53Task_Impl(void *argument)
{
(void)argument;
static Vl53Board_t left_board;
static Vl53Board_t right_board;
/* --- 配置左侧雷达 (I2C2) --- */
Vl53BoardHwCfg_t left_cfgs[2] = {
{&hi2c2, GPIOB, GPIO_PIN_1, 0x62, "LF", 0}, // 左前 (PB1)
{&hi2c2, GPIOC, GPIO_PIN_5, 0x64, "LR", 1} // 左后 (PC5)
};
// 【修改 1】测距预算从 robot_params.h 读取
Vl53Board_Init(&left_board, left_cfgs, 2, PARAM_VL53_TIMING_BUDGET);
Vl53Board_StartContinuous(&left_board);
/* --- 配置右侧雷达 (I2C1) --- */
Vl53BoardHwCfg_t right_cfgs[2] = {
{&hi2c1, GPIOD, GPIO_PIN_13, 0x56, "RF", 2}, // 右前 (PD13)
{&hi2c1, GPIOD, GPIO_PIN_14, 0x58, "RR", 3} // 右后 (PD14)
};
// 【修改 2】同样从 robot_params.h 读取
Vl53Board_Init(&right_board, right_cfgs, 2, PARAM_VL53_TIMING_BUDGET);
Vl53Board_StartContinuous(&right_board);
Vl53BoardSnapshot_t left_snap, right_snap, combined_snap;
for(;;) {
// 读取左右两侧的雷达快照
Vl53Board_ReadAll(&left_board, &left_snap);
Vl53Board_ReadAll(&right_board, &right_snap);
// 合并到一个统一的 Snapshot 中送给黑板
memset(&combined_snap, 0, sizeof(combined_snap));
combined_snap.tick_ms = HAL_GetTick();
// 映射约定:[0]左前,[1]左后,[2]右前,[3]右后
for(int i = 0; i < 2; i++) {
// 左侧复制到 [0], [1]
combined_snap.range_mm[i] = left_snap.range_mm[i];
combined_snap.range_mm_filtered[i] = left_snap.range_mm_filtered[i];
combined_snap.range_status[i] = left_snap.range_status[i];
// 右侧偏移 2 个身位,复制到 [2], [3]
combined_snap.range_mm[i+2] = right_snap.range_mm[i];
combined_snap.range_mm_filtered[i+2] = right_snap.range_mm_filtered[i];
combined_snap.range_status[i+2] = right_snap.range_status[i];
}
// 合并掩码 (右侧掩码左移 2 位)
combined_snap.valid_mask = (left_snap.valid_mask & 0x03) | ((right_snap.valid_mask & 0x03) << 2);
// 统一推送到黑板
Blackboard_UpdateVl53(&combined_snap);
// 【修改 3】休眠 100ms 匹配 VL53L0X 的新测距周期
osDelay(100);
}
}
/* =========================================================
* 4. 走廊导航控制任务 (Nav Pipeline)
* 周期20ms (50Hz),与 CAN 发送同频
* 流水线Obs → Filter → Ctrl → Script → FSM → CmdSlot_Push
* ========================================================= */
void AppTasks_RunNavTask_Impl(void *argument)
{
(void)argument;
uint32_t wake_tick = osKernelGetTickCount();
const uint32_t period_ticks = AppTasks_MsToTicks(20U);
uint32_t last_ms = HAL_GetTick();
/* 等传感器全部就绪再启动脚本 (避免刚上电全是脏数据) */
osDelay(500);
NavScript_Start(); // 开始执行比赛脚本
for (;;) {
uint32_t now_ms = HAL_GetTick();
float dt_s = (float)(now_ms - last_ms) / 1000.0f;
if (dt_s <= 0.0f || dt_s > 0.5f) {
dt_s = 0.02f; /* 容错:防止首拍或溢出 */
}
last_ms = now_ms;
/* --- Step 1: 拍摄黑板快照 --- */
RobotBlackboard_t board;
Blackboard_GetSnapshot(&board);
/* --- Step 2: 预处理 → 清洗观测 --- */
CorridorObs_t obs;
CorridorPreproc_ExtractObs(&board, now_ms, &obs);
/* --- Step 3: 互补滤波 → 走廊状态估计 --- */
/* 注意: HWT101 输出 wz 单位是 °/sEKF 需要 rad/s必须转换 */
float imu_wz_raw = board.imu_wz.is_valid ? board.imu_wz.value : 0.0f;
float imu_wz = PARAM_DEG2RAD(imu_wz_raw);
float odom_vx = board.odom_vx; /* 里程计已接入,由 monitorTask 调用 Odom_Update() 更新 */
/* IMU 连续 yaw → rad作为 EKF 额外航向观测 */
float imu_yaw_cont_rad = board.imu_yaw_continuous.is_valid
? PARAM_DEG2RAD(board.imu_yaw_continuous.value) : 0.0f;
bool imu_yaw_ok = board.imu_yaw_continuous.is_valid;
CorridorState_t corridor_state;
CorridorFilter_Update(&obs, imu_wz, odom_vx, dt_s,
imu_yaw_cont_rad, imu_yaw_ok, &corridor_state);
/* --- Step 4: 段脚本执行器 → 决定当前阶段和目标 --- */
NavScriptOutput_t script_out;
float imu_yaw_cont_deg = board.imu_yaw_continuous.is_valid
? board.imu_yaw_continuous.value : 0.0f;
NavScript_Update(&obs, &corridor_state, imu_yaw_cont_deg, &script_out);
/* --- Step 5: 控制律 → 计算期望 v, w --- */
RawCmd_t raw_cmd;
if (script_out.use_override) {
/* 脚本覆盖模式:直接用脚本的输出(入口对准/原地转向/退出等) */
raw_cmd.t_ms = now_ms;
raw_cmd.v = script_out.override_v;
raw_cmd.w = script_out.override_w;
raw_cmd.flags = 0U;
} else if (script_out.request_corridor) {
/* 走廊跟踪模式:使用走廊控制器 */
CorridorCtrl_Compute(&corridor_state, &obs, imu_wz, &raw_cmd);
} else {
/* 默认停车 */
raw_cmd.t_ms = now_ms;
raw_cmd.v = 0.0f;
raw_cmd.w = 0.0f;
raw_cmd.flags = 0U;
}
/* --- Step 6: 段状态机 → 安全仲裁 --- */
SegFsmOutput_t fsm_out;
SegFsm_Update(&raw_cmd, &obs, &corridor_state, &fsm_out);
/* --- Step 7: 将安全后的指令喂给 CAN 发送层 --- */
CmdSlot_Push(fsm_out.safe_v, fsm_out.safe_w, 0U);
wake_tick += period_ticks;
(void)osDelayUntil(wake_tick);
}
}
void AppTasks_Init(void)
{
SNC_CAN_AppInit();
Odom_Init();
/* --- 初始化走廊滤波器 (EKF) --- */
CorridorFilterConfig_t filter_cfg = {
.sensor_base_length = PARAM_SENSOR_BASE_LENGTH, /* 实测:同侧前后雷达间距 */
.corridor_width = PARAM_CORRIDOR_WIDTH, /* 实测:走廊宽度 */
.y_offset = 0.0f, /* 0 = 绝对居中 */
.side_sensor_inset = PARAM_VL53_SIDE_INSET, /* 实测:侧向传感器内缩距离 */
.robot_width = PARAM_ROBOT_WIDTH, /* 实测:车体宽度 */
.alpha_theta = 0.98f, /* 保留兼容EKF 内部使用 Q/R */
.alpha_y = 0.7f,
};
CorridorFilter_Init(&filter_cfg);
/* --- 初始化走廊控制器 --- */
CorridorCtrlConfig_t ctrl_cfg = {
.kp_theta = PARAM_CTRL_KP_THETA, /* 调优:航向比例增益 */
.kd_theta = PARAM_CTRL_KD_THETA, /* 调优:航向微分增益 */
.kp_y = PARAM_CTRL_KP_Y, /* 调优:横向比例增益 */
.v_cruise = PARAM_CTRL_V_CRUISE, /* 调优:巡航速度 */
.w_max = PARAM_CTRL_W_MAX, /* 角速度限幅 */
.v_max = PARAM_CTRL_V_MAX, /* 线速度限幅 */
.speed_reduction_k = PARAM_CTRL_SPEED_REDUCTION, /* 调优:弯道减速系数 */
};
CorridorCtrl_Init(&ctrl_cfg);
/* --- 初始化段状态机 --- */
SegFsmConfig_t fsm_cfg = {
.d_front_stop = PARAM_SAFE_D_FRONT_STOP, /* 安全:前向停车距离 */
.d_front_approach = PARAM_SAFE_D_FRONT_APPROACH, /* 安全:前向减速距离 */
.approach_min_v = PARAM_SAFE_APPROACH_MIN_V, /* 安全:减速区最低速度 */
.conf_estop_thresh = PARAM_SAFE_CONF_ESTOP, /* 安全E-Stop 置信度阈值 */
};
SegFsm_Init(&fsm_cfg);
SegFsm_Start(); /* P0 修复: 必须显式启动安全状态机,否则 IDLE 状态直接输出零速 */
/* --- 初始化段脚本执行器 --- */
NavScriptConfig_t script_cfg = {
.turn_target_angle = 3.14159265f, /* 固定180度转向 */
.turn_omega = PARAM_SCRIPT_TURN_OMEGA, /* 调优:转向角速度 */
.corridor_length = 3.0f, /* 备用:垄沟长度估计 */
.entry_align_timeout = PARAM_SCRIPT_ENTRY_TIMEOUT, /* 调优:入口对准超时 */
.d_entry_exit_front = 0.10f, /* 调优:出入口距离阈值 */
.entry_align_v = PARAM_SCRIPT_ENTRY_V, /* 调优:入口对准速度 */
.exit_runout_m = PARAM_SCRIPT_EXIT_RUNOUT, /* 调优:退出后冲出距离 */
.exit_v = PARAM_SCRIPT_EXIT_V, /* P1 修复:退出直线速度独立参数 */
};
NavScript_Init(&script_cfg);
}

33
App/app_tasks.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef APP_TASKS_H
#define APP_TASKS_H
#include "cmsis_os2.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/* =========================================================
* 启动接力标志位定义 (按 Bit 划分)
* ========================================================= */
#define INIT_FLAG_CAN_READY (1UL << 0) // Bit 0: CAN 握手完成
#define INIT_FLAG_IMU_READY (1UL << 1) // Bit 1: IMU 初始化完成
#define INIT_FLAG_VL53_READY (1UL << 2) // Bit 2: 侧向雷达初始化完成
#define INIT_FLAG_LASER_READY (1UL << 3) // Bit 3: 防撞雷达初始化完成
/* 全局事件组句柄声明 */
extern osEventFlagsId_t g_init_events;
void AppTasks_RunCanTxTask(void *argument);
void AppTasks_RunMonitorTask(void *argument);
/* 三个核心传感器采集与黑板更新任务 */
void AppTasks_RunImuTask_Impl(void *argument);
void AppTasks_RunLaserTestTask_Impl(void *argument);
void AppTasks_RunVl53Task_Impl(void *argument);
void AppTasks_RunNavTask_Impl(void *argument);
void AppTasks_Init(void);
#ifdef __cplusplus
}
#endif
#endif /* APP_TASKS_H */

806
App/est/corridor_ekf.c Normal file
View File

@@ -0,0 +1,806 @@
/**
* @file corridor_ekf.c
* @brief 鲁棒 EKF 走廊相对定位滤波器实现
*
* 完整算法流程:
*
* 【预测步】Predict(vx, wz, dt)
* x_pred = f(x, u) -- 非线性状态转移
* P_pred = F * P * F^T + Q -- 协方差预测
*
* 【更新步】Update(obs)
* z = h(x_pred) -- 观测预测
* y = z_meas - z -- 新息 (Innovation)
* S = H * P_pred * H^T + R -- 新息协方差
* d² = y^T * S^(-1) * y -- 马氏距离平方
* if d² > χ²_threshold: 拒绝观测 (鲁棒)
* K = P_pred * H^T * S^(-1) -- 卡尔曼增益
* x = x_pred + K * y -- 状态更新
* P = (I - K * H) * P_pred -- 协方差更新
*/
#include "corridor_ekf.h"
#include <math.h>
#include <string.h>
/* =========================================================
* 内部静态状态
* ========================================================= */
static CorridorEKFConfig_t s_cfg;
static CorridorEKFState_t s_state;
static bool s_initialized = false;
static uint32_t s_last_update_ms = 0U;
/* 协方差上界保护阈值 */
#define P_MAX_DIAG 100.0f
/* =========================================================
* 内部辅助函数
* ========================================================= */
/** 限幅 */
static inline float clampf(float val, float lo, float hi)
{
if (val < lo) return lo;
if (val > hi) return hi;
return val;
}
/** 对称矩阵拷贝 + 上三角 symmetrize */
static void symmetrize(float M[3][3])
{
M[1][0] = M[0][1];
M[2][0] = M[0][2];
M[2][1] = M[1][2];
}
/** P 上界保护 */
static void protect_P(float P[3][3])
{
for (int i = 0; i < 3; i++) {
if (P[i][i] > P_MAX_DIAG) P[i][i] = P_MAX_DIAG;
if (P[i][i] < 0.0f) P[i][i] = 0.0f;
}
}
/** 计算 2x2 对称矩阵的逆 (原地) */
static bool invert_2x2_sym(float S[2][2])
{
float det = S[0][0] * S[1][1] - S[0][1] * S[1][0];
if (fabsf(det) < 1e-8f) {
return false; // 奇异矩阵
}
float inv_det = 1.0f / det;
float S00 = S[0][0];
S[0][0] = inv_det * S[1][1];
S[1][1] = inv_det * S00;
S[0][1] = -inv_det * S[0][1];
S[1][0] = S[0][1];
return true;
}
/** 2x2 对称矩阵求逆 (原地) */
static bool invert_3x3_cholesky(float S[3][3])
{
// 使用 Cholesky 分解求逆
float L[3][3] = {0};
for (int i = 0; i < 3; i++) {
for (int j = 0; j <= i; j++) {
float sum = S[i][j];
for (int k = 0; k < j; k++) {
sum -= L[i][k] * L[j][k];
}
if (i == j) {
if (sum <= 0.0f) return false;
L[i][j] = sqrtf(sum);
} else {
L[i][j] = sum / L[j][j];
}
}
}
// 求逆: S_inv = L^(-T) * L^(-1)
float Linv[3][3] = {0};
for (int i = 0; i < 3; i++) {
Linv[i][i] = 1.0f / L[i][i];
for (int j = i - 1; j >= 0; j--) {
float sum = 0.0f;
for (int k = j + 1; k <= i; k++) {
sum += L[k][j] * Linv[k][i];
}
Linv[j][i] = -sum / L[j][j];
}
}
// S_inv = Linv^T * Linv
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
float sum = 0.0f;
for (int k = 0; k < 3; k++) {
sum += Linv[k][i] * Linv[k][j];
}
S[i][j] = sum;
}
}
return true;
}
/** 计算马氏距离平方 (新息向量 y, 新息协方差 S_inv) */
static float mahalanobis_d2_3dof(const float y[3], const float S_inv[3][3])
{
// d² = y^T * S_inv * y
float tmp[3] = {0};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
tmp[i] += S_inv[i][j] * y[j];
}
}
float d2 = 0.0f;
for (int i = 0; i < 3; i++) {
d2 += y[i] * tmp[i];
}
return d2;
}
/** 计算马氏距离平方 (1DOF: 只用 e_y) */
static float mahalanobis_d2_1dof(float y_ey, float S_inv_00)
{
return y_ey * y_ey * S_inv_00;
}
/** 计算马氏距离平方 (2DOF: e_ey + e_th_avg) */
static float mahalanobis_d2_2dof(const float y[2], const float S_inv[2][2])
{
float tmp[2] = {0};
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
tmp[i] += S_inv[i][j] * y[j];
}
}
float d2 = 0.0f;
for (int i = 0; i < 2; i++) {
d2 += y[i] * tmp[i];
}
return d2;
}
/** 零矩阵 */
static void zero_3x3(float M[3][3])
{
memset(M, 0, sizeof(float) * 9);
}
/** 单位矩阵 */
static void eye_3x3(float M[3][3])
{
zero_3x3(M);
M[0][0] = M[1][1] = M[2][2] = 1.0f;
}
/* =========================================================
* API 实现
* ========================================================= */
void CorridorEKF_Init(const CorridorEKFConfig_t *config)
{
s_cfg = *config;
memset(&s_state, 0, sizeof(s_state));
/* 初始化状态 */
s_state.x[0] = 0.0f; // e_y
s_state.x[1] = 0.0f; // e_th
s_state.x[2] = 0.0f; // s
/* 初始化协方差 */
eye_3x3(s_state.P);
s_state.P[0][0] = config->P0_diag[0];
s_state.P[1][1] = config->P0_diag[1];
s_state.P[2][2] = config->P0_diag[2];
s_initialized = true;
}
void CorridorEKF_Reset(void)
{
if (!s_initialized) return;
s_state.x[0] = 0.0f;
s_state.x[1] = 0.0f;
s_state.x[2] = 0.0f;
eye_3x3(s_state.P);
s_state.P[0][0] = s_cfg.P0_diag[0];
s_state.P[1][1] = s_cfg.P0_diag[1];
s_state.P[2][2] = s_cfg.P0_diag[2];
s_last_update_ms = 0U;
}
void CorridorEKF_SetProcessNoise(float q_ey, float q_eth, float q_s)
{
s_cfg.q_ey = q_ey;
s_cfg.q_eth = q_eth;
s_cfg.q_s = q_s;
}
void CorridorEKF_SetMeasurementNoise(float r_ey, float r_eth)
{
s_cfg.r_ey = r_ey;
s_cfg.r_eth = r_eth;
}
/* =========================================================
* 预测步 (Predict)
* ========================================================= */
void CorridorEKF_Predict(float odom_vx, float imu_wz, float dt)
{
if (!s_initialized || dt <= 0.0f) return;
float e_y = s_state.x[0];
float e_th = s_state.x[1];
float s = s_state.x[2];
float vx = odom_vx;
float wz = imu_wz;
/* 状态预测: x_pred = f(x, u) */
float cos_th = cosf(e_th);
float sin_th = sinf(e_th);
/* 安全检查: cos_th 不能太小 (防止数值爆炸) */
if (fabsf(cos_th) < 0.01f) cos_th = (cos_th >= 0.0f) ? 0.01f : -0.01f;
float e_y_pred = e_y + vx * sin_th * dt;
float e_th_pred = e_th + wz * dt;
float s_pred = s + vx * cos_th * dt;
s_state.x[0] = e_y_pred;
s_state.x[1] = e_th_pred;
s_state.x[2] = s_pred;
/* 雅可比矩阵 F (状态转移的 Jacobian) */
float F[3][3] = {0};
F[0][0] = 1.0f;
F[0][1] = vx * cos_th * dt; // de_y/de_th
F[0][2] = 0.0f;
F[1][0] = 0.0f;
F[1][1] = 1.0f;
F[1][2] = 0.0f;
F[2][0] = 0.0f;
F[2][1] = -vx * sin_th * dt; // ds/de_th
F[2][2] = 1.0f;
/* 过程噪声协方差 Q (对角) */
float Q[3][3] = {0};
Q[0][0] = s_cfg.q_ey * dt * dt;
Q[1][1] = s_cfg.q_eth * dt * dt;
Q[2][2] = s_cfg.q_s * dt * dt;
/* 协方差预测: P_pred = F * P * F^T + Q */
float F_P[3][3] = {0};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
F_P[i][j] += F[i][k] * s_state.P[k][j];
}
}
}
float P_pred[3][3] = {0};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
P_pred[i][j] += F_P[i][k] * F[j][k]; // F^T: F[j][k] = F[k][j]
}
}
P_pred[i][i] += Q[i][i]; // 加过程噪声
}
symmetrize(P_pred);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
s_state.P[i][j] = P_pred[i][j];
}
}
protect_P(s_state.P);
}
/* =========================================================
* 观测步 (Update) - 鲁棒 EKF
* ========================================================= */
int CorridorEKF_Update(const CorridorObs_t *obs, CorridorState_t *out_state)
{
if (!s_initialized) return 0;
int updated_obs_count = 0;
/* 清除新息和拒绝掩码 */
memset(s_state.K, 0, sizeof(s_state.K));
uint8_t reject_mask = 0U;
float max_maha_d2 = 0.0f;
/* ----------------------------------------------------
* 提取有效观测
* ---------------------------------------------------- */
bool left_ok = ((obs->valid_mask & (1U << 0)) != 0U) &&
((obs->valid_mask & (1U << 1)) != 0U);
bool right_ok = ((obs->valid_mask & (1U << 2)) != 0U) &&
((obs->valid_mask & (1U << 3)) != 0U);
/* 左右侧横向平均距离 */
float d_lf = obs->d_lf, d_lr = obs->d_lr;
float d_rf = obs->d_rf, d_rr = obs->d_rr;
float Ls = s_cfg.sensor_base_length;
float W = s_cfg.corridor_width;
float yoff = s_cfg.y_offset;
float inset = s_cfg.side_sensor_inset;
float Rw = s_cfg.robot_width;
/* 传感器居中时的理论读数 (考虑车体宽度和传感器内缩)
*
* 推导 (以左侧为例)
* 沟道宽 W车体宽 Rw传感器内缩 inset
* 居中时:
* 车体左边缘到左墙 = (W - Rw) / 2
* 传感器到左墙 = (W - Rw) / 2 + inset (传感器比边缘更靠内)
*
* 所以 d_center = (W - Rw) / 2 + inset
*
* 验证W=0.40, Rw=0.20, inset=0
* d_center = (0.40-0.20)/2 + 0 = 0.10m ✓ (每边余量10cm)
*
* 单侧公式e_y = d_center - d_left (左侧传感器越近墙,偏差越大)
* 双侧公式e_y = [(d_center - d_left) + (d_right - d_center)] / 2
* = (d_right - d_left) / 2 (d_center 被消掉)
*
* ⚠ 当 inset = 0 且 Rw = 0 时d_center = W/2退化回原始行为
*/
float d_center = (W - Rw) / 2.0f + inset; /* 传感器居中时的理论读数 */
/* 观测值 (测量) */
float z_ey = 0.0f;
float z_eth_L = 0.0f;
float z_eth_R = 0.0f;
int valid_sides = 0;
if (left_ok) {
z_ey += d_center - ((d_lf + d_lr) / 2.0f) - yoff;
z_eth_L = atan2f(d_lr - d_lf, Ls);
valid_sides++;
}
if (right_ok) {
z_ey += ((d_rf + d_rr) / 2.0f) - d_center - yoff;
z_eth_R = atan2f(d_rf - d_rr, Ls);
valid_sides++;
}
if (valid_sides == 0) {
/* 两边都失效: 协方差持续膨胀,输出预测值 */
out_state->t_ms = obs->t_ms;
out_state->e_y = s_state.x[0];
out_state->e_th = s_state.x[1];
out_state->s = s_state.x[2];
out_state->conf = clampf(1.0f - (s_state.P[0][0] + s_state.P[1][1]) * 0.1f, 0.0f, 1.0f);
out_state->obs_reject_mask = 0xFF;
out_state->mahalanobis_d2 = 0.0f;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
out_state->P[i][j] = s_state.P[i][j];
}
}
/* 协方差膨胀 (无观测时的信任衰减) */
s_state.P[0][0] += s_cfg.q_ey * 5.0f;
s_state.P[1][1] += s_cfg.q_eth * 5.0f;
protect_P(s_state.P);
return 0;
}
/* 横向观测: 两侧平均 */
if (valid_sides == 2) {
z_ey /= 2.0f;
}
/* ----------------------------------------------------
* 构建观测向量 z 和预测观测 h(x)
* ---------------------------------------------------- */
float e_y = s_state.x[0];
float e_th = s_state.x[1];
/* 预测观测 h(x) */
float h_ey = e_y; // 横向: z_ey ≈ e_y
float h_eth_L = e_th; // 左侧航向: z_eth_L ≈ e_th
float h_eth_R = e_th; // 右侧航向: z_eth_R ≈ e_th
/* 新息向量 y = z - h(x) */
float y[3] = {0};
int obs_idx = 0;
/* e_y 观测 */
y[obs_idx++] = z_ey - h_ey;
/* e_th_L 观测 */
if (left_ok) y[obs_idx++] = z_eth_L - h_eth_L;
/* e_th_R 观测 */
if (right_ok) y[obs_idx++] = z_eth_R - h_eth_R;
/* ----------------------------------------------------
* 构建 H 矩阵 (Jacobian of h(x))
* ---------------------------------------------------- */
/* H 布局:
* 航向角观测对应列是 1,0,0 (e_y 观测量)
* 航向角观测对应列是 0,1,0 (e_th 观测量)
* s 不被直接观测
*/
float H[3][3] = {0};
int H_row = 0;
/* e_y 行: H = [1, 0, 0] */
H[H_row][0] = 1.0f; H[H_row][1] = 0.0f; H[H_row][2] = 0.0f;
H_row++;
/* e_th_L 行: H = [0, 1, 0] */
if (left_ok) {
H[H_row][0] = 0.0f; H[H_row][1] = 1.0f; H[H_row][2] = 0.0f;
H_row++;
}
/* e_th_R 行: H = [0, 1, 0] */
if (right_ok) {
H[H_row][0] = 0.0f; H[H_row][1] = 1.0f; H[H_row][2] = 0.0f;
H_row++;
}
int obs_count = H_row;
/* ----------------------------------------------------
* 构建观测噪声协方差 R (根据有效侧数量调整)
* ---------------------------------------------------- */
float R[3][3] = {0};
R[0][0] = s_cfg.r_ey; // e_y 的噪声
if (left_ok && right_ok) {
/* 双侧: 航向噪声更小 (两个独立观测平均) */
R[1][1] = s_cfg.r_eth * 0.5f; // e_th_L
R[2][2] = s_cfg.r_eth * 0.5f; // e_th_R
} else {
/* 单侧: 航向噪声较大 */
if (left_ok) {
R[1][1] = s_cfg.r_eth;
}
if (right_ok) {
R[1][1] = s_cfg.r_eth;
}
}
/* ----------------------------------------------------
* 计算新息协方差 S = H * P * H^T + R
* ---------------------------------------------------- */
float HP[3][3] = {0};
for (int i = 0; i < obs_count; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
HP[i][j] += H[i][k] * s_state.P[k][j];
}
}
}
float S[3][3] = {0};
for (int i = 0; i < obs_count; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
S[i][j] += HP[i][k] * H[j][k]; // H^T: H[j][k] = H[k][j]
}
}
S[i][i] += R[i][i]; // 加观测噪声
}
/* ----------------------------------------------------
* 计算 S 的逆
* ---------------------------------------------------- */
float S_inv[3][3] = {0};
if (obs_count == 1) {
/* 1 观测: 标量 */
if (fabsf(S[0][0]) < 1e-8f) {
goto output_result;
}
S_inv[0][0] = 1.0f / S[0][0];
} else if (obs_count == 2) {
/* 2 观测2x2 - 拷贝到局部矩阵 */
float S_2x2[2][2];
S_2x2[0][0] = S[0][0]; S_2x2[0][1] = S[0][1];
S_2x2[1][0] = S[1][0]; S_2x2[1][1] = S[1][1];
if (!invert_2x2_sym(S_2x2)) {
goto output_result;
}
/* 拷贝回 S_inv */
S_inv[0][0] = S_2x2[0][0]; S_inv[0][1] = S_2x2[0][1];
S_inv[1][0] = S_2x2[1][0]; S_inv[1][1] = S_2x2[1][1];
} else {
/* 3 观测: 3x3 */
memcpy(S_inv, S, sizeof(float) * 9);
if (!invert_3x3_cholesky(S_inv)) {
goto output_result;
}
}
/* ----------------------------------------------------
* χ² 马氏距离检验 (鲁棒拒绝)
* ---------------------------------------------------- */
float d2_total = 0.0f;
if (obs_count == 1) {
d2_total = mahalanobis_d2_1dof(y[0], S_inv[0][0]);
} else if (obs_count == 2) {
d2_total = mahalanobis_d2_2dof(y, (const float (*)[2])S_inv);
} else {
d2_total = mahalanobis_d2_3dof(y, S_inv);
}
max_maha_d2 = d2_total;
/* 单自由度检验: e_y 单独检验 */
float d2_ey = mahalanobis_d2_1dof(y[0], S_inv[0][0]);
if (d2_ey > s_cfg.chi2_1dof) {
reject_mask |= (1U << 0); // 拒绝 e_y
}
/* 1 DOF 门限约 3.84 (95%), 约 6.63 (99%) */
/* 如果整体 d² 过大,拒绝最可疑的观测 */
if (obs_count >= 2) {
/* 检验 e_th_L */
if (left_ok && !(reject_mask & (1U << 0))) {
/* 需要重新计算不含 e_y 的马氏距离 */
/* 简化: 用 y[1]^2 / S[1][1] 作为 1DOF 近似 */
if (fabsf(S[1][1]) > 1e-8f) {
float d2_eth_L = y[1] * y[1] / S[1][1];
if (d2_eth_L > s_cfg.chi2_1dof) {
reject_mask |= (1U << 1); // 拒绝 e_th_L
}
}
}
/* 检验 e_th_R */
if (right_ok && !(reject_mask & (1U << 0)) && obs_count >= 3) {
if (fabsf(S[2][2]) > 1e-8f) {
float d2_eth_R = y[2] * y[2] / S[2][2];
if (d2_eth_R > s_cfg.chi2_1dof) {
reject_mask |= (1U << 2); // 拒绝 e_th_R
}
}
}
}
/* ----------------------------------------------------
* 计算卡尔曼增益 K = P * H^T * S^(-1)
* P1 修复: 必须做完整矩阵乘法 (P*H^T) * S_inv
* 而不能只乘 S_inv 的对角项 S_inv[j][j]。
* 后者会忽略 S 的非对角元素(观测间相关性),
* 导致卡尔曼增益不正确,影响滤波收敛性。
* ---------------------------------------------------- */
float HT[3][3] = {0};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < obs_count; j++) {
HT[i][j] = H[j][i]; // H^T
}
}
/* Step 1: PH^T = P * H^T, 结果为 3×obs_count */
float PHT[3][3] = {0};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < obs_count; j++) {
for (int k = 0; k < 3; k++) {
PHT[i][j] += s_state.P[i][k] * HT[k][j];
}
}
}
/* Step 2: K = PHT * S_inv, 结果为 3×obs_count */
float K[3][3] = {0};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < obs_count; j++) {
for (int k = 0; k < obs_count; k++) {
K[i][j] += PHT[i][k] * S_inv[k][j];
}
}
}
/* ----------------------------------------------------
* 跳过被拒绝的观测,更新剩余观测
* ---------------------------------------------------- */
int used_obs = 0;
for (int i = 0; i < obs_count; i++) {
uint8_t bit = (i == 0) ? (1U << 0) : ((i == 1) ? (1U << 1) : (1U << 2));
if (reject_mask & bit) {
/*
* 关键:被拒绝的观测不仅不能更新状态,
* 也不能参与后续 KH/P 更新,否则会错误收缩协方差。
*/
K[0][i] = 0.0f;
K[1][i] = 0.0f;
K[2][i] = 0.0f;
continue;
}
/* 状态更新: x += K[:, i] * y[i] */
s_state.x[0] += K[0][i] * y[i];
s_state.x[1] += K[1][i] * y[i];
s_state.x[2] += K[2][i] * y[i];
used_obs++;
}
/* ----------------------------------------------------
* 协方差更新: P = (I - K * H) * P_pred
* 简化 Joseph 形式: P = (I - K*H) * P * (I - K*H)^T + K * R * K^T
* 这里使用简化形式: P = (I - K*H) * P
* ---------------------------------------------------- */
float KH[3][3] = {0};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < obs_count; k++) {
KH[i][j] += K[i][k] * H[k][j];
}
}
}
float I_KH[3][3];
I_KH[0][0] = 1.0f - KH[0][0]; I_KH[0][1] = -KH[0][1]; I_KH[0][2] = -KH[0][2];
I_KH[1][0] = -KH[1][0]; I_KH[1][1] = 1.0f - KH[1][1]; I_KH[1][2] = -KH[1][2];
I_KH[2][0] = -KH[2][0]; I_KH[2][1] = -KH[2][1]; I_KH[2][2] = 1.0f - KH[2][2];
float P_tmp[3][3] = {0};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
P_tmp[i][j] += I_KH[i][k] * s_state.P[k][j];
}
}
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
s_state.P[i][j] = P_tmp[i][j];
}
}
symmetrize(s_state.P);
protect_P(s_state.P);
updated_obs_count = used_obs;
output_result:
/* ----------------------------------------------------
* 填充输出
* ---------------------------------------------------- */
out_state->t_ms = obs->t_ms;
out_state->e_y = s_state.x[0];
out_state->e_th = s_state.x[1];
out_state->s = s_state.x[2];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
out_state->P[i][j] = s_state.P[i][j];
}
}
out_state->mahalanobis_d2 = max_maha_d2;
out_state->obs_reject_mask = reject_mask;
/* 置信度: 基于协方差迹和拒绝比例 */
float P_trace = s_state.P[0][0] + s_state.P[1][1] + s_state.P[2][2];
float conf_from_P = clampf(1.0f - P_trace * 0.5f, 0.0f, 1.0f);
/* 根据有效侧数加权 */
float side_factor = (valid_sides == 2) ? 1.0f : 0.7f;
/* 根据拒绝比例降低置信度 */
float reject_ratio = 0.0f;
if (obs_count > 0) {
int rejected = 0;
if (reject_mask & (1U << 0)) rejected++;
if (reject_mask & (1U << 1)) rejected++;
if (reject_mask & (1U << 2)) rejected++;
reject_ratio = (float)rejected / (float)obs_count;
}
out_state->conf = clampf(conf_from_P * side_factor * (1.0f - reject_ratio * 0.5f), 0.0f, 1.0f);
return updated_obs_count;
}
/* =========================================================
* 辅助 API
* ========================================================= */
/* =========================================================
* IMU 航向观测更新 (独立 1DOF 标量 EKF 更新)
*
* 观测方程: z_eth_imu = imu_yaw_rad - imu_yaw_ref_rad
* 对应状态: e_th (x[1])
* H = [0, 1, 0] (只观测 e_th)
*
* 设计意图:
* - IMU 内部维护的 yaw 经过模块校准,比外部积分 wz 更稳定
* - 在侧墙观测丢失 (转弯/单侧退化) 时提供航向约束
* - 使用较大 R 值,让侧墙观测在有效时主导
* ========================================================= */
void CorridorEKF_UpdateIMUYaw(float imu_yaw_rad, float imu_yaw_ref_rad, bool valid)
{
if (!s_initialized || !valid) return;
/* 观测值: IMU 相对于走廊参考方向的航向偏差 */
float z_eth_imu = imu_yaw_rad - imu_yaw_ref_rad;
/* 新息: y = z - h(x), h(x) = e_th = x[1] */
float y_imu = z_eth_imu - s_state.x[1];
/* H = [0, 1, 0] → S = P[1][1] + R_imu */
float R_imu = s_cfg.r_eth_imu;
float S_imu = s_state.P[1][1] + R_imu;
if (fabsf(S_imu) < 1e-8f) return;
/* χ² 1DOF 检验: d² = y² / S */
float d2_imu = y_imu * y_imu / S_imu;
if (d2_imu > s_cfg.chi2_1dof) return; /* 拒绝异常观测 */
/* 卡尔曼增益: K = P * H^T / S = P[:][1] / S */
float K[3];
float S_inv = 1.0f / S_imu;
K[0] = s_state.P[0][1] * S_inv;
K[1] = s_state.P[1][1] * S_inv;
K[2] = s_state.P[2][1] * S_inv;
/* 状态更新: x += K * y */
s_state.x[0] += K[0] * y_imu;
s_state.x[1] += K[1] * y_imu;
s_state.x[2] += K[2] * y_imu;
/* 协方差更新: P = (I - K*H) * P
* H = [0, 1, 0], 所以 KH[i][j] = K[i] * H[j] = K[i] * δ(j,1) */
float P_new[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
P_new[i][j] = s_state.P[i][j] - K[i] * s_state.P[1][j];
}
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
s_state.P[i][j] = P_new[i][j];
}
}
symmetrize(s_state.P);
protect_P(s_state.P);
}
void CorridorEKF_GetState(CorridorState_t *out)
{
if (!s_initialized || out == NULL) return;
out->t_ms = s_last_update_ms;
out->e_y = s_state.x[0];
out->e_th = s_state.x[1];
out->s = s_state.x[2];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
out->P[i][j] = s_state.P[i][j];
}
}
out->mahalanobis_d2 = 0.0f;
out->obs_reject_mask = 0U;
float P_trace = s_state.P[0][0] + s_state.P[1][1] + s_state.P[2][2];
out->conf = clampf(1.0f - P_trace * 0.5f, 0.0f, 1.0f);
}

137
App/est/corridor_ekf.h Normal file
View File

@@ -0,0 +1,137 @@
/**
* @file corridor_ekf.h
* @brief 鲁棒 EKF 走廊相对定位滤波器
*
* 状态向量x = [e_y, e_th, s]^T
* - e_y : 横向偏差 (m)
* - e_th : 航向偏差 (rad)
* - s : 沿走廊进度 (m)
*
* 观测向量z = [z_ey, z_eth_L, z_eth_R]^T
* - z_ey : 横向偏差观测 (由左右侧平均距离差计算)
* - z_eth_L: 左侧航向观测 (atan2((d_lr-d_lf), L_s))
* - z_eth_R: 右侧航向观测 (atan2((d_rf-d_rr), L_s))
*
* 鲁棒机制:
* - χ² 马氏距离检验拒绝异常观测
* - 自适应观测噪声 (根据传感器健康度调整 R 矩阵)
* - 协方差上界保护 (防止发散)
*/
#ifndef CORRIDOR_EKF_H
#define CORRIDOR_EKF_H
#include <stdint.h>
#include <stdbool.h>
/* 先引入消息定义 (含 EKF_STATE_DIM/EKF_OBS_DIM 宏) */
#include "preproc/corridor_msgs.h"
#ifdef __cplusplus
extern "C" {
#endif
/* =========================================================
* EKF 配置参数
* ========================================================= */
typedef struct {
/* 过程噪声协方差 Q */
float q_ey; // e_y 过程噪声方差
float q_eth; // e_th 过程噪声方差
float q_s; // s 过程噪声方差
/* 观测噪声协方差 R */
float r_ey; // 横向观测噪声方差 (侧墙)
float r_eth; // 航向观测噪声方差 (侧墙)
float r_eth_imu; // 航向观测噪声方差 (IMU yaw),建议远大于 r_eth
/* 初始协方差 */
float P0_diag[3]; // 初始 P 对角线
/* χ² 检验门限 */
float chi2_1dof; // 1 自由度门限 (默认 3.84)
float chi2_2dof; // 2 自由度门限 (默认 5.99)
/* 走廊几何参数 */
float sensor_base_length; // 同侧前后雷达间距 L_s
float corridor_width; // 走廊标准宽度
float y_offset; // 期望偏置
float side_sensor_inset; // VL53L0X 侧向传感器内缩距离 (传感器面到车体外边缘)
float robot_width; // 车体外轮廓宽度 (用于单侧退化时的精确定位)
} CorridorEKFConfig_t;
/* =========================================================
* EKF 内部状态
* ========================================================= */
typedef struct {
float x[EKF_STATE_DIM]; // 状态向量
float P[EKF_STATE_DIM][EKF_STATE_DIM]; // 状态协方差
float K[EKF_STATE_DIM][EKF_OBS_DIM]; // 卡尔曼增益
float S[EKF_OBS_DIM][EKF_OBS_DIM]; // 新息协方差
float S_inv[EKF_OBS_DIM][EKF_OBS_DIM]; // S 的逆
} CorridorEKFState_t;
/* =========================================================
* API 接口
* ========================================================= */
/**
* @brief 初始化 EKF 滤波器
* @param config 配置参数
*/
void CorridorEKF_Init(const CorridorEKFConfig_t *config);
/**
* @brief EKF 预测步 (时间更新)
* @param odom_vx 里程计线速度 (m/s)
* @param imu_wz IMU 角速度 (rad/s)
* @param dt 时间间隔 (s)
*/
void CorridorEKF_Predict(float odom_vx, float imu_wz, float dt);
/**
* @brief EKF 观测步 (测量更新) - 鲁棒版本
* @param obs 预处理后的观测快照
* @param out_state 输出状态 (含马氏距离、拒绝掩码等)
* @return 成功更新的观测数
*/
int CorridorEKF_Update(const CorridorObs_t *obs, CorridorState_t *out_state);
/**
* @brief EKF IMU 航向观测更新 (独立于侧墙观测,在 Update 后调用)
*
* 将 IMU 连续 yaw 的变化量作为 e_th 的额外标量观测,执行 1DOF EKF 更新。
* 在侧墙观测丢失时 (转弯/单侧退化) 提供航向约束,防止 e_th 漂移。
*
* @param imu_yaw_rad IMU 连续 yaw 当前值 (rad)
* @param imu_yaw_ref_rad 进入走廊时锁定的 IMU yaw 参考值 (rad)
* z_eth_imu = imu_yaw_rad - imu_yaw_ref_rad
* @param valid IMU 数据是否有效
*/
void CorridorEKF_UpdateIMUYaw(float imu_yaw_rad, float imu_yaw_ref_rad, bool valid);
/**
* @brief 获取当前状态估计
*/
void CorridorEKF_GetState(CorridorState_t *out);
/**
* @brief 重置 EKF 状态
*/
void CorridorEKF_Reset(void);
/**
* @brief 设置过程噪声 (运行时可调)
*/
void CorridorEKF_SetProcessNoise(float q_ey, float q_eth, float q_s);
/**
* @brief 设置观测噪声 (运行时可调,用于自适应)
*/
void CorridorEKF_SetMeasurementNoise(float r_ey, float r_eth);
#ifdef __cplusplus
}
#endif
#endif /* CORRIDOR_EKF_H */

108
App/est/corridor_filter.c Normal file
View File

@@ -0,0 +1,108 @@
/**
* @file corridor_filter.c
* @brief 走廊相对定位滤波器 - 鲁棒 EKF 实现
*
* 本文件是对外统一接口层,内部调用 corridor_ekf 模块
* 保持与原有互补滤波接口兼容,方便无缝替换
*/
#include "corridor_filter.h"
#include "corridor_ekf.h"
#include "preproc/corridor_msgs.h" /* 引入 CHI2_THRESHOLD 宏 */
#include "robot_params.h" /* 引入 PARAM_EKF_* 宏 */
#include <math.h>
#include <string.h>
/* =========================================================
* 兼容层配置
* ========================================================= */
static CorridorFilterConfig_t s_cfg;
static bool s_initialized = false;
/* IMU yaw 参考值管理:进入走廊时锁定,用于计算相对走廊方向的航向偏差 */
static float s_imu_yaw_ref_rad = 0.0f; // 走廊参考 yaw (rad)
static bool s_imu_yaw_ref_set = false; // 参考值是否已锁定
/* =========================================================
* 初始化
* ========================================================= */
void CorridorFilter_Init(const CorridorFilterConfig_t *config)
{
s_cfg = *config;
/* 转换为 EKF 配置 */
CorridorEKFConfig_t ekf_cfg;
memset(&ekf_cfg, 0, sizeof(ekf_cfg));
/* 走廊几何参数 */
ekf_cfg.sensor_base_length = config->sensor_base_length;
ekf_cfg.corridor_width = config->corridor_width;
ekf_cfg.y_offset = config->y_offset;
ekf_cfg.side_sensor_inset = config->side_sensor_inset;
ekf_cfg.robot_width = config->robot_width;
/* 过程噪声 Q —— 统一从 robot_params.h 读取,改参数只改那一个文件 */
ekf_cfg.q_ey = PARAM_EKF_Q_EY; /* 横向过程噪声 */
ekf_cfg.q_eth = PARAM_EKF_Q_ETH; /* 航向过程噪声 */
ekf_cfg.q_s = PARAM_EKF_Q_S; /* 里程过程噪声 */
/* 观测噪声 R */
ekf_cfg.r_ey = PARAM_EKF_R_EY; /* 横向观测噪声 (侧墙) */
ekf_cfg.r_eth = PARAM_EKF_R_ETH; /* 航向观测噪声 (侧墙) */
ekf_cfg.r_eth_imu = PARAM_EKF_R_ETH_IMU; /* 航向观测噪声 (IMU yaw),较大 */
/* 初始协方差 */
ekf_cfg.P0_diag[0] = PARAM_EKF_P0_EY; /* e_y 初始不确定度 */
ekf_cfg.P0_diag[1] = PARAM_EKF_P0_ETH; /* e_th 初始不确定度 */
ekf_cfg.P0_diag[2] = 0.0f; /* s 初始确定(已知从 0 出发) */
/* χ² 门限 */
ekf_cfg.chi2_1dof = PARAM_CHI2_1DOF;
ekf_cfg.chi2_2dof = PARAM_CHI2_2DOF;
CorridorEKF_Init(&ekf_cfg);
s_initialized = true;
}
/* =========================================================
* 核心更新函数
* ========================================================= */
void CorridorFilter_Update(const CorridorObs_t *obs, float imu_wz, float odom_vx,
float dt_s, float imu_yaw_continuous_rad, bool imu_yaw_valid,
CorridorState_t *out_state)
{
if (!s_initialized || dt_s <= 0.0f) {
return;
}
/* 预测步 */
CorridorEKF_Predict(odom_vx, imu_wz, dt_s);
/* 侧墙观测更新步 (含马氏距离异常检测) */
CorridorEKF_Update(obs, out_state);
/* ---- IMU yaw 航向观测更新 ---- *
* 在侧墙观测之后独立执行 1DOF 标量更新。
*
* 参考值管理策略:
* 首次收到有效 IMU yaw 且 EKF 置信度足够时锁定参考值。
* 此时 e_th ≈ 0 (刚被侧墙观测修正过)
* 所以 yaw_ref = imu_yaw_current → z_eth_imu = 0
* 后续 yaw 的变化量就等于 e_th 的变化量。
*/
if (imu_yaw_valid) {
if (!s_imu_yaw_ref_set && out_state->conf >= 0.5f) {
/* 首次锁定:此刻 e_th 已被侧墙修正到接近 0 */
s_imu_yaw_ref_rad = imu_yaw_continuous_rad - out_state->e_th;
s_imu_yaw_ref_set = true;
}
if (s_imu_yaw_ref_set) {
CorridorEKF_UpdateIMUYaw(imu_yaw_continuous_rad, s_imu_yaw_ref_rad, true);
/* 更新输出 (IMU 观测可能微调了 e_th) */
CorridorEKF_GetState(out_state);
out_state->t_ms = obs->t_ms;
}
}
}

46
App/est/corridor_filter.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef CORRIDOR_FILTER_H
#define CORRIDOR_FILTER_H
#include "preproc/corridor_preproc.h"
#include "preproc/corridor_msgs.h"
/* 滤波器配置参数结构体 */
typedef struct {
float sensor_base_length; // 同侧前后雷达的纵向安装间距 L_s (m)
float corridor_width; // 走廊标准宽度 (m),比赛规则为 0.4m
float y_offset; // 期望的偏置行走量 (m)0 表示绝对居中
float side_sensor_inset; // VL53L0X 传感器内缩距离 (传感器面到车体外边缘) (m)
float robot_width; // 车体外轮廓宽度 (m)
float alpha_theta; // 航向互补滤波系数 (0~1)
// 【注】因为您的IMU极好此值建议设为 0.98~0.995
float alpha_y; // 横向低通滤波系数 (0~1),建议设为 0.6~0.8 防止地毯颠簸
} CorridorFilterConfig_t;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief 初始化走廊滤波器
* @param config 滤波器调参配置
*/
void CorridorFilter_Init(const CorridorFilterConfig_t *config);
/**
* @brief 核心函数:执行一次走廊状态估计 (建议与 CAN 发送同频,如 50Hz/20ms运行)
* @param obs 预处理模块输出的、清洗干净的雷达观测快照
* @param imu_wz 当前的 IMU Z轴角速度 (rad/s),左转为正
* @param odom_vx 底盘反馈的当前里程计线速度 (m/s)
* @param dt_s 距离上一次调用的时间间隔 (s)
* @param imu_yaw_continuous_rad IMU unwrap 后的连续偏航角 (rad)
* @param imu_yaw_valid IMU 数据是否有效
* @param out_state 输出平滑后的 e_y (横向误差), e_th (航向误差) 和健康度
*/
void CorridorFilter_Update(const CorridorObs_t *obs, float imu_wz, float odom_vx,
float dt_s, float imu_yaw_continuous_rad, bool imu_yaw_valid,
CorridorState_t *out_state);
#ifdef __cplusplus
}
#endif
#endif // CORRIDOR_FILTER_H

175
App/laser/Laser Manager.md Normal file
View File

@@ -0,0 +1,175 @@
激光雷达管理模块 (Laser Manager) 🚀
===========================
本模块专为 **STM32H7 + FreeRTOS** 环境打造,用于同时驱动和解析 4 路单点激光雷达2 路连续流 STP-23L2 路文本流 ATK-MS53L1M
采用 **DMA 环形缓冲 + 串口空闲中断 (IDLE) + RTOS 事件驱动** 架构,彻底消灭单字节中断引起的 CPU 拥堵,是适用于机器人底盘避障与路径规划的“企业级”底层驱动。
✨ 核心特性
------
1. **零中断阻塞**:所有数据均由硬件 DMA 搬运CPU 仅在数据接收过半/完成或触发 IDLE 空闲时被唤醒。
2. **免 Cache 物理隔离**:基于 MPU 划分专用 `.dma_buffer` 特区,彻底杜绝 Cortex-M7 的 Cache 一致性导致的数据乱码或 USB 掉线问题。
3. **极速解析算法**
* **STP 协议**:采用 O(1) 环形指针流式提取,**0 内存搬运 (`memmove`)**。
* **ATK 协议**:采用 O(1) 字符特征匹配,彻底抛弃耗时的 `strstr``strtol` 标准库函数。
4. **高质量数据输出**:内置 **滑动中值滤波 (Median Filter)**,有效剔除玻璃反光、灰尘引起的突发测距尖峰,提供平滑稳定的控制级数据。
5. **安全可靠**
* 采用 `taskENTER_CRITICAL()` 保护快照读取,杜绝多线程数据撕裂。
* 严格区分中断上下文 (`FROM_ISR`) 与任务上下文的临界区调用。
* 内置 `HAL_UART_ErrorCallback`,在遭受电磁干扰触发 ORE/FE 错误时自动重启 DMA永久防死机。
* * *
⚙️ 移植与配置指南
----------
### 第一步STM32CubeMX 硬件配置
1. **MPU 设置 (极其重要)**
* 进入 `Cortex-M7` -> `MPU Control`
* Enable MPU
* **Region 1**: Base Address = **`0x30000000`**, Size = **`32KB`**
* Access Permission: **`ALL ACCESS PERMITTED`**
* Cacheable: **`Disable`** (彻底关闭该区域的 D-Cache)
2. **串口与 DMA 设置**
* **STP 雷达** (如 USART2, UART4 - 230400bps):添加 RX DMA模式选 **`Circular`** (数据宽度 Byte)。优先级建议设为 **`High`**。
* **ATK 雷达** (如 USART3, USART6 - 115200bps):添加 RX DMA模式选 **`Circular`**。优先级设为 **`Medium`**。
* **NVIC**:必须开启这 4 个串口的**全局中断 (Global Interrupt)**。
### 第二步:链接脚本 (.ld) 配置
打开工程的链接脚本(如 `STM32H743XX_FLASH.ld`),在 `RAM_D2` 区域添加 `.dma_buffer` 段定义:
代码段
/* 给雷达 DMA 专门划分的免 Cache 区域 */
.dma_buffer (NOLOAD) :
{
. = ALIGN(32);
*(.dma_buffer)
*(.dma_buffer*)
. = ALIGN(32);
} >RAM_D2
### 第三步:中断回调接管
确保在 `usart.c``main.c`**删除或注释掉** 旧的串口接收回调,因为 `laser_manager.c` 底部已经重写了以下函数并接管了整个链路:
* `HAL_UART_RxCpltCallback`
* `HAL_UART_RxHalfCpltCallback`
* `HAL_UARTEx_RxEventCallback` (用于处理 IDLE)
* `HAL_UART_ErrorCallback` (用于自动恢复错误)
* * *
💻 API 使用说明
-----------
### 1. 数据结构概览
C
typedef struct {
uint16_t distance_mm; // 经过中值滤波处理后平滑的距离值 (推荐用于避障控制)
uint16_t raw_distance_mm; // 传感器吐出的原始跳动距离值 (仅供调试观察)
uint8_t valid; // 数据是否有效 (1:有效, 0:无效)
uint8_t online; // 雷达是否在线 (未超时)
uint8_t fault_code; // 故障码 (0x00:正常, 0x80:掉线超时)
uint32_t update_tick_ms; // 最后一次数据刷新的系统 tick
} laser_simple_data_t;
### 2. 初始化与任务启动
在 FreeRTOS 调度器启动前(或统一的应用初始化任务中)调用初始化接口。它会自动配置并开启 DMA同时创建一个高优先级的解析守护任务。
C
#include "laser/laser_manager.h"
// 在 main.c 或 app_tasks.c 初始化阶段调用
LASER_SIMPLE_Init();
### 3. 数据轮询与读取 (应用层)
在你的应用周期任务中(如 `100ms` 测试任务或控制任务),调用 `Poll` 并获取快照指针:
C
void AppTasks_RunLaserTestTask_Impl(void *argument)
{
const laser_simple_snapshot_t *snap;
uint32_t print_divider = 0;
LASER_SIMPLE_Init();
for(;;)
{
// 1. 触发状态机巡检 (更新在线状态/超时)
LASER_SIMPLE_Poll(HAL_GetTick());
// 2. 获取绝对安全、无撕裂的全局数据快照
snap = LASER_SIMPLE_GetSnapshot();
// 3. 降频打印 (例如每 500ms 打印一次)
if (++print_divider >= 5)
{
print_divider = 0;
printf("F_STP [Filter:%4umm, Raw:%4umm] Valid:%d Fault:%02X\r\n",
snap->ch[LASER_CH_FRONT_STP].distance_mm,
snap->ch[LASER_CH_FRONT_STP].raw_distance_mm,
snap->ch[LASER_CH_FRONT_STP].valid,
snap->ch[LASER_CH_FRONT_STP].fault_code);
}
osDelay(100); // 维持高频巡检节拍 (切勿大于雷达设定的 Timeout 时间)
}
}
### 4. 便捷测距接口
如果你的小车只需要知道“前方/后方离障碍物最近是多少”,可以直接调用辅助接口:
C
// 获取前/后两路雷达中,最近且有效的平滑距离值 (毫米)
uint16_t front_min_dist = LASER_SIMPLE_GetFrontNearest();
uint16_t rear_min_dist = LASER_SIMPLE_GetRearNearest();
* * *
❓ 常见问题 (Troubleshooting)
------------------------
**Q: 烧录程序后USB 虚拟串口无法识别 (或电脑提示无法识别的 USB 设备)**
> **A:** 请检查 MPU 配置是否生效,以及链接脚本中是否正确加入了 `.dma_buffer`。如果 DMA 数组被编译器分配到了带有 D-Cache 的内存中USB 外设会因为内存一致性冲突而死机。
**Q: 雷达数据一直是 0且终端不停输出 FaultCode `0x80`**
> **A:** `0x80` 代表超时掉线。请检查:
>
> 1. 雷达硬件连线RX/TX 是否接反)。
>
> 2. `CubeMX` 中 4 个串口是否正确开启了**全局中断**(未开启中断将无法唤醒解析任务)。
>
> 3. 波特率是否匹配STP: `230400`ATK: `115200`)。
**Q: 想要调整中值滤波的平滑程度?**
> **A:** 在 `laser_manager.c` 顶部修改 `#define FILTER_WIN_SZ 3U`。改为 `5U` 会更平滑,但会增加几毫秒的系统响应延迟。通常 `3` 是最佳平衡点。

317
App/laser/laser_manager.c Normal file
View File

@@ -0,0 +1,317 @@
#include "laser_manager.h"
#include <string.h>
#include "cmsis_os2.h"
#include "FreeRTOS.h"
#include "task.h"
/* --- 配置区 --- */
#define STP_TIMEOUT_MS 200U
#define ATK_TIMEOUT_MS 500U
#define FILTER_WIN_SZ 3U // 中值滤波窗口大小(推荐 3 或 5
#define FAULT_NONE 0x00
#define FAULT_STP_CHECKSUM 0x41
#define FAULT_STP_FRAME 0x42
#define FAULT_TIMEOUT 0x80
/* MPU 无 Cache 段宏定义 */
#if defined(__GNUC__)
#define LASER_DMA_RAM __attribute__((section(".dma_buffer"))) __attribute__((aligned(32)))
#else
#define LASER_DMA_RAM
#endif
/* 缓冲区大小 */
#define STP_DMA_SZ 512U
#define ATK_DMA_SZ 256U
/* 分配在无 Cache 区域的 DMA 内存 */
static LASER_DMA_RAM uint8_t g_stp_front_dma[STP_DMA_SZ];
static LASER_DMA_RAM uint8_t g_atk_front_dma[ATK_DMA_SZ];
static LASER_DMA_RAM uint8_t g_stp_rear_dma[STP_DMA_SZ];
static LASER_DMA_RAM uint8_t g_atk_rear_dma[ATK_DMA_SZ];
/* 数据节点与快照 */
typedef struct {
UART_HandleTypeDef *huart;
uint8_t *dma_buf;
uint16_t dma_sz;
uint16_t read_ptr;
uint32_t last_tick;
// 滤波队列缓存
uint16_t dist_history[FILTER_WIN_SZ];
uint8_t hist_idx;
uint8_t hist_cnt;
laser_simple_data_t data;
} laser_node_t;
static laser_node_t g_nodes[LASER_CH_MAX] = {
[LASER_CH_FRONT_STP] = { &huart2, g_stp_front_dma, STP_DMA_SZ, 0, 0, {0}, 0, 0, {0} },
[LASER_CH_FRONT_ATK] = { &huart3, g_atk_front_dma, ATK_DMA_SZ, 0, 0, {0}, 0, 0, {0} },
[LASER_CH_REAR_STP] = { &huart4, g_stp_rear_dma, STP_DMA_SZ, 0, 0, {0}, 0, 0, {0} },
[LASER_CH_REAR_ATK] = { &huart6, g_atk_rear_dma, ATK_DMA_SZ, 0, 0, {0}, 0, 0, {0} }
};
static laser_simple_snapshot_t g_snapshot;
static osThreadId_t laserTaskHandle;
/* --- 辅助宏与函数 --- */
#define READ_RING(buf, sz, pos, offset) (buf[((pos) + (offset)) % (sz)])
static uint16_t le16_read(const uint8_t *p) { return (uint16_t)(p[0] | (p[1] << 8)); }
static uint16_t apply_median_filter(laser_node_t *n, uint16_t new_val) {
n->dist_history[n->hist_idx] = new_val;
n->hist_idx = (n->hist_idx + 1) % FILTER_WIN_SZ;
if (n->hist_cnt < FILTER_WIN_SZ) n->hist_cnt++;
uint16_t temp[FILTER_WIN_SZ];
for (int i = 0; i < n->hist_cnt; i++) temp[i] = n->dist_history[i];
for (int i = 0; i < n->hist_cnt - 1; i++) {
for (int j = i + 1; j < n->hist_cnt; j++) {
if (temp[i] > temp[j]) {
uint16_t t = temp[i]; temp[i] = temp[j]; temp[j] = t;
}
}
}
return temp[n->hist_cnt / 2];
}
/* --- STP 环形无 memmove 解析 (保持不变) --- */
static void process_stp(laser_channel_t ch) {
laser_node_t *n = &g_nodes[ch];
uint16_t write_ptr = n->dma_sz - __HAL_DMA_GET_COUNTER(n->huart->hdmarx);
uint16_t available = (write_ptr - n->read_ptr + n->dma_sz) % n->dma_sz;
while (available >= 11U) {
uint16_t head = 0xFFFF;
for (uint16_t i = 0; i <= available - 4; i++) {
if (READ_RING(n->dma_buf, n->dma_sz, n->read_ptr, i) == 0xAA &&
READ_RING(n->dma_buf, n->dma_sz, n->read_ptr, i+1) == 0xAA &&
READ_RING(n->dma_buf, n->dma_sz, n->read_ptr, i+2) == 0xAA &&
READ_RING(n->dma_buf, n->dma_sz, n->read_ptr, i+3) == 0xAA) {
head = i; break;
}
}
if (head == 0xFFFF) {
n->read_ptr = (n->read_ptr + available - 3) % n->dma_sz;
break;
}
n->read_ptr = (n->read_ptr + head) % n->dma_sz;
available -= head;
if (available < 11) break;
uint8_t data_len = READ_RING(n->dma_buf, n->dma_sz, n->read_ptr, 8);
uint16_t frame_len = 10 + data_len + 1;
if (data_len > 200) { n->read_ptr = (n->read_ptr + 1) % n->dma_sz; available--; continue; }
if (available < frame_len) break;
uint8_t frame[256];
uint32_t sum = 0;
for (uint16_t i = 0; i < frame_len; i++) {
frame[i] = READ_RING(n->dma_buf, n->dma_sz, n->read_ptr, i);
if (i >= 4 && i < frame_len - 1) sum += frame[i];
}
if ((sum & 0xFF) == frame[frame_len - 1] && frame[5] == 0x02 && data_len == 0xB8) {
uint32_t p = 10;
uint16_t best = 0xFFFF;
for (int i = 0; i < 12; i++) {
int16_t dist = le16_read(&frame[p]); p += 8;
uint8_t conf = frame[p]; p += 7;
if (dist >= 70 && dist <= 7500 && conf >= 1 && dist < best) best = dist;
}
taskENTER_CRITICAL();
if (best != 0xFFFF) {
n->data.raw_distance_mm = best;
n->data.distance_mm = apply_median_filter(n, best);
n->data.valid = 1;
n->data.fault_code = 0;
} else {
n->data.valid = 0;
}
n->last_tick = HAL_GetTick();
taskEXIT_CRITICAL();
}
n->read_ptr = (n->read_ptr + frame_len) % n->dma_sz;
available -= frame_len;
}
}
/* --- 【全新】ATK 环形滑动窗口解析 (无视断帧与粘包) --- */
static void process_atk(laser_channel_t ch) {
laser_node_t *n = &g_nodes[ch];
uint16_t write_ptr = n->dma_sz - __HAL_DMA_GET_COUNTER(n->huart->hdmarx);
uint16_t available = (write_ptr - n->read_ptr + n->dma_sz) % n->dma_sz;
// ATK 哪怕报故障,最小长度也有类似 "State:1\r\n" 约 9 字节
while (available >= 5) {
char c0 = (char)READ_RING(n->dma_buf, n->dma_sz, n->read_ptr, 0);
char c1 = (char)READ_RING(n->dma_buf, n->dma_sz, n->read_ptr, 1);
// 匹配帧头 "d:" 或 "St" (State的开头)
if ((c0 == 'd' && c1 == ':') || (c0 == 'S' && c1 == 't')) {
// 寻找帧尾 '\n'
uint16_t lf_pos = 0xFFFF;
for (uint16_t i = 0; i < available; i++) {
if (READ_RING(n->dma_buf, n->dma_sz, n->read_ptr, i) == '\n') {
lf_pos = i;
break;
}
}
// 如果没找到换行符,说明这帧 DMA 还没搬运完,立刻退出等下次任务周期
if (lf_pos == 0xFFFF) {
break;
}
uint16_t frame_len = lf_pos + 1;
char line[64] = {0};
for (uint16_t i = 0; i < frame_len && i < sizeof(line) - 1; i++) {
line[i] = READ_RING(n->dma_buf, n->dma_sz, n->read_ptr, i);
}
taskENTER_CRITICAL();
if (line[0] == 'S' && line[1] == 't') {
int state_val = line[6] - '0';
if (state_val >= 0 && state_val <= 9) {
n->data.fault_code = state_val;
if (state_val != 0) n->data.valid = 0;
n->last_tick = HAL_GetTick();
}
}
else if (line[0] == 'd' && line[1] == ':') {
int dist_val = 0;
const char *p = &line[2];
while (*p == ' ') p++;
while (*p >= '0' && *p <= '9') {
dist_val = dist_val * 10 + (*p - '0');
p++;
}
if (dist_val > 0 && n->data.fault_code == 0) {
n->data.raw_distance_mm = dist_val;
n->data.distance_mm = apply_median_filter(n, dist_val);
n->data.valid = 1;
} else {
n->data.valid = 0;
}
n->last_tick = HAL_GetTick();
}
taskEXIT_CRITICAL();
// 成功解析一帧,滑动读取指针
n->read_ptr = (n->read_ptr + frame_len) % n->dma_sz;
available -= frame_len;
} else {
// 没找到帧头,说明有垃圾数据,把指针往后挪 1 字节继续找
n->read_ptr = (n->read_ptr + 1) % n->dma_sz;
available--;
}
}
}
/* --- 核心 RTOS 任务 (全轮询模式) --- */
static void LaserTask(void *arg) {
(void)arg;
for(;;) {
// 【架构升级】:不再死等中断标志,而是以 10ms 的心跳主动去 DMA 缓冲区提货。
// 50Hz 等于 20ms 来一帧10ms 巡视一次性能富裕且绝不漏包。
osDelay(10);
uint32_t now = HAL_GetTick();
// 纯 DMA 内存操作,极快
process_stp(LASER_CH_FRONT_STP);
process_stp(LASER_CH_REAR_STP);
process_atk(LASER_CH_FRONT_ATK);
process_atk(LASER_CH_REAR_ATK);
// 统一心跳/超时/快照检查
for (int i = 0; i < LASER_CH_MAX; i++) {
uint32_t timeout = (i == LASER_CH_FRONT_STP || i == LASER_CH_REAR_STP) ? STP_TIMEOUT_MS : ATK_TIMEOUT_MS;
taskENTER_CRITICAL();
if (now - g_nodes[i].last_tick > timeout) {
g_nodes[i].data.online = 0;
g_nodes[i].data.valid = 0;
g_nodes[i].data.fault_code = FAULT_TIMEOUT;
g_nodes[i].hist_cnt = 0; // 掉线时清空历史滤波数组
} else {
g_nodes[i].data.online = 1;
g_nodes[i].data.update_tick_ms = g_nodes[i].last_tick;
}
g_snapshot.ch[i] = g_nodes[i].data;
taskEXIT_CRITICAL();
}
}
}
/* --- API 接口 --- */
void LASER_SIMPLE_Init(void) {
memset(&g_snapshot, 0, sizeof(g_snapshot));
// 【重要变更】:全员使用普通循环 DMA彻底抛弃 IDLE 接收
HAL_UART_Receive_DMA(g_nodes[LASER_CH_FRONT_STP].huart, g_nodes[LASER_CH_FRONT_STP].dma_buf, STP_DMA_SZ);
HAL_UART_Receive_DMA(g_nodes[LASER_CH_REAR_STP].huart, g_nodes[LASER_CH_REAR_STP].dma_buf, STP_DMA_SZ);
HAL_UART_Receive_DMA(g_nodes[LASER_CH_FRONT_ATK].huart, g_nodes[LASER_CH_FRONT_ATK].dma_buf, ATK_DMA_SZ);
HAL_UART_Receive_DMA(g_nodes[LASER_CH_REAR_ATK].huart, g_nodes[LASER_CH_REAR_ATK].dma_buf, ATK_DMA_SZ);
osThreadAttr_t attr = { .name = "LaserTsk", .stack_size = 1024 * 4, .priority = osPriorityAboveNormal };
laserTaskHandle = osThreadNew(LaserTask, NULL, &attr);
}
void LASER_SIMPLE_Poll(uint32_t tick_ms) {
(void)tick_ms;
}
const laser_simple_snapshot_t *LASER_SIMPLE_GetSnapshot(void) {
return &g_snapshot;
}
static uint16_t nearest_of_two(const laser_simple_data_t *a, const laser_simple_data_t *b) {
if (a->online && a->valid && b->online && b->valid) {
return (a->distance_mm < b->distance_mm) ? a->distance_mm : b->distance_mm;
}
if (a->online && a->valid) return a->distance_mm;
if (b->online && b->valid) return b->distance_mm;
return 0U;
}
uint16_t LASER_SIMPLE_GetFrontNearest(void) {
return nearest_of_two(&g_snapshot.ch[LASER_CH_FRONT_STP], &g_snapshot.ch[LASER_CH_FRONT_ATK]);
}
uint16_t LASER_SIMPLE_GetRearNearest(void) {
return nearest_of_two(&g_snapshot.ch[LASER_CH_REAR_STP], &g_snapshot.ch[LASER_CH_REAR_ATK]);
}
/* --- 中断桥接 (已大幅瘦身,仅保留错误恢复) --- */
// 因为改为轮询模式,不再需要依赖这几个正常接收的中断了。保留空函数防止外部调用报错。
void LASER_UART_RxCpltCallback(UART_HandleTypeDef *huart) { (void)huart; }
void LASER_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) { (void)huart; }
void LASER_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { (void)huart; (void)Size; }
// 错误自动恢复保留,这是底层硬件 ORE 报错时重启 DMA 必需的
void LASER_UART_ErrorRecovery(UART_HandleTypeDef *huart) {
for (int i=0; i<LASER_CH_MAX; i++) {
if (g_nodes[i].huart == huart) {
HAL_UART_DMAStop(huart);
// 统一恢复为普通 DMA 接收
if (i == LASER_CH_FRONT_STP || i == LASER_CH_REAR_STP)
HAL_UART_Receive_DMA(huart, g_nodes[i].dma_buf, STP_DMA_SZ);
else
HAL_UART_Receive_DMA(huart, g_nodes[i].dma_buf, ATK_DMA_SZ);
}
}
}

53
App/laser/laser_manager.h Normal file
View File

@@ -0,0 +1,53 @@
#ifndef __LASER_SIMPLE_H
#define __LASER_SIMPLE_H
#include <stdint.h>
#include "usart.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
LASER_CH_FRONT_STP = 0,
LASER_CH_FRONT_ATK,
LASER_CH_REAR_STP,
LASER_CH_REAR_ATK,
LASER_CH_MAX
} laser_channel_t;
typedef struct {
uint16_t distance_mm; // [新增] 经过中值滤波处理后平滑的距离值 (推荐用于避障控制)
uint16_t raw_distance_mm; // [新增] 传感器吐出的原始距离值 (供调试或特殊算法读取)
uint8_t valid; // 数据是否有效
uint8_t online; // 雷达是否在线(未超时)
uint8_t fault_code; // 故障码 (0为正常0x80为超时)
uint32_t update_tick_ms; // 最后一次数据刷新的系统节拍
} laser_simple_data_t;
typedef struct {
laser_simple_data_t ch[LASER_CH_MAX];
} laser_simple_snapshot_t;
/* 初始化并启动 DMA 及解析任务 */
void LASER_SIMPLE_Init(void);
/* 周期调用 (实际为空,保留接口兼容) */
void LASER_SIMPLE_Poll(uint32_t tick_ms);
/* 获取统一快照 (无数据撕裂风险) */
const laser_simple_snapshot_t *LASER_SIMPLE_GetSnapshot(void);
/* 获取前后最小有效距离 (使用滤波后的值) */
uint16_t LASER_SIMPLE_GetFrontNearest(void);
uint16_t LASER_SIMPLE_GetRearNearest(void);
/* --- 新增:暴露给全局回调分发器的专用接口 --- */
void LASER_UART_RxCpltCallback(UART_HandleTypeDef *huart);
void LASER_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);
void LASER_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size);
void LASER_UART_ErrorRecovery(UART_HandleTypeDef *huart);
#ifdef __cplusplus
}
#endif
#endif

83
App/nav/corridor_ctrl.c Normal file
View File

@@ -0,0 +1,83 @@
#include "corridor_ctrl.h"
#include <math.h>
#include <stdbool.h>
/* ====================== 内部状态 ====================== */
static CorridorCtrlConfig_t s_cfg;
static bool s_initialized = false;
/* 辅助:浮点数限幅 */
static inline float clampf(float val, float lo, float hi)
{
if (val < lo) return lo;
if (val > hi) return hi;
return val;
}
void CorridorCtrl_Init(const CorridorCtrlConfig_t *config)
{
s_cfg = *config;
s_initialized = true;
}
void CorridorCtrl_Compute(const CorridorState_t *state,
const CorridorObs_t *obs,
float imu_wz,
RawCmd_t *out_cmd)
{
if (!s_initialized) {
out_cmd->v = 0.0f;
out_cmd->w = 0.0f;
out_cmd->flags = 0U;
return;
}
/* ========================================================
* 核心控制律:
* w_cmd = kp_theta * e_th + kd_theta * (-imu_wz) + kp_y * e_y
*
* - kp_theta * e_th : 比例项,车头偏了就回转
* - kd_theta * (-imu_wz) : 微分阻尼,等价于"阻止车头继续转"
* 用 IMU 直接读数做微分项,比差分 e_th 更丝滑无噪声
* - kp_y * e_y : 横向纠偏,车身偏了就产生角速度拉回来
* ======================================================== */
float w_cmd = s_cfg.kp_theta * state->e_th
+ s_cfg.kd_theta * (-imu_wz)
+ s_cfg.kp_y * state->e_y;
/* 角速度限幅:防止 PD 溢出导致原地打转 */
w_cmd = clampf(w_cmd, -s_cfg.w_max, s_cfg.w_max);
/* ========================================================
* 线速度策略:
* 基础巡航速度 v_cruise
* 当角速度偏大时适当降速(弯道减速),保持运动学协调
* 公式: v = v_cruise * (1 - k * |w/w_max|)
* k 取 0.3~0.5 较保守
* ======================================================== */
float speed_reduction = s_cfg.speed_reduction_k * fabsf(w_cmd) / s_cfg.w_max;
float v_cmd = s_cfg.v_cruise * (1.0f - speed_reduction);
/* 线速度限幅:不允许倒车,不允许超速 */
v_cmd = clampf(v_cmd, 0.0f, s_cfg.v_max);
/* ========================================================
* 置信度降级保护:
* 当滤波器健康度 conf 过低(两边雷达全瞎),
* 说明走廊参照完全丢失,降低线速度防止盲飞
* ======================================================== */
if (state->conf < 0.3f) {
/* 健康度极低:速度打三折,保持航向惯性滑行 */
v_cmd *= 0.3f;
} else if (state->conf < 0.6f) {
/* 健康度较低(单侧退化):速度打七折 */
v_cmd *= 0.7f;
}
/* 输出赋值 */
out_cmd->t_ms = state->t_ms;
out_cmd->v = v_cmd;
out_cmd->w = w_cmd;
out_cmd->flags = 0U;
}

47
App/nav/corridor_ctrl.h Normal file
View File

@@ -0,0 +1,47 @@
#ifndef CORRIDOR_CTRL_H
#define CORRIDOR_CTRL_H
#include "preproc/corridor_msgs.h"
/**
* @brief 走廊控制器调参配置
* @note 所有增益参数都应在调试阶段"从小往大调",防止震荡
*/
typedef struct {
float kp_theta; // 航向偏差比例增益 (rad/s per rad)
float kd_theta; // 航向偏差微分增益 (rad/s per rad/s) [阻尼项]
float kp_y; // 横向偏差比例增益 (rad/s per m)
float v_cruise; // 走廊内巡航线速度 (m/s)
float w_max; // 角速度输出硬限幅 (rad/s),超过此值一律削峰
float v_max; // 线速度输出硬限幅 (m/s)
float speed_reduction_k; // 弯道减速系数 (0~1),公式: v = v_cruise*(1-k*|w/w_max|)
} CorridorCtrlConfig_t;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief 初始化走廊控制器
* @param config 控制器增益与限幅配置
*/
void CorridorCtrl_Init(const CorridorCtrlConfig_t *config);
/**
* @brief 核心函数:根据滤波器输出的走廊状态计算控制量
* @param state 滤波器输出的走廊状态 (e_y, e_th, conf)
* @param obs 预处理层的观测快照 (用于获取 d_front 等辅助信息)
* @param imu_wz 当前的 IMU Z轴角速度 (rad/s),用于微分阻尼
* @param out_cmd 输出的控制指令 (v, w)
*/
void CorridorCtrl_Compute(const CorridorState_t *state,
const CorridorObs_t *obs,
float imu_wz,
RawCmd_t *out_cmd);
#ifdef __cplusplus
}
#endif
#endif // CORRIDOR_CTRL_H

322
App/nav/nav_script.c Normal file
View File

@@ -0,0 +1,322 @@
/**
* @file nav_script.c
* @brief 段脚本执行器实现:编排完整比赛流程
*/
#include "nav_script.h"
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#include <string.h>
/* =========================================================
* 内部状态
* ========================================================= */
static NavScriptConfig_t s_cfg;
static NavScriptStage_t s_stage = SCRIPT_STAGE_IDLE;
static bool s_initialized = false;
static bool s_running = false;
/* 阶段内部状态变量 */
static struct {
uint32_t entry_align_start_ms; // 入口对准开始时间
float turn_start_e_th; // 转向开始时的 EKF 航向 (保留作后备)
float turn_start_imu_yaw_deg; // 转向开始时的 IMU 连续偏航角 (deg)
bool turn_started; // 转向是否已开始
float corridor_s_entry; // 进入垄沟时的 s 里程
int pass_count; // 已走过的垄沟数
float exit_start_s; // 离开垄沟瞬间的 s 里程 (0=未触发)
} s_internal;
/* =========================================================
* 内部辅助函数
* ========================================================= */
static inline float clampf(float val, float lo, float hi)
{
if (val < lo) return lo;
if (val > hi) return hi;
return val;
}
/* =========================================================
* API 实现
* ========================================================= */
void NavScript_Init(const NavScriptConfig_t *config)
{
s_cfg = *config;
s_stage = SCRIPT_STAGE_IDLE;
s_running = false;
s_initialized = true;
/* 初始化内部状态 */
memset(&s_internal, 0, sizeof(s_internal));
}
void NavScript_Start(void)
{
if (s_initialized) {
s_stage = SCRIPT_STAGE_ENTRY_ALIGN;
s_running = true;
s_internal.entry_align_start_ms = 0;
s_internal.pass_count = 0;
}
}
NavScriptStage_t NavScript_GetStage(void)
{
return s_stage;
}
const char* NavScript_GetStageName(NavScriptStage_t stage)
{
switch (stage) {
case SCRIPT_STAGE_IDLE: return "IDLE";
case SCRIPT_STAGE_ENTRY_ALIGN: return "ENTRY_ALIGN";
case SCRIPT_STAGE_CORRIDOR_FORWARD: return "CORRIDOR_FWD";
case SCRIPT_STAGE_TURN_AT_END: return "TURN_AT_END";
case SCRIPT_STAGE_CORRIDOR_BACKWARD: return "CORRIDOR_BWD";
case SCRIPT_STAGE_EXIT: return "EXIT";
case SCRIPT_STAGE_FINISHED: return "FINISHED";
default: return "UNKNOWN";
}
}
void NavScript_Reset(void)
{
s_stage = SCRIPT_STAGE_IDLE;
s_running = false;
memset(&s_internal, 0, sizeof(s_internal));
}
void NavScript_Update(const CorridorObs_t *obs,
const CorridorState_t *state,
float imu_yaw_continuous_deg,
NavScriptOutput_t *out)
{
if (!s_initialized) {
out->stage = SCRIPT_STAGE_IDLE;
out->stage_name = "IDLE";
out->active = false;
out->request_corridor = false;
out->override_v = 0.0f;
out->override_w = 0.0f;
out->use_override = true;
return;
}
/* 默认输出 */
out->stage = s_stage;
out->stage_name = NavScript_GetStageName(s_stage);
out->active = s_running;
out->request_corridor = true; // 默认请求走廊控制器
out->use_override = false; // 默认不覆盖
if (!s_running) {
out->request_corridor = false;
out->override_v = 0.0f;
out->override_w = 0.0f;
out->use_override = true;
return;
}
/* ========================================================
* 核心状态机:按比赛流程执行
* ======================================================== */
switch (s_stage) {
/* ==============================================
* STAGE 1: 入口对准
* ============================================== */
case SCRIPT_STAGE_ENTRY_ALIGN: {
if (s_internal.entry_align_start_ms == 0) {
s_internal.entry_align_start_ms = state->t_ms;
}
/* 检查是否已进入垄沟:两侧都有距离数据 */
bool left_ok = ((obs->valid_mask & CORRIDOR_OBS_MASK_LF) != 0U) &&
((obs->valid_mask & CORRIDOR_OBS_MASK_LR) != 0U);
bool right_ok = ((obs->valid_mask & CORRIDOR_OBS_MASK_RF) != 0U) &&
((obs->valid_mask & CORRIDOR_OBS_MASK_RR) != 0U);
if (left_ok && right_ok && state->conf >= 0.8f) {
/* 两侧雷达都有数据,且置信度高 -> 进入垄沟,开始跟踪 */
s_internal.corridor_s_entry = state->s;
s_internal.pass_count = 1;
s_stage = SCRIPT_STAGE_CORRIDOR_FORWARD;
out->request_corridor = true;
} else {
/* 入口对准策略:慢速前进,让侧向雷达找墙 */
out->override_v = s_cfg.entry_align_v; // 慢速前进 (由 PARAM_SCRIPT_ENTRY_V 配置)
out->override_w = 0.0f;
out->use_override = true;
out->request_corridor = false;
/* P1 修复: 超时保护使用配置参数 s_cfg.entry_align_timeout
* 而非硬编码 30000 ms */
uint32_t elapsed = state->t_ms - s_internal.entry_align_start_ms;
if (elapsed > (uint32_t)s_cfg.entry_align_timeout) {
/* 超时强制进入走廊跟踪:必须补齐与正常入沟一致的内部状态,
* 否则 pass_count 停留在 0导致后续 TURN_AT_END 判定时
* 多跑一趟走廊(三趟而非文档描述的两趟)。 */
s_internal.corridor_s_entry = state->s;
s_internal.pass_count = 1;
s_stage = SCRIPT_STAGE_CORRIDOR_FORWARD;
}
}
break;
}
/* ==============================================
* STAGE 2: 向前走垄沟
* ============================================== */
case SCRIPT_STAGE_CORRIDOR_FORWARD: {
/* 使用走廊控制器 */
out->request_corridor = true;
/* 检查是否到端 */
bool front_ok = (obs->valid_mask & CORRIDOR_OBS_MASK_FRONT) != 0U;
if (front_ok && obs->d_front <= s_cfg.d_entry_exit_front) {
/* 前向距离足够近 -> 到达垄沟末端,准备转向 */
s_internal.turn_start_e_th = state->e_th;
s_internal.turn_start_imu_yaw_deg = imu_yaw_continuous_deg;
s_internal.turn_started = false;
s_stage = SCRIPT_STAGE_TURN_AT_END;
out->request_corridor = false;
}
break;
}
/* ==============================================
* STAGE 3: 到端原地转向
* ============================================== */
case SCRIPT_STAGE_TURN_AT_END: {
out->request_corridor = false;
if (!s_internal.turn_started) {
s_internal.turn_start_e_th = state->e_th;
s_internal.turn_start_imu_yaw_deg = imu_yaw_continuous_deg;
s_internal.turn_started = true;
}
/* 原地 180 度转向策略 */
float target_delta = s_cfg.turn_target_angle; // 默认 PI (180度)
/* ---- 使用 IMU 连续 yaw 判定转角 (deg → rad) ---- *
* 优点IMU 内部维护的 yaw 经过模块校准,比外部积分 wz 更稳定,
* 且 unwrap 后不存在 ±180° 跳变问题。
* 后备:如果 IMU 离线,退化回 EKF e_th 差值判定。 */
float delta_turned;
float imu_delta_deg = imu_yaw_continuous_deg - s_internal.turn_start_imu_yaw_deg;
delta_turned = imu_delta_deg * 0.01745329252f; // deg → rad
float remaining = target_delta - fabsf(delta_turned);
if (remaining <= 0.1f) {
/* 转向完成 -> 决定下一步 */
if (s_internal.pass_count < 2) {
/* 只走了一遍,往回走 */
s_internal.pass_count++;
s_stage = SCRIPT_STAGE_CORRIDOR_BACKWARD;
} else {
/* 走了两遍,退出场地 */
s_stage = SCRIPT_STAGE_EXIT;
}
out->override_v = 0.0f;
out->override_w = 0.0f;
out->use_override = true;
} else {
/* 继续转向:根据目标方向选择角速度 */
float turn_dir = (target_delta > 0.0f) ? 1.0f : -1.0f;
/* 接近目标时减速 */
float turn_speed = s_cfg.turn_omega;
if (remaining < 0.5f) {
turn_speed *= (remaining / 0.5f); // 线性减速
turn_speed = clampf(turn_speed, 0.3f, s_cfg.turn_omega);
}
out->override_v = 0.0f; // 线速度为 0原地转
out->override_w = turn_dir * turn_speed;
out->use_override = true;
}
break;
}
/* ==============================================
* STAGE 4: 返程走垄沟 (原地转 180° 后继续正向行驶)
* ============================================== */
case SCRIPT_STAGE_CORRIDOR_BACKWARD: {
/* 使用走廊控制器,正向行驶 */
out->request_corridor = true;
/* P1 修复: 原地转 180° 后车头已调转,返回方向即"向前"
* 因此到端检测应使用前向雷达 d_front而非后向雷达 d_back */
bool front_ok = (obs->valid_mask & CORRIDOR_OBS_MASK_FRONT) != 0U;
if (front_ok && obs->d_front <= s_cfg.d_entry_exit_front) {
/* 前向距离足够近 -> 到达垄沟起始端,转向或退出 */
s_internal.turn_start_e_th = state->e_th;
s_internal.turn_start_imu_yaw_deg = imu_yaw_continuous_deg;
s_internal.turn_started = false;
s_stage = SCRIPT_STAGE_TURN_AT_END;
out->request_corridor = false;
}
break;
}
/* ==============================================
* STAGE 5: 退出场地
* ============================================== */
case SCRIPT_STAGE_EXIT: {
/* P1 修复: 退出速度使用独立的 exit_v 参数,
* 而非误用角速度参数 turn_omega * 0.5f */
out->request_corridor = false;
out->override_v = s_cfg.exit_v; // 直线冲出速度 (由 PARAM_SCRIPT_EXIT_V 配置)
out->override_w = 0.0f;
out->use_override = true;
/* 检测是否已离开:两侧雷达都丢失 */
bool left_ok = ((obs->valid_mask & CORRIDOR_OBS_MASK_LF) != 0U) &&
((obs->valid_mask & CORRIDOR_OBS_MASK_LR) != 0U);
bool right_ok = ((obs->valid_mask & CORRIDOR_OBS_MASK_RF) != 0U) &&
((obs->valid_mask & CORRIDOR_OBS_MASK_RR) != 0U);
if (!left_ok && !right_ok) {
/* 两侧都丢了 -> 已离开垄沟,再往前冲 exit_runout_m 后停车 */
if (s_internal.exit_start_s == 0.0f) {
s_internal.exit_start_s = state->s;
}
if (state->s - s_internal.exit_start_s >= s_cfg.exit_runout_m) {
/* 冲够了,停车 */
s_stage = SCRIPT_STAGE_FINISHED;
s_internal.exit_start_s = 0.0f;
}
}
break;
}
/* ==============================================
* STAGE 6: 比赛完成,安全停车
* ============================================== */
case SCRIPT_STAGE_FINISHED: {
out->request_corridor = false;
out->override_v = 0.0f;
out->override_w = 0.0f;
out->use_override = true;
s_running = false;
break;
}
/* ==============================================
* DEFAULT/IDLE: 安全停车
* ============================================== */
case SCRIPT_STAGE_IDLE:
default: {
out->request_corridor = false;
out->override_v = 0.0f;
out->override_w = 0.0f;
out->use_override = true;
break;
}
}
}

133
App/nav/nav_script.h Normal file
View File

@@ -0,0 +1,133 @@
/**
* @file nav_script.h
* @brief 段脚本执行器:编排完整比赛流程
*
* 比赛流程模型:
* ┌─────────────┐
* │ ENTRY_ALIGN │ 入口对准:启动区 -> 第一垄沟入口
* └──────┬──────┘
* │
* v
* ┌─────────────┐
* │ CORRIDOR_A │ 第一垄沟跟踪
* └──────┬──────┘
* │ (到端)
* v
* ┌─────────────┐
* │ TURN_180 │ 原地 180 度转向
* └──────┬──────┘
* │
* v
* ┌─────────────┐
* │ CORRIDOR_B │ 返回垄沟跟踪
* └──────┬──────┘
* │ (到端)
* v
* ┌─────────────┐
* │ EXIT │ 退出比赛场地
* └──────┬──────┘
* │
* v
* ┌─────────────┐
* │ FINISH │ 停在启动区
* └─────────────┘
*/
#ifndef NAV_SCRIPT_H
#define NAV_SCRIPT_H
#include <stdint.h>
#include <stdbool.h>
#include "preproc/corridor_msgs.h"
#include "preproc/corridor_preproc.h"
#ifdef __cplusplus
extern "C" {
#endif
/* =========================================================
* 段脚本阶段枚举
* ========================================================= */
typedef enum {
SCRIPT_STAGE_IDLE = 0, // 待命阶段,不输出任何指令
SCRIPT_STAGE_ENTRY_ALIGN, // 入口对准:从启动区到第一垄沟
SCRIPT_STAGE_CORRIDOR_FORWARD, // 向前走垄沟
SCRIPT_STAGE_TURN_AT_END, // 到端原地转向
SCRIPT_STAGE_CORRIDOR_BACKWARD,// 向后走垄沟
SCRIPT_STAGE_EXIT, // 退出场地
SCRIPT_STAGE_FINISHED, // 比赛完成,安全停车
} NavScriptStage_t;
/* =========================================================
* 段脚本配置参数
* ========================================================= */
typedef struct {
float turn_target_angle; // 原地转向目标角度 (rad),默认 PI (180度)
float turn_omega; // 原地转向角速度 (rad/s)
float corridor_length; // 垄沟长度估计 (m),用于触发到端(备用)
float entry_align_timeout; // 入口对准超时 (ms)
float d_entry_exit_front; // 出入口前向距离阈值 (m)
float entry_align_v; // 入口对准慢速前进速度 (m/s)
float exit_runout_m; // 离开走廊后继续冲出的距离 (m)
float exit_v; // 退出场地直线冲出速度 (m/s)
} NavScriptConfig_t;
/* =========================================================
* 段脚本输出
* ========================================================= */
typedef struct {
NavScriptStage_t stage; // 当前执行阶段
const char *stage_name; // 阶段名称字符串
bool active; // 脚本是否正在运行
bool request_corridor; // 是否请求走廊控制器
float override_v; // 覆盖输出的 v (m/s)
float override_w; // 覆盖输出的 w (rad/s)
bool use_override; // 是否使用覆盖值
} NavScriptOutput_t;
/* =========================================================
* API 接口
* ========================================================= */
/**
* @brief 初始化段脚本执行器
*/
void NavScript_Init(const NavScriptConfig_t *config);
/**
* @brief 开始运行比赛脚本
*/
void NavScript_Start(void);
/**
* @brief 核心执行函数:每个导航周期调用一次
* @param obs 预处理层的观测快照
* @param state 滤波器的走廊状态
* @param imu_yaw_continuous_deg IMU unwrap 后的连续偏航角 (度),用于转弯判定
* @param out 段脚本输出
*/
void NavScript_Update(const CorridorObs_t *obs,
const CorridorState_t *state,
float imu_yaw_continuous_deg,
NavScriptOutput_t *out);
/**
* @brief 获取当前执行阶段
*/
NavScriptStage_t NavScript_GetStage(void);
/**
* @brief 获取阶段名称
*/
const char* NavScript_GetStageName(NavScriptStage_t stage);
/**
* @brief 强制重置脚本到 IDLE
*/
void NavScript_Reset(void);
#ifdef __cplusplus
}
#endif
#endif // NAV_SCRIPT_H

156
App/nav/segment_fsm.c Normal file
View File

@@ -0,0 +1,156 @@
#include "segment_fsm.h"
#include <string.h>
/* ====================== 内部状态 ====================== */
static SegFsmConfig_t s_cfg;
static SegFsmState_t s_state = SEG_STATE_IDLE;
static bool s_initialized = false;
/* 辅助:浮点数限幅 */
static inline float seg_clampf(float val, float lo, float hi)
{
if (val < lo) return lo;
if (val > hi) return hi;
return val;
}
void SegFsm_Init(const SegFsmConfig_t *config)
{
s_cfg = *config;
s_state = SEG_STATE_IDLE;
s_initialized = true;
}
void SegFsm_Start(void)
{
if (s_initialized) {
s_state = SEG_STATE_CORRIDOR;
}
}
SegFsmState_t SegFsm_GetState(void)
{
return s_state;
}
const char* SegFsm_GetStateName(SegFsmState_t s)
{
switch (s) {
case SEG_STATE_IDLE: return "IDLE";
case SEG_STATE_CORRIDOR: return "CORRIDOR";
case SEG_STATE_APPROACH: return "APPROACH";
case SEG_STATE_STOP: return "STOP";
case SEG_STATE_ESTOP: return "E-STOP";
default: return "UNKNOWN";
}
}
void SegFsm_Update(const RawCmd_t *raw_cmd,
const CorridorObs_t *obs,
const CorridorState_t *state,
SegFsmOutput_t *out)
{
if (!s_initialized) {
out->state = SEG_STATE_IDLE;
out->safe_v = 0.0f;
out->safe_w = 0.0f;
return;
}
/* ========================================================
* 1. 全局安全断言:无论在什么状态,满足条件直接超驰
* ======================================================== */
/* 1a. 置信度极低 → 紧急停车 */
if (state->conf < s_cfg.conf_estop_thresh) {
s_state = SEG_STATE_ESTOP;
}
/* ========================================================
* 2. 待命状态:什么都不做
* ======================================================== */
if (s_state == SEG_STATE_IDLE) {
out->state = SEG_STATE_IDLE;
out->safe_v = 0.0f;
out->safe_w = 0.0f;
return;
}
/* ========================================================
* 3. 紧急停车状态:等待置信度恢复
* ======================================================== */
if (s_state == SEG_STATE_ESTOP) {
out->state = SEG_STATE_ESTOP;
out->safe_v = 0.0f;
out->safe_w = 0.0f;
/* 自动恢复开关:当置信度重新回到安全区且前方有路,恢复巡航 */
if (state->conf >= 0.5f) {
s_state = SEG_STATE_CORRIDOR;
}
return;
}
/* ========================================================
* 4. 前向距离判定:决定 CORRIDOR / APPROACH / STOP
* ======================================================== */
bool front_valid = (obs->valid_mask & CORRIDOR_OBS_MASK_FRONT) != 0U;
float d_front = obs->d_front;
if (front_valid) {
if (d_front <= s_cfg.d_front_stop) {
/* 距离过近:到端停车 */
s_state = SEG_STATE_STOP;
} else if (d_front <= s_cfg.d_front_approach) {
/* 进入减速预警区 */
s_state = SEG_STATE_APPROACH;
} else {
/* 前方安全:正常走廊跟踪 */
if (s_state == SEG_STATE_STOP || s_state == SEG_STATE_APPROACH) {
s_state = SEG_STATE_CORRIDOR;
}
}
} else {
/* 前向雷达失效:保守策略,保持当前状态但降速
* (不往 STOP 跳,避免前雷达偶发掉线就急停) */
}
/* ========================================================
* 5. 根据当前状态输出最终安全速度
* ======================================================== */
switch (s_state) {
case SEG_STATE_CORRIDOR: {
/* 正常放行控制器输出 */
out->safe_v = raw_cmd->v;
out->safe_w = raw_cmd->w;
break;
}
case SEG_STATE_APPROACH: {
/* 线性插值减速:
* 当 d_front 从 approach 距离滑向 stop 距离时,
* 速度从 raw_cmd->v 线性衰减至 approach_min_v
*/
float range = s_cfg.d_front_approach - s_cfg.d_front_stop;
float ratio = 1.0f;
if (range > 0.001f) {
ratio = (d_front - s_cfg.d_front_stop) / range;
ratio = seg_clampf(ratio, 0.0f, 1.0f);
}
float v_scaled = s_cfg.approach_min_v + ratio * (raw_cmd->v - s_cfg.approach_min_v);
out->safe_v = seg_clampf(v_scaled, 0.0f, raw_cmd->v);
out->safe_w = raw_cmd->w; // 角速度不限,仍然允许纠偏
break;
}
case SEG_STATE_STOP:
default: {
/* 到端停车 / 紧急停车:零速 */
out->safe_v = 0.0f;
out->safe_w = 0.0f;
break;
}
}
out->state = s_state;
}

78
App/nav/segment_fsm.h Normal file
View File

@@ -0,0 +1,78 @@
#ifndef SEGMENT_FSM_H
#define SEGMENT_FSM_H
#include "preproc/corridor_msgs.h"
#include "preproc/corridor_preproc.h"
/**
* @brief 段状态机的运行阶段枚举
*/
typedef enum {
SEG_STATE_IDLE = 0, // 待命:不输出任何指令
SEG_STATE_CORRIDOR, // 走廊跟踪中:放行控制器输出
SEG_STATE_APPROACH, // 接近端墙:降速保护
SEG_STATE_STOP, // 到端停车:强制零速
SEG_STATE_ESTOP, // 紧急停车:传感器全部失效或异常
} SegFsmState_t;
/**
* @brief 段状态机配置参数
*/
typedef struct {
float d_front_stop; // 前向停车距离阈值 (m),低于此值直接停车
float d_front_approach; // 前向减速预警距离 (m),低于此值开始线性减速
float approach_min_v; // 减速区内最低速度 (m/s),防止爬行太慢永远到不了
float conf_estop_thresh; // 置信度紧急停车阈值,低于此值触发 E-Stop
} SegFsmConfig_t;
/**
* @brief 段状态机对外暴露的完整快照 (供日志或上位机读取)
*/
typedef struct {
SegFsmState_t state; // 当前状态
float safe_v; // 经安全仲裁后的最终线速度 (m/s)
float safe_w; // 经安全仲裁后的最终角速度 (rad/s)
} SegFsmOutput_t;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief 初始化段状态机
* @param config 距离阈值与降级参数
*/
void SegFsm_Init(const SegFsmConfig_t *config);
/**
* @brief 启动走廊跟踪(从 IDLE 切换到 CORRIDOR
*/
void SegFsm_Start(void);
/**
* @brief 核心函数:输入控制器的期望指令,输出安全仲裁后的最终指令
* @param raw_cmd 走廊控制器的原始输出 (v, w)
* @param obs 预处理层的观测快照 (提供 d_front 和 valid_mask)
* @param state 滤波器的状态输出 (提供 conf 置信度)
* @param out 安全仲裁后的最终输出
*/
void SegFsm_Update(const RawCmd_t *raw_cmd,
const CorridorObs_t *obs,
const CorridorState_t *state,
SegFsmOutput_t *out);
/**
* @brief 获取当前状态机状态 (用于日志打印)
*/
SegFsmState_t SegFsm_GetState(void);
/**
* @brief 获取状态名称字符串 (用于日志打印)
*/
const char* SegFsm_GetStateName(SegFsmState_t s);
#ifdef __cplusplus
}
#endif
#endif // SEGMENT_FSM_H

View File

@@ -0,0 +1,58 @@
#ifndef CORRIDOR_MSGS_H
#define CORRIDOR_MSGS_H
#include <stdint.h>
#include <stdbool.h>
/* =========================================================
* EKF 状态维度定义
* ========================================================= */
#define EKF_STATE_DIM 3 // [e_y, e_th, s]
#define EKF_OBS_DIM 3 // [z_ey, z_eth_L, z_eth_R]
/* χ² 检验门限 (95% 置信度) */
/* 1 DOF: 3.84, 2 DOF: 5.99, 3 DOF: 7.81 */
#define CHI2_THRESHOLD_1DOF 3.84f
#define CHI2_THRESHOLD_2DOF 5.99f
#define CHI2_THRESHOLD_3DOF 7.81f
/**
* @brief 走廊观测快照 (由 Blackboard 数据转化清洗而来)
* @note 所有距离单位统一为 米 (m)
*/
typedef struct {
uint32_t t_ms; // 观测时间戳
float d_lf, d_lr; // 左侧前后距离 (m)
float d_rf, d_rr; // 右侧前后距离 (m)
float d_front, d_back; // 前后防撞/到端距离 (m)
uint8_t valid_mask; // 位域掩码:标记哪些雷达数据是当前存活且合法的
} CorridorObs_t;
/**
* @brief 走廊相对定位状态 (EKF 的输出结果)
*/
typedef struct {
uint32_t t_ms; // 状态更新时间戳
float e_y; // 横向偏差 (m),向左偏为正
float e_th; // 航向偏差 (rad),车头偏左为正
float s; // 沿走廊进度里程 (m)
float conf; // 置信度/健康度 (0.0~1.0),用于触发降级
/* EKF 扩展输出 */
float P[EKF_STATE_DIM][EKF_STATE_DIM]; // 状态协方差矩阵
float innovation[EKF_OBS_DIM]; // 新息向量 (观测残差)
float mahalanobis_d2; // 马氏距离平方
uint8_t obs_reject_mask; // 被拒绝的观测位掩码
} CorridorState_t;
/**
* @brief 纯控制指令 (准备交给安全层仲裁)
*/
typedef struct {
uint32_t t_ms;
float v; // 期望线速度 (m/s)
float w; // 期望角速度 (rad/s)
uint8_t flags; // 控制特殊标志位
} RawCmd_t;
#endif // CORRIDOR_MSGS_H

View File

@@ -0,0 +1,119 @@
#include "corridor_preproc.h"
/**
* @brief 内部辅助函数:处理单个侧向 VL53L0X 测距
* @return true 表示数据合法且在量程内false 表示异常或超量程飞点
*/
static bool process_side_laser(const SensorItem_t *item, float *out_m)
{
// 驱动层报异常,直接抛弃
if (!item->is_valid) {
return false;
}
// 毫米转米
float dist_m = item->value / 1000.0f;
// 剔除硬件量程外的死区或异常噪点
if (dist_m > PREPROC_MAX_SIDE_RANGE_M || dist_m < PREPROC_MIN_SIDE_RANGE_M) {
return false;
}
*out_m = dist_m;
return true;
}
/**
* @brief 内部辅助函数:处理前后向互补雷达 (STP 远距离 + ATK 近盲区)
* @note 完美解决 STP-23L 的 7cm 物理盲区问题,防止“幽灵撞墙”
*/
static bool process_complementary_laser(const SensorItem_t *stp, const SensorItem_t *atk, float *out_m)
{
bool stp_ok = stp->is_valid && (stp->value > 0.0f);
bool atk_ok = atk->is_valid && (atk->value > 0.0f);
float stp_m = stp->value / 1000.0f;
float atk_m = atk->value / 1000.0f;
/* 1. 近距离补盲优先:如果 ATK 存活,且测距进入 8cm 内 (7cm盲区+1cm裕量) */
/* 此时 STP 的数据大概率是垃圾数据卡死在7cm或报错无条件信任 ATK */
if (atk_ok && atk_m <= PREPROC_BLIND_ZONE_M) {
*out_m = atk_m;
return true;
}
/* 2. 正常中远距离:两者都存活,取保守值防撞 */
if (stp_ok && atk_ok) {
// 如果 STP 读数等于 7cm 极限值,它可能已经瞎了,直接用 ATK 的值
if (stp_m <= 0.07f) {
*out_m = atk_m;
} else {
*out_m = (stp_m < atk_m) ? stp_m : atk_m; // 正常情况取两者中更近的
}
return true;
}
/* 3. 硬件单体降级:只剩下一个雷达活着 */
if (stp_ok) {
// 只有 STP 活着,但读数在盲区内。这数据极其危险(骗人的),宁可报失效触发急停!
if (stp_m <= 0.07f) {
return false;
}
*out_m = stp_m;
return true;
}
if (atk_ok) {
*out_m = atk_m;
return true;
}
/* 全挂了,通知上层失明 */
return false;
}
void CorridorPreproc_ExtractObs(const RobotBlackboard_t *board, uint32_t now_ms, CorridorObs_t *out_obs)
{
// 初始化输出结构体,清空掩码
out_obs->t_ms = now_ms;
out_obs->valid_mask = 0U;
out_obs->d_lf = 0.0f;
out_obs->d_lr = 0.0f;
out_obs->d_rf = 0.0f;
out_obs->d_rr = 0.0f;
out_obs->d_front = 0.0f;
out_obs->d_back = 0.0f;
/* --- 1. 独立清洗侧向 4 个 VL53L0X 数据 --- */
if (process_side_laser(&board->dist_left_f, &out_obs->d_lf)) {
out_obs->valid_mask |= CORRIDOR_OBS_MASK_LF;
}
if (process_side_laser(&board->dist_left_r, &out_obs->d_lr)) {
out_obs->valid_mask |= CORRIDOR_OBS_MASK_LR;
}
if (process_side_laser(&board->dist_right_f, &out_obs->d_rf)) {
out_obs->valid_mask |= CORRIDOR_OBS_MASK_RF;
}
if (process_side_laser(&board->dist_right_r, &out_obs->d_rr)) {
out_obs->valid_mask |= CORRIDOR_OBS_MASK_RR;
}
/* --- 2. 前向雷达:远近互补融合 --- */
if (process_complementary_laser(&board->dist_front_stp, &board->dist_front_atk, &out_obs->d_front)) {
/* 补偿传感器内缩:将"传感器到墙"转换为"车体前端到墙"
* d_body = d_sensor - front_laser_offset
* 当 offset > 0 时表示传感器在车体内部,车体前端比传感器更接近墙 */
out_obs->d_front -= PARAM_FRONT_LASER_OFFSET;
if (out_obs->d_front < 0.0f) out_obs->d_front = 0.0f; /* 安全下限 */
out_obs->valid_mask |= CORRIDOR_OBS_MASK_FRONT;
}
/* --- 3. 后向雷达:远近互补融合 --- */
if (process_complementary_laser(&board->dist_rear_stp, &board->dist_rear_atk, &out_obs->d_back)) {
/* 补偿传感器内缩:同前向逻辑 */
out_obs->d_back -= PARAM_REAR_LASER_OFFSET;
if (out_obs->d_back < 0.0f) out_obs->d_back = 0.0f;
out_obs->valid_mask |= CORRIDOR_OBS_MASK_BACK;
}
}

View File

@@ -0,0 +1,43 @@
#ifndef CORRIDOR_PREPROC_H
#define CORRIDOR_PREPROC_H
#include <stdint.h>
#include <stdbool.h>
#include "Contract/robot_blackboard.h"
#include "corridor_msgs.h"
/* 传感器有效性掩码定义 (对应 CorridorObs_t.valid_mask) */
#define CORRIDOR_OBS_MASK_LF (1U << 0) // 左前有效
#define CORRIDOR_OBS_MASK_LR (1U << 1) // 左后有效
#define CORRIDOR_OBS_MASK_RF (1U << 2) // 右前有效
#define CORRIDOR_OBS_MASK_RR (1U << 3) // 右后有效
#define CORRIDOR_OBS_MASK_FRONT (1U << 4) // 前方互补测距有效
#define CORRIDOR_OBS_MASK_BACK (1U << 5) // 后方互补测距有效
/* VL53L0X 侧向雷达的物理有效探测区间 (m) */
#define PREPROC_MAX_SIDE_RANGE_M 2.0f
#define PREPROC_MIN_SIDE_RANGE_M 0.02f
/* 前后向雷达近战盲区阈值 (m) (STP 7cm盲区 + 1cm工程裕量) */
#define PREPROC_BLIND_ZONE_M 0.08f
/* 前后激光传感器内缩补偿 (从 robot_params.h 引入) */
#include "robot_params.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief 从黑板快照中提取、仲裁并清洗走廊观测数据
* @param board 输入的黑板数据快照
* @param now_ms 当前的系统时间戳
* @param out_obs 输出的清洗后观测值 (仅保留合法数据,单位统一为 m)
*/
void CorridorPreproc_ExtractObs(const RobotBlackboard_t *board, uint32_t now_ms, CorridorObs_t *out_obs);
#ifdef __cplusplus
}
#endif
#endif // CORRIDOR_PREPROC_H

99
App/retarget.c Normal file
View File

@@ -0,0 +1,99 @@
#include "retarget.h"
#include <stdint.h>
#include <stdio.h>
#include "cmsis_os.h"
#include "usbd_cdc_if.h"
/*
* 说明:
* 1. 这里默认使用 FreeRTOS 的 CMSIS-RTOS2 接口
* 2. printf 最终会走到 _write()
* 3. _write() 内部调用 CDC_Transmit_FS() 发送到 USB 虚拟串口
* 4. 为避免多个任务同时 printf 打花,这里提供互斥锁
*/
static osMutexId_t s_retarget_mutex = NULL;
static uint8_t s_inited = 0U;
/* 互斥锁属性 */
static const osMutexAttr_t s_retarget_mutex_attr = {
.name = "retargetMutex"
};
void Retarget_Init(void)
{
if (s_inited != 0U)
{
return;
}
/* 只有在内核启动后创建互斥量才有意义 */
if (osKernelGetState() == osKernelRunning)
{
s_retarget_mutex = osMutexNew(&s_retarget_mutex_attr);
}
s_inited = 1U;
}
void Retarget_Lock(void)
{
if ((s_retarget_mutex != NULL) && (osKernelGetState() == osKernelRunning))
{
(void)osMutexAcquire(s_retarget_mutex, osWaitForever);
}
}
void Retarget_Unlock(void)
{
if ((s_retarget_mutex != NULL) && (osKernelGetState() == osKernelRunning))
{
(void)osMutexRelease(s_retarget_mutex);
}
}
/*
* GNU 工具链 printf 重定向
* 注意:
* - 不要在中断里调用 printf
* - USB CDC 忙时最多等待 20ms
* - 等待期间 osDelay(1) 让出 CPU
*/
int _write(int file, char *ptr, int len)
{
uint32_t start_tick;
uint8_t result;
(void)file;
if ((ptr == NULL) || (len <= 0))
{
return 0;
}
start_tick = HAL_GetTick();
while (1)
{
result = CDC_Transmit_FS((uint8_t *)ptr, (uint16_t)len);
if (result == USBD_OK)
{
return len;
}
/* USB 还没准备好或者正忙,最多等 20ms */
if ((HAL_GetTick() - start_tick) > 20U)
{
return 0;
}
/* 在 FreeRTOS 下主动让出 CPU */
if (osKernelGetState() == osKernelRunning)
{
osDelay(1);
}
}
}

21
App/retarget.h Normal file
View File

@@ -0,0 +1,21 @@
#ifndef __RETARGET_H
#define __RETARGET_H
#ifdef __cplusplus
extern "C" {
#endif
/* 初始化日志输出模块 */
void Retarget_Init(void);
/* 日志输出加锁 */
void Retarget_Lock(void);
/* 日志输出解锁 */
void Retarget_Unlock(void);
#ifdef __cplusplus
}
#endif
#endif

406
App/robot_params.h Normal file
View File

@@ -0,0 +1,406 @@
/**
* @file robot_params.h
* @brief ARES 机器人全局参数配置中心
*
* ============================================
* 实车调参前必读
* ============================================
* 1. 所有长度单位默认为 米 (m),角度为 弧度 (rad),速度为 m/s
* 2. 带"实测"标记的参数必须用卷尺/编码器实际测量后填写
* 3. 带"调优"标记的参数需要根据实车运行效果从小往大调整
* 4. 修改本文件后需要重新编译烧录
*
* 调参顺序建议:
* P0: 几何参数 (传感器位置、轮子尺寸) -> 必须实测
* P1: 里程计参数 -> 实车跑 10 米对比编码器/实际距离
* P2: 走廊滤波器 -> 从保守值开始逐步调优
* P3: 控制器增益 -> 实车走廊测试,从低增益开始
* P4: 安全阈值 -> 根据实际场地微调
*/
#ifndef ROBOT_PARAMS_H
#define ROBOT_PARAMS_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* =========================================================
* 【P0】机械/几何参数 (必须实测,开机前填写!)
* ========================================================= */
/* ------------------- 车体几何 ------------------- */
/** @brief [实测] 车体外轮廓宽度 [m] (左右方向,含外壳)
* 测量方法:卷尺测量车体最宽处
* 典型值20cm -> 0.20
* 用途:侧向安全裕量计算,传感器偏移补偿
*/
#define PARAM_ROBOT_WIDTH 0.200f
/** @brief [实测] 车体外轮廓长度 [m] (前后方向,含外壳)
* 测量方法:卷尺测量车体最长处
* 典型值20cm -> 0.20
* 用途:前后安全距离补偿
*/
#define PARAM_ROBOT_LENGTH 0.200f
/** @brief [实测] 驱动轮标称直径 [m]
* 测量方法:卷尺测量轮胎外径 (非轮毂)
* 典型值60mm 轮胎 -> 0.060
*/
#define PARAM_WHEEL_DIAMETER 0.080f
/** @brief [实测] 左右轮中心距 [m]
* 测量方法:卷尺测量左右驱动轮中心之间的距离
* 典型值:车体 20cm 宽,轮胎每边厚 3cm -> 约 0.14m
*/
#define PARAM_WHEEL_TRACK 0.140f
/** @brief [实测] 同侧前后 VL53L0X 雷达纵向间距 [m]
* 测量方法:卷尺测量同侧前后两个 VL53L0X 的中心距离
* 典型值:根据机械安装,约 0.10~0.15m
* 影响:航向观测精度 z_eth = atan2((d_back-d_front), L_s)
*/
#define PARAM_SENSOR_BASE_LENGTH 0.120f
/** @brief [实测] 比赛走廊标准宽度 [m]
* 测量方法:卷尺测量赛场垄沟实际宽度 (规则 40cm允许±5% 误差)
* 典型值0.40 (但建议实测后填写)
*/
#define PARAM_CORRIDOR_WIDTH 0.40f
/** @brief [实测] 前向激光雷达安装中心偏置 [m]
* 测量方法:雷达发射面到车头最前端的距离 (内缩为正)
* 典型值:根据机械安装,若与车头齐平则为 0
* 用途:前向到端距离补偿 d_body_front = d_sensor - offset
* 注意:这里定义的是传感器到车头前缘的距离,不是到几何中心
*/
#define PARAM_FRONT_LASER_OFFSET 0.0f
/** @brief [实测] 后向激光雷达安装中心偏置 [m]
* 测量方法:雷达发射面到车尾最后端的距离 (内缩为正)
* 典型值:根据机械安装,若与车尾齐平则为 0
* 用途:后向到端距离补偿 d_body_rear = d_sensor - offset
*/
#define PARAM_REAR_LASER_OFFSET 0.0f
/** @brief [实测] 侧向 VL53L0X 传感器内缩距离 [m]
* 测量方法VL53L0X 发射面到车体侧面最外边缘的距离 (向内为正)
* 典型值:传感器与外壳齐平则为 0嵌入 1cm 则为 0.01
* 用途侧向测距补偿d_actual_to_wall = d_sensor - sensor_inset
* 即传感器测到的距离减去这个内缩量才是车体边缘到墙的真实距离
* ⚠ 极其重要沟道40cm - 车体20cm = 每边仅10cm1cm的偏差就是10%的误差!
*/
#define PARAM_VL53_SIDE_INSET 0.0f
/* ------------------- 编码器参数 ------------------- */
/** @brief [实测] 编码器每转脉冲数 (CPR)
* 测量方法:查阅 F407 固件配置,或实车转动一圈数脉冲
* 典型值500 (F407 默认固件)
*/
#define PARAM_ENCODER_CPR 500
/* =========================================================
* 【P1】里程计参数 (实车标定)
* ========================================================= */
/** @brief [调优] 里程计过程噪声 [m²/s²]
* 含义:对里程计信任程度,越小越信任
* 调优方法:实车直线跑 10 米,对比 EKF 输出的 s 与实际距离
* 典型值0.01~0.1
* 过大EKF 过度依赖里程计,轮滑时误差累积
* 过小EKF 不信任里程计,沿程 s 估计不准
*/
#define PARAM_ODOM_PROCESS_NOISE 0.1f
/** @brief [调优] 里程计速度低通滤波系数
* 含义alpha=0.8 表示新采样占 20%,历史值占 80%
* 典型值0.7~0.9
*/
#define PARAM_ODOM_LOWPASS_ALPHA 0.8f
/* =========================================================
* 【P2】走廊 EKF 滤波器参数 (调优)
* ========================================================= */
/* --- EKF 过程噪声 Q (对模型信任度) --- */
/** @brief [调优] 横向偏差 e_y 过程噪声方差 [m²]
* 含义:横向状态的自然发散速度,越小表示横向越稳定
* 调优方法:从 0.001 开始,逐步增大直到走廊跟踪平滑
* 典型值0.001~0.02
* 过大EKF 认为横向很不稳定,过度依赖观测 -> 震荡
* 过小EKF 不信任观测,响应慢
*/
#define PARAM_EKF_Q_EY 0.01f
/** @brief [调优] 航向偏差 e_th 过程噪声方差 [rad²]
* 含义:航向状态的自然发散速度
* 调优方法IMU 短时漂移小,可以设很小
* 典型值0.0001~0.005
* 过大EKF 认为航向不稳定IMU 作用被削弱
* 过小EKF 过度信任 IMU雷达观测不起作用
*/
#define PARAM_EKF_Q_ETH 0.001f
/** @brief [调优] 沿程进度 s 过程噪声方差 [m²]
* 含义:里程估计的不确定度
* 调优方法:地毯轮滑严重时调大
* 典型值0.05~0.2
*/
#define PARAM_EKF_Q_S 0.1f
/* --- EKF 观测噪声 R (对传感器信任度) --- */
/** @brief [调优] 横向观测噪声方差 [m²]
* 含义VL53L0X 测距的可靠程度
* 调优方法:从 0.001 开始,根据走廊跟踪平滑度调整
* 典型值0.001~0.005
* 过大EKF 不信任侧向雷达,横向响应慢
* 过小EKF 过度信任雷达,对跳变敏感
*/
#define PARAM_EKF_R_EY 0.002f
/** @brief [调优] 航向观测噪声方差 [rad²]
* 含义:同侧前后雷达差分测角的可程靠度
* 调优方法:从 0.001 开始
* 典型值0.0005~0.003
*/
#define PARAM_EKF_R_ETH 0.001f
/** @brief [调优] IMU 航向观测噪声方差 [rad²]
* 含义IMU yaw 作为 EKF 航向观测时的噪声
* 设计意图IMU yaw 用于长时航向约束 (防止 wz 积分漂移)
* R 值应明显大于侧墙航向观测 R_ETH避免干扰侧墙短时精确修正
* 调优方法:从 0.01 开始,如果 IMU yaw 非常稳定可减小
* 典型值0.005~0.05
* 过大IMU 航向观测作用弱,等于没接入
* 过小IMU 航向主导,侧墙观测被压制
*/
#define PARAM_EKF_R_ETH_IMU 0.01f
/* --- EKF 初始状态 --- */
/** @brief [调优] e_y 初始不确定度 [m²]
* 含义:开机时横向位置的先验不确定度
* 典型值0.01~0.1 (对应 10~30cm 不确定)
*/
#define PARAM_EKF_P0_EY 0.1f
/** @brief [调优] e_th 初始不确定度 [rad²]
* 含义:开机时航向的先验不确定度
* 典型值0.05~0.2 (对应 13°~26°不确定)
*/
#define PARAM_EKF_P0_ETH 0.1f
/* --- χ² 检验门限 (鲁棒拒绝) --- */
/** @brief [固定] 1 自由度 χ² 检验门限 (95% 置信度)
* 含义:单路观测的马氏距离超过此值则拒绝
* 理论值3.84 (95%), 6.63 (99%)
* 建议:不要修改,除非传感器质量极差
*/
#define PARAM_CHI2_1DOF 3.84f
/** @brief [固定] 2 自由度 χ² 检验门限 (95% 置信度)
* 理论值5.99
*/
#define PARAM_CHI2_2DOF 5.99f
/* =========================================================
* 【P3】走廊控制器参数 (实车调优)
* ========================================================= */
/** @brief [调优] 航向比例增益 kp_theta [1/s]
* 含义:航向偏差 1 rad 时产生的角速度
* 调优方法:从 0.5 开始逐步增加,直到走廊跟踪响应快但不震荡
* 典型值1.0~3.0
* 过大:车头左右摆动 (震荡)
* 过小:纠偏太慢,容易撞墙
*/
#define PARAM_CTRL_KP_THETA 2.0f
/** @brief [调优] 航向微分增益 kd_theta [s]
* 含义IMU 角速度阻尼项,抑制车头转动速度
* 调优方法:从 0.05 开始
* 典型值0.05~0.2
* 过大:车头转动被过度抑制,响应迟钝
* 过小:阻尼不足,容易超调震荡
*/
#define PARAM_CTRL_KD_THETA 0.1f
/** @brief [调优] 横向比例增益 kp_y [1/(m·s)]
* 含义:横向偏差 1m 时产生的角速度修正
* 调优方法:从 1.0 开始
* 典型值1.5~4.0
* 过大:横向纠偏过猛,引起震荡
* 过小:偏了拉不回来
*/
#define PARAM_CTRL_KP_Y 3.0f
/** @brief [调优] 走廊巡航速度 [m/s]
* 含义:走廊内正常行驶速度
* 调优方法:从 0.1 m/s 开始逐步增加
* 典型值0.15~0.4 m/s
* 注意:速度越高,对滤波器带宽和控制器增益要求越高
*/
#define PARAM_CTRL_V_CRUISE 0.15f
/** @brief [调优] 角速度输出限幅 [rad/s]
* 含义:最大允许转角速度
* 典型值1.0~2.0 (约 57°/s ~ 115°/s)
*/
#define PARAM_CTRL_W_MAX 1.5f
/** @brief [调优] 线速度输出限幅 [m/s]
* 含义:最大允许线速度
* 典型值0.3~0.5
*/
#define PARAM_CTRL_V_MAX 0.3f
/** @brief [调优] 弯道减速系数 [0~1]
* 含义:角速度大时线速度打折程度
* 公式v = v_cruise * (1 - k * |w/w_max|)
* 典型值0.3~0.5
*/
#define PARAM_CTRL_SPEED_REDUCTION 0.4f
/* =========================================================
* 【P4】安全阈值与状态机参数
* ========================================================= */
/* --- 到端检测 --- */
/** @brief [调优] 前向停车距离阈值 [m]
* 含义:前向雷达 (传感器到墙的距离) 低于此值强制停车
* 计算方法PARAM_FRONT_LASER_OFFSET (传感器内缩) + 安全裕量 (2~5cm)
* 示例:传感器与车头齐平(offset=0) + 3cm安全裕量 = 0.03m
* 传感器内缩5cm(offset=0.05) + 3cm安全裕量 = 0.08m
* ⚠ 此阈值应 >= PARAM_FRONT_LASER_OFFSET否则传感器到墙的距离
* 还没到阈值,车体前端就已经撞墙了!
* 过小:可能撞墙
* 过大:离墙很远就停车,走不完走廊
*/
#define PARAM_SAFE_D_FRONT_STOP 0.08f
/** @brief [调优] 前向减速预警距离 [m]
* 含义:前向雷达低于此值开始线性减速
* 典型值0.20~0.40
*/
#define PARAM_SAFE_D_FRONT_APPROACH 0.25f
/** @brief [调优] 减速区最低速度 [m/s]
* 含义:到端前爬行速度
* 典型值0.03~0.08
*/
#define PARAM_SAFE_APPROACH_MIN_V 0.05f
/* --- 置信度降级 --- */
/** @brief [调优] E-Stop 置信度阈值
* 含义EKF 置信度低于此值触发紧急停车
* 典型值0.05~0.15
*/
#define PARAM_SAFE_CONF_ESTOP 0.1f
/** @brief [调优] 单侧退化置信度
* 含义:单侧 VL53L0X 失效时,置信度降为多少
* 典型值0.6~0.8
*/
#define PARAM_SAFE_CONF_DEGRADED 0.7f
/* --- 入口/退出 --- */
/** @brief [调优] 入口对准速度 [m/s]
* 含义:从启动区进入走廊的慢速对准速度
* 典型值0.05~0.10
*/
#define PARAM_SCRIPT_ENTRY_V 0.08f
/** @brief [调优] 入口对准超时 [ms]
* 含义:超过此时间强制进入走廊模式 (保护)
* 典型值20000~40000 (20~40 秒)
*/
#define PARAM_SCRIPT_ENTRY_TIMEOUT 30000U
/** @brief [调优] 原地转向角速度 [rad/s]
* 含义:到端 180 度转向的角速度
* 典型值0.8~1.5
*/
#define PARAM_SCRIPT_TURN_OMEGA 1.0f
/** @brief [调优] 退出场地后冲距离 [m]
* 含义:检测到离开垄沟后再往前冲的距离
* 典型值1.5~2.5
*/
#define PARAM_SCRIPT_EXIT_RUNOUT 2.0f
/** @brief [调优] 退出场地直线冲出速度 [m/s]
* 含义:检测到离开垄沟后直线冲出的速度
* 典型值0.3~0.5
* 注意:与 turn_omega (转向角速度) 无关,两者独立
*/
#define PARAM_SCRIPT_EXIT_V 0.3f
/* =========================================================
* 【P5】传感器驱动参数
* ========================================================= */
/* --- VL53L0X --- */
/** @brief [实测] VL53L0X 测距预算 [μs]
* 含义:单次测距的时间预算,越大精度越高但频率越低
* 选项20000(20ms, 高速), 33000(33ms), 100000(100ms), 200000(200ms, 高精度)
* 典型值100000 (100ms折中)
* 调优:走廊跟踪时用 100ms原地转向时可切 200ms 提高精度
*/
#define PARAM_VL53_TIMING_BUDGET 100000U
/** @brief [调优] VL53L0X 卡尔曼滤波参数 Q
* 含义:测距过程噪声
* 典型值5.0~20.0
*/
#define PARAM_VL53_KALMAN_Q 10.0f
/** @brief [调优] VL53L0X 卡尔曼滤波参数 R
* 含义:测距观测噪声
* 典型值10.0~30.0
*/
#define PARAM_VL53_KALMAN_R 14.1f
/* --- IMU --- */
/** @brief [实测] HWT101 IMU 安装偏置 (航向) [rad]
* 含义IMU 零位与车头方向的偏差
* 测量:车头对准正北,读取 IMU 航向作为偏置
* 典型值:需要通过校准确定
*/
#define PARAM_IMU_YAW_OFFSET 0.0f
/* =========================================================
* 宏工具函数
* ========================================================= */
#define PARAM_RAD2DEG(rad) ((rad) * 57.2957795131f)
#define PARAM_DEG2RAD(deg) ((deg) * 0.01745329252f)
/* =========================================================
* 快速参考表
* =========================================================
*
* 调参流程:
* 1. 实测几何参数 (P0 组) -> 卷尺测量
* 2. 里程计标定 (P1 组) -> 跑 10 米对比
* 3. 原地测试控制器 -> 只调 kp_theta, kd_theta
* 4. 走廊低速测试 -> 调 kp_y, v_cruise
* 5. 逐步提速 -> 微调各增益
* 6. 安全阈值 -> 根据实际场地
*
* 常见问题诊断:
* 车头左右摆 -> 减小 kp_theta 或增大 kd_theta
* 横向纠偏慢 -> 增大 kp_y
* 到端刹车不住 -> 减小 d_front_stop 或增大 approach 距离
* 出口冲不出 -> 减小 exit_runout 或增大 v_cruise
* EKF 发散 -> 增大 Q 或减小 R
*
* =========================================================
*/
#ifdef __cplusplus
}
#endif
#endif /* ROBOT_PARAMS_H */

79
CMakeLists.txt Normal file
View File

@@ -0,0 +1,79 @@
cmake_minimum_required(VERSION 3.22)
#
# This file is generated only once,
# and is not re-generated if converter is called multiple times.
#
# User is free to modify the file as much as necessary
#
# Setup compiler settings
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
# Define the build type
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
endif()
# Set the project name
set(CMAKE_PROJECT_NAME ARES)
# Enable compile command to ease indexing with e.g. clangd
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
# Core project settings
project(${CMAKE_PROJECT_NAME})
message("Build type: " ${CMAKE_BUILD_TYPE})
# Enable CMake support for ASM and C languages
enable_language(C ASM)
# Create an executable object type
# NOTE: 所有 App/ 下的源文件统一由下方 file(GLOB_RECURSE) 收集,
# 此处不再手写重复列表,避免配置漂移和平台差异(如大小写敏感文件系统)。
add_executable(${CMAKE_PROJECT_NAME})
# Add STM32CubeMX generated sources
add_subdirectory(cmake/stm32cubemx)
# Link directories setup
target_link_directories(${CMAKE_PROJECT_NAME} PRIVATE
# Add user defined library search paths
)
file(GLOB_RECURSE USER_APP_SOURCES "App/*.c")
# Add sources to executable
target_sources(${CMAKE_PROJECT_NAME} PRIVATE
# Add user sources here
${USER_APP_SOURCES}
)
# Add include paths
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
# Add user defined include paths
App
App/Can
App/VL53L0X_API/core/inc
App/VL53L0X_API/core/src
App/VL53L0X_API/platform
)
# Add project symbols (macros)
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE
# Add user defined symbols
)
# Remove wrong libob.a library dependency when using cpp files
list(REMOVE_ITEM CMAKE_C_IMPLICIT_LINK_LIBRARIES ob)
# Add linked libraries
target_link_libraries(${CMAKE_PROJECT_NAME}
stm32cubemx
# Add user defined libraries
)
target_link_options(${CMAKE_PROJECT_NAME} PRIVATE
-u _printf_float
)

38
CMakePresets.json Normal file
View File

@@ -0,0 +1,38 @@
{
"version": 3,
"configurePresets": [
{
"name": "default",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"toolchainFile": "${sourceDir}/cmake/gcc-arm-none-eabi.cmake",
"cacheVariables": {
}
},
{
"name": "Debug",
"inherits": "default",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "Release",
"inherits": "default",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
],
"buildPresets": [
{
"name": "Debug",
"configurePreset": "Debug"
},
{
"name": "Release",
"configurePreset": "Release"
}
]
}

397
CODE_REVIEW.md Normal file
View File

@@ -0,0 +1,397 @@
# ARES 项目代码审查报告
> **审查日期**: 2025 年
> **审查范围**: `/App` 目录下全部业务代码(排除 `VL53L0X_API/core` ST 官方库)
> **审查基准**: HANDOFF.md 中的设计描述与已修复 BUG 列表
> **审查重点**: 残留 BUG、潜在运行时风险、代码质量问题
---
## 审查总结
| 严重等级 | 数量 | 说明 |
|---------|------|------|
| 🔴 严重 (可能导致功能错误/崩溃) | 4 | 运行时会导致错误行为 |
| 🟠 中等 (潜在风险/隐患) | 6 | 特定条件下可能触发问题 |
| 🟡 低 (代码质量/可维护性) | 7 | 不影响功能但应改善 |
**总体评价**: 项目架构设计清晰HANDOFF.md 中列出的 9 个严重 BUG 和 7 个质量问题均已正确修复。但仍存在若干残留问题,以下逐一分析。
---
## 🔴 严重问题
### S-1: VL53L0X 卡尔曼滤波 Q/R 参数硬编码,未使用 `robot_params.h` 配置
**文件**: `VL53L0X_API/platform/vl53_board.c:84`
```c
/* 初始化卡尔曼滤波器:默认 Q=1.0, R=9.5 */ // ← 注释过期
vl53_kalman_init(&board->kf[i], 10.0f, 14.1f); // ← 硬编码值
```
`robot_params.h` 中定义了 `PARAM_VL53_KALMAN_Q = 10.0f``PARAM_VL53_KALMAN_R = 14.1f`,但 `vl53_board.c` 没有 `#include "robot_params.h"`,而是直接写死了 `10.0f``14.1f`。虽然当前值恰好与参数一致,但**修改 `robot_params.h` 中的 `PARAM_VL53_KALMAN_Q/R` 不会生效**,与 BUG-2 (EKF 参数硬编码) 属于同类问题。
**修复建议**:
```c
#include "robot_params.h"
// ...
vl53_kalman_init(&board->kf[i], PARAM_VL53_KALMAN_Q, PARAM_VL53_KALMAN_R);
```
---
### S-2: `LASER_SIMPLE_GetSnapshot()` 返回指针无线程安全保护,存在数据撕裂风险
**文件**: `laser/laser_manager.c:277-279`
```c
const laser_simple_snapshot_t *LASER_SIMPLE_GetSnapshot(void) {
return &g_snapshot; // ← 返回原始指针,无拷贝、无临界区保护
}
```
消费者 `AppTasks_RunLaserTestTask_Impl()` 调用此函数获取指针后直接传给 `Blackboard_UpdateLaser(snap)`。由于 `LaserTask`内部10ms任务`taskENTER_CRITICAL()` 中**逐通道写入** `g_snapshot.ch[i]`,而消费者拿到的是裸指针,读取可能发生在写入的间隙——比如前两个通道已更新、后两个通道还是旧值——构成**部分撕裂**。
虽然 `Blackboard_UpdateLaser` 内部有临界区保护,但问题出在**读 g_snapshot 的时候没有保护**。当前架构中 `laserTestTask` 以 50ms 周期读取、`LaserTask` 以 10ms 周期写入,两者优先级相同,可能发生抢占。
**影响等级**: 中高。实际撕裂概率取决于临界区外的读取窗口大小。由于 `laser_simple_snapshot_t` 只包含 4 个 `laser_simple_data_t`,单次 `memcpy` 耗时极短,实际风险较低。但从防御性编程角度应修复。
**修复建议**:
```c
void LASER_SIMPLE_GetSnapshotCopy(laser_simple_snapshot_t *out) {
taskENTER_CRITICAL();
*out = g_snapshot;
taskEXIT_CRITICAL();
}
```
---
### S-3: `snc_parse_odom_delta()` 在 ISR 中写 `odom_accum` 无临界区保护
**文件**: `Can/snc_can_app.c:148-173` (在 `SNC_CAN_RxFifo0Callback` 即 CAN ISR 中被调用)
```c
static void snc_parse_odom_delta(const uint8_t *d)
{
// ... 直接写 g_snc_can_app.odom_accum 的各个字段 ...
SNC_OdomDeltaAccum_t *acc = &g_snc_can_app.odom_accum;
acc->fl_accum += (int32_t)snc_read_i16_le(d[0], d[1]);
// ...
if (acc->frame_count < 255U) {
acc->frame_count++;
}
}
```
而消费侧 `SNC_CAN_ConsumeOdomDelta()` 使用 `taskENTER_CRITICAL()` 保护读取和清零。问题是:**`taskENTER_CRITICAL()` 在 Cortex-M 上通过 BASEPRI 屏蔽中断,只屏蔽优先级不高于 `configMAX_SYSCALL_INTERRUPT_PRIORITY` 的中断**。如果 CAN FIFO0 中断的优先级高于此阈值(即数值更小),那么 `snc_parse_odom_delta()` 可能在消费者持有临界区期间执行,导致**竞态条件**消费者清零后ISR 立刻写入新数据,然后消费者返回的 `snapshot``frame_count=0``accum` 值已非零。
**影响等级**: 取决于 CAN 中断优先级配置。如果 CAN 中断优先级在 FreeRTOS 管理范围内(优先级数值 ≥ `configMAX_SYSCALL_INTERRUPT_PRIORITY`),则 `taskENTER_CRITICAL()` 可以正确屏蔽它,问题不存在。**需要检查 CubeMX 中 FDCAN1 中断优先级配置**。
**修复建议**: 确认 FDCAN1 中断优先级 ≥ `configMAX_SYSCALL_INTERRUPT_PRIORITY`。或在 `snc_parse_odom_delta()` 中也使用 `taskENTER_CRITICAL()`(但 ISR 中应使用 `taskENTER_CRITICAL_FROM_ISR()`)。
---
### S-4: `corridor_msgs.h` 使用 `#pragma pack(push, 1)` 导致 EKF 矩阵和浮点运算性能损失及潜在对齐异常
**文件**: `preproc/corridor_msgs.h:8,61`
```c
#pragma pack(push, 1)
// ...
typedef struct {
float P[3][3]; // 36 字节的浮点矩阵,被强制 1 字节对齐
float innovation[3]; // 12 字节
float mahalanobis_d2;
// ...
} CorridorState_t;
// ...
#pragma pack(pop)
```
`CorridorState_t` 包含大量 `float``float[3][3]` 数组,被 `#pragma pack(push, 1)` 强制 1 字节对齐。在 Cortex-M7 上:
1. **性能损失**: 未对齐的 float 访问会触发硬件 unaligned access 处理,速度比对齐访问慢数倍。这个结构体在 navTask 的 20ms 循环中被高频读写,影响实时性能。
2. **FPU 指令风险**: 某些 FPU 指令(如 `VLDM`/`VSTM`**要求 4 字节对齐**,不对齐会触发 UsageFault。虽然 GCC 通常会生成安全的加载指令,但编译器优化可能引入向量化或批量加载指令。
`CorridorObs_t``RawCmd_t` 也受影响,但内部结构更简单,风险较低。
**修复建议**: `#pragma pack(push, 1)` 仅用于需要匹配物理总线帧格式的结构体(如 `chassis_can_msg.h` 中的 CAN 帧,那是正确的用法)。`corridor_msgs.h` 中的结构体是内存中的数据传递,**不需要 pack(1)**,应删除。
---
## 🟠 中等问题
### M-1: IMU 帧解析状态机缺少帧类型 0x55 之后的 header byte 校验
**文件**: `IMU/hwt101.c:64-68`
```c
if (s_frame_idx == 0 && byte != 0x55) continue;
s_frame[s_frame_idx++] = byte;
if (s_frame_idx >= 11) {
```
当前状态机只检查首字节 `0x55`,然后无条件接收后续 10 字节。如果数据流中出现非帧头的 `0x55`(比如校验和恰好是 `0x55`),会导致帧错位。虽然最后有校验和检查可以过滤错误帧,但会**浪费 10 个字节的解析窗口**,在高频数据流中可能导致短暂的数据更新延迟。
**修复建议**: 在 `s_frame_idx == 1` 时检查第二字节是否为有效帧类型 (`0x51`/`0x52`/`0x53`),不匹配则 `s_frame_idx = 0` 重新寻帧。
---
### M-2: `nav_script.c` 转向方向始终为正,不支持反向 (顺时针) 180° 转弯
**文件**: `nav/nav_script.c:202,229`
```c
float target_delta = s_cfg.turn_target_angle; // 默认 PI (180度)
// ...
float turn_dir = (target_delta > 0.0f) ? 1.0f : -1.0f;
```
`turn_target_angle``app_tasks.c` 中始终被初始化为 `3.14159265f`(正值),所以 `turn_dir` 永远为 `1.0f`(逆时针)。如果因场地布局需要顺时针转弯,当前代码无法支持。更关键的是,**两次 180° 转弯方向相同**——第一次到端逆时针转,第二次到端又逆时针转,结果机器人回到出发方向。这可能是设计意图(转完 180° 后继续正向走),但如果走廊空间不对称,固定转向方向可能导致转弯时撞墙。
**修复建议**: 考虑根据当前方向或走廊几何自动选择转向方向,或至少在 `NavScriptConfig_t` 中加一个 `turn_direction` 参数。
---
### M-3: `Odom_GetSpeed()` 在临界区外读取 `s_odom.vx` 和 `s_odom.wz`
**文件**: `Contract/robot_odom.c:122-124`
```c
void Odom_GetSpeed(float *out_vx, float *out_wz, OdomStatus_t *out_status)
{
if (out_vx != NULL) *out_vx = s_odom.vx; // ← 临界区外
if (out_wz != NULL) *out_wz = s_odom.wz; // ← 临界区外
if (out_status != NULL) {
lock_odom(); // ← 只有 status 在临界区内
// ...
unlock_odom();
}
}
```
`s_odom.vx``s_odom.wz``float` 类型,在 Cortex-M7 上 32 位对齐的 float 读写是原子的,所以单独读取不会撕裂。但 `vx``wz` 之间不是原子的——可能读到旧的 `vx` 和新的 `wz`。不过此函数当前未被任何代码调用(速度通过 `Blackboard_UpdateOdom` 传递),所以实际影响为零。
**修复建议**: 将 `vx/wz` 的读取也放入 `lock_odom()` 中,或标注此函数为 `@deprecated`
---
### M-4: `SNC_CAN_SendHeartbeat()` 使用零长度数组
**文件**: `Can/snc_can_app.c:194`
```c
HAL_StatusTypeDef SNC_CAN_SendHeartbeat(void)
{
uint8_t data[0]; // ← 零长度数组C11 标准未定义行为
HAL_StatusTypeDef ret = snc_fdcan_add_tx_std(SNC_CAN_ID_HEARTBEAT, data, 0U);
```
零长度数组 `uint8_t data[0]` 在 C11 标准中是未定义行为C99 的 flexible array member 语法是 `[]` 且只能在结构体末尾)。虽然 GCC 作为扩展支持它,且 `snc_fdcan_add_tx_std` 传入 `dlc_bytes=0` 不会实际读取 `data`,但这仍属于未定义行为。
**修复建议**: 改为 `uint8_t data[1] = {0};` 或直接传 `NULL`(需确认 HAL 是否接受 NULL data
---
### M-5: 安全状态机 (SegFsm) 在脚本覆盖模式下仍然生效,可能干扰转弯等特殊动作
**文件**: `app_tasks.c` navTask 流水线 Step 5-6
```c
/* Step 5: 控制律 */
if (script_out.use_override) {
raw_cmd.v = script_out.override_v; // 脚本指定速度
raw_cmd.w = script_out.override_w;
} else if (script_out.request_corridor) {
CorridorCtrl_Compute(..., &raw_cmd);
}
/* Step 6: 段状态机 -> 安全仲裁 */
SegFsm_Update(&raw_cmd, &obs, &corridor_state, &fsm_out);
```
当脚本处于 `TURN_AT_END` 阶段时,`use_override = true`,输出 `v=0, w=turn_omega`(原地转向)。但此时 EKF 因侧墙观测丢失,`conf` 可能降到 `< 0.1`,触发 `SegFsm` 进入 `E-STOP`**强制将转向角速度归零**,导致机器人无法完成转弯。
虽然 `E-STOP` 有自动恢复机制(`conf >= 0.5` 时恢复),但在转弯过程中侧墙持续不可见,`conf` 不会恢复,造成**死锁**:转不了弯 → 永远看不到墙 → 永远 E-STOP。
**影响等级**: 实车中度风险。取决于转弯时 EKF 的 IMU 航向观测是否能维持 `conf >= 0.1`。如果 IMU 航向观测能阻止 `conf` 跌破阈值,则不会触发。但这是一个脆弱的依赖。
**修复建议**: 在 `SegFsm_Update()` 中增加一个 bypass 标志,当脚本处于 `use_override` 模式时跳过 E-STOP 判定;或仅在 `request_corridor` 为 true 时检查置信度。
---
### M-6: `process_complementary_laser()` 中 ATK 距离值无上限校验
**文件**: `preproc/corridor_preproc.c:30-73`
```c
static bool process_complementary_laser(const SensorItem_t *stp, const SensorItem_t *atk, float *out_m)
{
// ...
float atk_m = atk->value / 1000.0f;
// ATK 没有像 VL53 那样的量程校验 (0.02~2.0m)
// 如果 ATK 吐出异常大值 (如 65535mm),会被当作有效数据
```
`process_side_laser()` 对 VL53L0X 数据做了 `[0.02m, 2.0m]` 范围校验,但 `process_complementary_laser()` 对 ATK 和 STP 数据**没有上限校验**。如果 ATK 传感器吐出异常大值(如掉线前最后一帧的乱码),这个值会被当作有效距离传递给安全状态机,可能导致**该停车时不停车**。
**修复建议**: 添加 ATK/STP 的量程校验,如 `atk_m > 0.0f && atk_m <= 8.0f` (ATK 标称量程 4m留双倍余量)。
---
## 🟡 低优先级 / 代码质量问题
### L-1: `PARAM_IMU_YAW_OFFSET` 声明但未使用
**文件**: `robot_params.h:100`
```c
#define PARAM_IMU_YAW_OFFSET 0.0f // 声明了但代码中未使用
```
HANDOFF.md CAL-4 已标注此问题。如果 IMU 安装有固定偏角,此参数应在 `HWT101_Process()``corridor_filter.c` 中使用。当前为死代码。
---
### L-2: `corridor_filter.c` 中 `s_imu_yaw_ref_set` 在 Reset/Init 时未重置
**文件**: `est/corridor_filter.c:23-24`
```c
static float s_imu_yaw_ref_rad = 0.0f;
static bool s_imu_yaw_ref_set = false;
```
`CorridorFilter_Init()` 不会重置 `s_imu_yaw_ref_set`。如果比赛中途调用 `NavScript_Reset()``CorridorFilter_Init()` 重新初始化,旧的 `s_imu_yaw_ref_rad` 会保留,导致 IMU 航向观测使用过时的参考值。
**修复建议**: 在 `CorridorFilter_Init()` 末尾添加:
```c
s_imu_yaw_ref_rad = 0.0f;
s_imu_yaw_ref_set = false;
```
---
### L-3: `retarget.c` 中 `_write()` 的忙等循环可能阻塞调用任务
**文件**: `retarget.c:44-64`
```c
int _write(int file, char *ptr, int len)
{
while (1) {
result = CDC_Transmit_FS((uint8_t *)ptr, (uint16_t)len);
if (result == USBD_OK) return len;
if ((HAL_GetTick() - start_tick) > 20U) return 0;
if (osKernelGetState() == osKernelRunning) osDelay(1);
}
}
```
如果 USB CDC 端口忙碌Host 未连接或 buffer 满),`printf` 会阻塞当前任务最多 20ms。对于 `navTask`20ms 周期)和 `canTxTask`20ms 周期),一次 `printf` 阻塞就可能导致**整个控制周期跳过**。当前 `App_PrintStatus()` 已被注释掉,但如果未来取消注释或在其他任务中添加 `printf`,可能造成问题。
**修复建议**: 在实时任务中避免使用 `printf`,或将 `_write` 改为非阻塞(丢弃模式)。
---
### L-4: 多个模块重复定义 `clampf()` 静态内联函数
**文件**:
- `est/corridor_ekf.c:42`
- `nav/corridor_ctrl.c:12`
- `nav/nav_script.c:34`
- `nav/segment_fsm.c:12`
四个文件各自定义了相同的 `static inline float clampf()`。虽然由于 `static` 链接属性不会导致链接错误,但违反 DRY 原则。
**修复建议**: 提取到公共头文件 `robot_params.h` 或新建 `utils.h`
---
### L-5: `CorridorObs_t.valid_mask` 类型为 `uint8_t` 但掩码使用 bit 0-5 共 6 位
**文件**: `preproc/corridor_msgs.h:31``corridor_preproc.h:10-15`
当前 6 个掩码位刚好在 `uint8_t` 范围内(最大 bit 5 = 0x20但余量很小。如果未来添加更多传感器如第二组 VL53很容易溢出。不紧急但值得注意。
---
### L-6: `vl53_board.c:84` 注释与实际值不一致
```c
/* 初始化卡尔曼滤波器:默认 Q=1.0, R=9.5 */ // ← 注释说 Q=1.0, R=9.5
vl53_kalman_init(&board->kf[i], 10.0f, 14.1f); // ← 实际值 Q=10.0, R=14.1
```
注释是旧版残留,与当前代码不符。
---
### L-7: `nav_script.c:285` 使用 `exit_start_s == 0.0f` 判断是否已触发,但 `s` 初始值就是 0
```c
if (s_internal.exit_start_s == 0.0f) {
s_internal.exit_start_s = state->s;
}
```
如果恰好在 `state->s ≈ 0.0` 时进入 EXIT 阶段(理论上不会,因为已经往返走过垄沟),`exit_start_s` 会被设为 0然后下次循环 `== 0.0f` 再次为 true重复赋值但不会出错`state->s` 每次都差不多)。实际上因为 `memset(&s_internal, 0, ...)` 已将其初始化为 0.0,如果 EXIT 阶段被跳过再重入,可能出现意外行为。
**修复建议**: 使用 `bool exit_triggered` 标志代替浮点数零值判断。
---
## 架构设计审查
### 优点
1. **分层清晰**: 传感器驱动 → 黑板 → 预处理 → EKF → 控制 → 安全 → 指令槽,每层职责明确。
2. **线程安全设计合理**: 黑板的 `taskENTER_CRITICAL` + snapshot 模式有效防止了数据撕裂。
3. **传感器互补融合策略** (`process_complementary_laser`): STP+ATK 的互补逻辑考虑了盲区、单体故障、保守防撞等多种场景,设计周到。
4. **EKF 实现质量高**: 鲁棒 χ² 检验、分级观测更新1/2/3 DOF、协方差保护等机制完备。BUG-7卡尔曼增益矩阵乘法的修复正确。
5. **参数集中管理**: `robot_params.h` 作为唯一调参入口,大部分参数已正确引用(除 S-1 遗漏)。
6. **里程计累加器设计** (BUG-8 修复): ISR 累加 + 原子取走清零的设计有效解决了漏积分/重复积分问题。
### 可改进方向
1. **缺少 Watchdog**: 系统没有硬件看门狗 (IWDG/WWDG)。如果任何任务死锁或 HardFaultMCU 将永久挂起而不会自动重启。建议在空闲任务中喂看门狗。
2. **缺少运行时错误日志**: 当前的错误处理主要是"静默忽略"或"返回零值"。建议增加一个轻量级错误计数器或环形日志 buffer方便赛后分析。
3. **EKF 和安全状态机没有联动**: 如 M-5 所述,脚本覆盖模式下安全状态机可能干扰正常流程。建议在 `SegFsmOutput_t` 中增加 bypass 机制。
4. **`laserTestTask``osDelay(50)` 不精确**: 使用 `osDelay` 而非 `osDelayUntil`,任务执行时间会累加到周期中,导致实际周期 > 50ms。对于激光数据更新频率有影响。
---
## 已修复 BUG 验证
| HANDOFF 编号 | 修复内容 | 验证结果 |
|-------------|---------|---------|
| BUG-1 | IMU wz deg→rad 转换 | ✅ `app_tasks.c:305` 使用 `PARAM_DEG2RAD()` |
| BUG-2 | EKF Q/R/P0 从 params 读取 | ✅ `corridor_filter.c:50-66` 使用 `PARAM_EKF_*` |
| BUG-3 | `SegFsm_Start()` 调用 | ✅ `app_tasks.c:382` |
| BUG-4 | BACKWARD 段使用 d_front | ✅ `nav_script.c:254` |
| BUG-5 | 超时使用配置参数 | ✅ `nav_script.c:157` |
| BUG-6 | EXIT 速度独立参数 | ✅ `nav_script.c:273` 使用 `s_cfg.exit_v` |
| BUG-7 | 完整矩阵乘法 K=PHT*S_inv | ✅ `corridor_ekf.c:576-607` 两步乘法 |
| BUG-8 | 里程计累加器模式 | ✅ `snc_can_app.c` ISR 累加 + `ConsumeOdomDelta` 原子取走 |
| BUG-9 | IMU yaw unwrap + 连续角度 | ✅ `hwt101.c` unwrap 逻辑 + `nav_script.c` 使用 IMU yaw |
| Q-1~Q-7 | 各项代码质量修复 | ✅ 全部验证通过 |
---
## 修复优先级建议
| 优先级 | 编号 | 预估工时 |
|--------|------|---------|
| 立即修复 | S-4 (pack 对齐) | 5 分钟 |
| 立即修复 | S-1 (VL53 KF 参数) | 5 分钟 |
| 赛前修复 | M-5 (安全 FSM bypass) | 30 分钟 |
| 赛前修复 | M-6 (ATK 量程校验) | 10 分钟 |
| 赛前修复 | S-2 (快照线程安全) | 15 分钟 |
| 赛前修复 | L-2 (IMU ref 重置) | 5 分钟 |
| 确认配置 | S-3 (CAN 中断优先级) | 10 分钟 |
| 建议改进 | 其余所有 | 按需 |
---
> **审查结论**: 项目整体质量良好,架构设计规范,历史 BUG 修复彻底。上述 S-4 和 S-1 建议在下次烧录前立即修复M-5 (安全状态机与脚本冲突) 是实车测试中最可能暴露的问题,建议优先验证。

170
Core/Inc/FreeRTOSConfig.h Normal file
View File

@@ -0,0 +1,170 @@
/* USER CODE BEGIN Header */
/*
* FreeRTOS Kernel V10.3.1
* Portion Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Portion Copyright (C) 2019 StMicroelectronics, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/* USER CODE END Header */
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* These parameters and more are described within the 'configuration' section of the
* FreeRTOS API documentation available on the FreeRTOS.org web site.
*
* See http://www.freertos.org/a00110.html
*----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* Section where include file can be added */
/* USER CODE END Includes */
/* Ensure definitions are only used by the compiler, and not by the assembler. */
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
#include <stdint.h>
extern uint32_t SystemCoreClock;
#endif
#ifndef CMSIS_device_header
#define CMSIS_device_header "stm32h7xx.h"
#endif /* CMSIS_device_header */
#define configENABLE_FPU 0
#define configENABLE_MPU 0
#define configUSE_PREEMPTION 1
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ ((TickType_t)1000)
#define configMAX_PRIORITIES ( 56 )
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
#define configTOTAL_HEAP_SIZE ((size_t)65536)
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
/* USER CODE BEGIN MESSAGE_BUFFER_LENGTH_TYPE */
/* Defaults to size_t for backward compatibility, but can be changed
if lengths will always be less than the number of bytes in a size_t. */
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
/* USER CODE END MESSAGE_BUFFER_LENGTH_TYPE */
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Software timer definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( 2 )
#define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH 256
/* CMSIS-RTOS V2 flags */
#define configUSE_OS2_THREAD_SUSPEND_RESUME 1
#define configUSE_OS2_THREAD_ENUMERATE 1
#define configUSE_OS2_EVENTFLAGS_FROM_ISR 1
#define configUSE_OS2_THREAD_FLAGS 1
#define configUSE_OS2_TIMER 1
#define configUSE_OS2_MUTEX 1
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_xQueueGetMutexHolder 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_eTaskGetState 1
/*
* The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used
* by the application thus the correct define need to be enabled below
*/
#define USE_FreeRTOS_HEAP_4
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
/* USER CODE BEGIN 1 */
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
/* USER CODE END 1 */
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
/* IMPORTANT: After 10.3.1 update, Systick_Handler comes from NVIC (if SYS timebase = systick), otherwise from cmsis_os2.c */
#define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 0
/* USER CODE BEGIN Defines */
/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
/* USER CODE END Defines */
#endif /* FREERTOS_CONFIG_H */

52
Core/Inc/dma.h Normal file
View File

@@ -0,0 +1,52 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file dma.h
* @brief This file contains all the function prototypes for
* the dma.c file
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __DMA_H__
#define __DMA_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* DMA memory to memory transfer handles -------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_DMA_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __DMA_H__ */

52
Core/Inc/fdcan.h Normal file
View File

@@ -0,0 +1,52 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file fdcan.h
* @brief This file contains all the function prototypes for
* the fdcan.c file
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FDCAN_H__
#define __FDCAN_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern FDCAN_HandleTypeDef hfdcan1;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_FDCAN1_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __FDCAN_H__ */

49
Core/Inc/gpio.h Normal file
View File

@@ -0,0 +1,49 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file gpio.h
* @brief This file contains all the function prototypes for
* the gpio.c file
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __GPIO_H__
#define __GPIO_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_GPIO_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__ GPIO_H__ */

55
Core/Inc/i2c.h Normal file
View File

@@ -0,0 +1,55 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file i2c.h
* @brief This file contains all the function prototypes for
* the i2c.c file
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __I2C_H__
#define __I2C_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern I2C_HandleTypeDef hi2c1;
extern I2C_HandleTypeDef hi2c2;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_I2C1_Init(void);
void MX_I2C2_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __I2C_H__ */

69
Core/Inc/main.h Normal file
View File

@@ -0,0 +1,69 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32h7xx_hal.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */

View File

@@ -0,0 +1,514 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32h7xx_hal_conf.h
* @author MCD Application Team
* @brief HAL configuration file.
******************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef STM32H7xx_HAL_CONF_H
#define STM32H7xx_HAL_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* ########################## Module Selection ############################## */
/**
* @brief This is the list of modules to be used in the HAL driver
*/
#define HAL_MODULE_ENABLED
/* #define HAL_ADC_MODULE_ENABLED */
#define HAL_FDCAN_MODULE_ENABLED
/* #define HAL_FMAC_MODULE_ENABLED */
/* #define HAL_CEC_MODULE_ENABLED */
/* #define HAL_COMP_MODULE_ENABLED */
/* #define HAL_CORDIC_MODULE_ENABLED */
/* #define HAL_CRC_MODULE_ENABLED */
/* #define HAL_CRYP_MODULE_ENABLED */
/* #define HAL_DAC_MODULE_ENABLED */
/* #define HAL_DCMI_MODULE_ENABLED */
/* #define HAL_DMA2D_MODULE_ENABLED */
/* #define HAL_ETH_MODULE_ENABLED */
/* #define HAL_ETH_LEGACY_MODULE_ENABLED */
/* #define HAL_NAND_MODULE_ENABLED */
/* #define HAL_NOR_MODULE_ENABLED */
/* #define HAL_OTFDEC_MODULE_ENABLED */
/* #define HAL_SRAM_MODULE_ENABLED */
/* #define HAL_SDRAM_MODULE_ENABLED */
/* #define HAL_HASH_MODULE_ENABLED */
/* #define HAL_HRTIM_MODULE_ENABLED */
/* #define HAL_HSEM_MODULE_ENABLED */
/* #define HAL_GFXMMU_MODULE_ENABLED */
/* #define HAL_JPEG_MODULE_ENABLED */
/* #define HAL_OPAMP_MODULE_ENABLED */
/* #define HAL_OSPI_MODULE_ENABLED */
/* #define HAL_I2S_MODULE_ENABLED */
/* #define HAL_SMBUS_MODULE_ENABLED */
/* #define HAL_IWDG_MODULE_ENABLED */
/* #define HAL_LPTIM_MODULE_ENABLED */
/* #define HAL_LTDC_MODULE_ENABLED */
/* #define HAL_QSPI_MODULE_ENABLED */
/* #define HAL_RAMECC_MODULE_ENABLED */
/* #define HAL_RNG_MODULE_ENABLED */
/* #define HAL_RTC_MODULE_ENABLED */
/* #define HAL_SAI_MODULE_ENABLED */
/* #define HAL_SD_MODULE_ENABLED */
/* #define HAL_MMC_MODULE_ENABLED */
/* #define HAL_SPDIFRX_MODULE_ENABLED */
/* #define HAL_SPI_MODULE_ENABLED */
/* #define HAL_SWPMI_MODULE_ENABLED */
#define HAL_TIM_MODULE_ENABLED
#define HAL_UART_MODULE_ENABLED
/* #define HAL_USART_MODULE_ENABLED */
/* #define HAL_IRDA_MODULE_ENABLED */
/* #define HAL_SMARTCARD_MODULE_ENABLED */
/* #define HAL_WWDG_MODULE_ENABLED */
#define HAL_PCD_MODULE_ENABLED
/* #define HAL_HCD_MODULE_ENABLED */
/* #define HAL_DFSDM_MODULE_ENABLED */
/* #define HAL_DSI_MODULE_ENABLED */
/* #define HAL_JPEG_MODULE_ENABLED */
/* #define HAL_MDIOS_MODULE_ENABLED */
/* #define HAL_PSSI_MODULE_ENABLED */
/* #define HAL_DTS_MODULE_ENABLED */
#define HAL_GPIO_MODULE_ENABLED
#define HAL_DMA_MODULE_ENABLED
#define HAL_MDMA_MODULE_ENABLED
#define HAL_RCC_MODULE_ENABLED
#define HAL_FLASH_MODULE_ENABLED
#define HAL_EXTI_MODULE_ENABLED
#define HAL_PWR_MODULE_ENABLED
#define HAL_I2C_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
#define HAL_HSEM_MODULE_ENABLED
/* ########################## Oscillator Values adaptation ####################*/
/**
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE (25000000UL) /*!< Value of the External oscillator in Hz : FPGA case fixed to 60MHZ */
#endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT (100UL) /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */
/**
* @brief Internal oscillator (CSI) default value.
* This value is the default CSI value after Reset.
*/
#if !defined (CSI_VALUE)
#define CSI_VALUE (4000000UL) /*!< Value of the Internal oscillator in Hz*/
#endif /* CSI_VALUE */
/**
* @brief Internal High Speed oscillator (HSI) value.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL).
*/
#if !defined (HSI_VALUE)
#define HSI_VALUE (64000000UL) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @brief External Low Speed oscillator (LSE) value.
* This value is used by the UART, RTC HAL module to compute the system frequency
*/
#if !defined (LSE_VALUE)
#define LSE_VALUE (32768UL) /*!< Value of the External oscillator in Hz*/
#endif /* LSE_VALUE */
#if !defined (LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT (5000UL) /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */
#if !defined (LSI_VALUE)
#define LSI_VALUE (32000UL) /*!< LSI Typical Value in Hz*/
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations
in voltage and temperature.*/
/**
* @brief External clock source for I2S peripheral
* This value is used by the I2S HAL module to compute the I2S clock source
* frequency, this source is inserted directly through I2S_CKIN pad.
*/
#if !defined (EXTERNAL_CLOCK_VALUE)
#define EXTERNAL_CLOCK_VALUE 12288000UL /*!< Value of the External clock in Hz*/
#endif /* EXTERNAL_CLOCK_VALUE */
/* Tip: To avoid modifying this file each time you need to use different HSE,
=== you can define the HSE value in your toolchain compiler preprocessor. */
/* ########################### System Configuration ######################### */
/**
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE (3300UL) /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY (15UL) /*!< tick interrupt priority */
#define USE_RTOS 0
#define USE_SD_TRANSCEIVER 0U /*!< use uSD Transceiver */
#define USE_SPI_CRC 0U /*!< use CRC in SPI */
#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */
#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */
#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */
#define USE_HAL_CORDIC_REGISTER_CALLBACKS 0U /* CORDIC register callback disabled */
#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */
#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */
#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */
#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */
#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */
#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */
#define USE_HAL_DTS_REGISTER_CALLBACKS 0U /* DTS register callback disabled */
#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */
#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */
#define USE_HAL_FMAC_REGISTER_CALLBACKS 0U /* FMAC register callback disabled */
#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */
#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */
#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */
#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */
#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */
#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */
#define USE_HAL_GFXMMU_REGISTER_CALLBACKS 0U /* GFXMMU register callback disabled */
#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U /* HRTIM register callback disabled */
#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */
#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */
#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */
#define USE_HAL_JPEG_REGISTER_CALLBACKS 0U /* JPEG register callback disabled */
#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */
#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */
#define USE_HAL_MDIOS_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */
#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */
#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */
#define USE_HAL_OSPI_REGISTER_CALLBACKS 0U /* OSPI register callback disabled */
#define USE_HAL_OTFDEC_REGISTER_CALLBACKS 0U /* OTFDEC register callback disabled */
#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */
#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */
#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */
#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */
#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */
#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */
#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */
#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */
#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */
#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */
#define USE_HAL_SWPMI_REGISTER_CALLBACKS 0U /* SWPMI register callback disabled */
#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */
#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */
#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */
#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */
/* ########################### Ethernet Configuration ######################### */
#define ETH_TX_DESC_CNT 4U /* number of Ethernet Tx DMA descriptors */
#define ETH_RX_DESC_CNT 4U /* number of Ethernet Rx DMA descriptors */
#define ETH_MAC_ADDR0 (0x02UL)
#define ETH_MAC_ADDR1 (0x00UL)
#define ETH_MAC_ADDR2 (0x00UL)
#define ETH_MAC_ADDR3 (0x00UL)
#define ETH_MAC_ADDR4 (0x00UL)
#define ETH_MAC_ADDR5 (0x00UL)
/* ########################## Assert Selection ############################## */
/**
* @brief Uncomment the line below to expanse the "assert_param" macro in the
* HAL drivers code
*/
/* #define USE_FULL_ASSERT 1U */
/* Includes ------------------------------------------------------------------*/
/**
* @brief Include module's header file
*/
#ifdef HAL_RCC_MODULE_ENABLED
#include "stm32h7xx_hal_rcc.h"
#endif /* HAL_RCC_MODULE_ENABLED */
#ifdef HAL_GPIO_MODULE_ENABLED
#include "stm32h7xx_hal_gpio.h"
#endif /* HAL_GPIO_MODULE_ENABLED */
#ifdef HAL_DMA_MODULE_ENABLED
#include "stm32h7xx_hal_dma.h"
#endif /* HAL_DMA_MODULE_ENABLED */
#ifdef HAL_MDMA_MODULE_ENABLED
#include "stm32h7xx_hal_mdma.h"
#endif /* HAL_MDMA_MODULE_ENABLED */
#ifdef HAL_HASH_MODULE_ENABLED
#include "stm32h7xx_hal_hash.h"
#endif /* HAL_HASH_MODULE_ENABLED */
#ifdef HAL_DCMI_MODULE_ENABLED
#include "stm32h7xx_hal_dcmi.h"
#endif /* HAL_DCMI_MODULE_ENABLED */
#ifdef HAL_DMA2D_MODULE_ENABLED
#include "stm32h7xx_hal_dma2d.h"
#endif /* HAL_DMA2D_MODULE_ENABLED */
#ifdef HAL_DSI_MODULE_ENABLED
#include "stm32h7xx_hal_dsi.h"
#endif /* HAL_DSI_MODULE_ENABLED */
#ifdef HAL_DFSDM_MODULE_ENABLED
#include "stm32h7xx_hal_dfsdm.h"
#endif /* HAL_DFSDM_MODULE_ENABLED */
#ifdef HAL_DTS_MODULE_ENABLED
#include "stm32h7xx_hal_dts.h"
#endif /* HAL_DTS_MODULE_ENABLED */
#ifdef HAL_ETH_MODULE_ENABLED
#include "stm32h7xx_hal_eth.h"
#endif /* HAL_ETH_MODULE_ENABLED */
#ifdef HAL_ETH_LEGACY_MODULE_ENABLED
#include "stm32h7xx_hal_eth_legacy.h"
#endif /* HAL_ETH_LEGACY_MODULE_ENABLED */
#ifdef HAL_EXTI_MODULE_ENABLED
#include "stm32h7xx_hal_exti.h"
#endif /* HAL_EXTI_MODULE_ENABLED */
#ifdef HAL_CORTEX_MODULE_ENABLED
#include "stm32h7xx_hal_cortex.h"
#endif /* HAL_CORTEX_MODULE_ENABLED */
#ifdef HAL_ADC_MODULE_ENABLED
#include "stm32h7xx_hal_adc.h"
#endif /* HAL_ADC_MODULE_ENABLED */
#ifdef HAL_FDCAN_MODULE_ENABLED
#include "stm32h7xx_hal_fdcan.h"
#endif /* HAL_FDCAN_MODULE_ENABLED */
#ifdef HAL_CEC_MODULE_ENABLED
#include "stm32h7xx_hal_cec.h"
#endif /* HAL_CEC_MODULE_ENABLED */
#ifdef HAL_COMP_MODULE_ENABLED
#include "stm32h7xx_hal_comp.h"
#endif /* HAL_COMP_MODULE_ENABLED */
#ifdef HAL_CORDIC_MODULE_ENABLED
#include "stm32h7xx_hal_cordic.h"
#endif /* HAL_CORDIC_MODULE_ENABLED */
#ifdef HAL_CRC_MODULE_ENABLED
#include "stm32h7xx_hal_crc.h"
#endif /* HAL_CRC_MODULE_ENABLED */
#ifdef HAL_CRYP_MODULE_ENABLED
#include "stm32h7xx_hal_cryp.h"
#endif /* HAL_CRYP_MODULE_ENABLED */
#ifdef HAL_DAC_MODULE_ENABLED
#include "stm32h7xx_hal_dac.h"
#endif /* HAL_DAC_MODULE_ENABLED */
#ifdef HAL_FLASH_MODULE_ENABLED
#include "stm32h7xx_hal_flash.h"
#endif /* HAL_FLASH_MODULE_ENABLED */
#ifdef HAL_GFXMMU_MODULE_ENABLED
#include "stm32h7xx_hal_gfxmmu.h"
#endif /* HAL_GFXMMU_MODULE_ENABLED */
#ifdef HAL_FMAC_MODULE_ENABLED
#include "stm32h7xx_hal_fmac.h"
#endif /* HAL_FMAC_MODULE_ENABLED */
#ifdef HAL_HRTIM_MODULE_ENABLED
#include "stm32h7xx_hal_hrtim.h"
#endif /* HAL_HRTIM_MODULE_ENABLED */
#ifdef HAL_HSEM_MODULE_ENABLED
#include "stm32h7xx_hal_hsem.h"
#endif /* HAL_HSEM_MODULE_ENABLED */
#ifdef HAL_SRAM_MODULE_ENABLED
#include "stm32h7xx_hal_sram.h"
#endif /* HAL_SRAM_MODULE_ENABLED */
#ifdef HAL_NOR_MODULE_ENABLED
#include "stm32h7xx_hal_nor.h"
#endif /* HAL_NOR_MODULE_ENABLED */
#ifdef HAL_NAND_MODULE_ENABLED
#include "stm32h7xx_hal_nand.h"
#endif /* HAL_NAND_MODULE_ENABLED */
#ifdef HAL_I2C_MODULE_ENABLED
#include "stm32h7xx_hal_i2c.h"
#endif /* HAL_I2C_MODULE_ENABLED */
#ifdef HAL_I2S_MODULE_ENABLED
#include "stm32h7xx_hal_i2s.h"
#endif /* HAL_I2S_MODULE_ENABLED */
#ifdef HAL_IWDG_MODULE_ENABLED
#include "stm32h7xx_hal_iwdg.h"
#endif /* HAL_IWDG_MODULE_ENABLED */
#ifdef HAL_JPEG_MODULE_ENABLED
#include "stm32h7xx_hal_jpeg.h"
#endif /* HAL_JPEG_MODULE_ENABLED */
#ifdef HAL_MDIOS_MODULE_ENABLED
#include "stm32h7xx_hal_mdios.h"
#endif /* HAL_MDIOS_MODULE_ENABLED */
#ifdef HAL_MMC_MODULE_ENABLED
#include "stm32h7xx_hal_mmc.h"
#endif /* HAL_MMC_MODULE_ENABLED */
#ifdef HAL_LPTIM_MODULE_ENABLED
#include "stm32h7xx_hal_lptim.h"
#endif /* HAL_LPTIM_MODULE_ENABLED */
#ifdef HAL_LTDC_MODULE_ENABLED
#include "stm32h7xx_hal_ltdc.h"
#endif /* HAL_LTDC_MODULE_ENABLED */
#ifdef HAL_OPAMP_MODULE_ENABLED
#include "stm32h7xx_hal_opamp.h"
#endif /* HAL_OPAMP_MODULE_ENABLED */
#ifdef HAL_OSPI_MODULE_ENABLED
#include "stm32h7xx_hal_ospi.h"
#endif /* HAL_OSPI_MODULE_ENABLED */
#ifdef HAL_OTFDEC_MODULE_ENABLED
#include "stm32h7xx_hal_otfdec.h"
#endif /* HAL_OTFDEC_MODULE_ENABLED */
#ifdef HAL_PSSI_MODULE_ENABLED
#include "stm32h7xx_hal_pssi.h"
#endif /* HAL_PSSI_MODULE_ENABLED */
#ifdef HAL_PWR_MODULE_ENABLED
#include "stm32h7xx_hal_pwr.h"
#endif /* HAL_PWR_MODULE_ENABLED */
#ifdef HAL_QSPI_MODULE_ENABLED
#include "stm32h7xx_hal_qspi.h"
#endif /* HAL_QSPI_MODULE_ENABLED */
#ifdef HAL_RAMECC_MODULE_ENABLED
#include "stm32h7xx_hal_ramecc.h"
#endif /* HAL_RAMECC_MODULE_ENABLED */
#ifdef HAL_RNG_MODULE_ENABLED
#include "stm32h7xx_hal_rng.h"
#endif /* HAL_RNG_MODULE_ENABLED */
#ifdef HAL_RTC_MODULE_ENABLED
#include "stm32h7xx_hal_rtc.h"
#endif /* HAL_RTC_MODULE_ENABLED */
#ifdef HAL_SAI_MODULE_ENABLED
#include "stm32h7xx_hal_sai.h"
#endif /* HAL_SAI_MODULE_ENABLED */
#ifdef HAL_SD_MODULE_ENABLED
#include "stm32h7xx_hal_sd.h"
#endif /* HAL_SD_MODULE_ENABLED */
#ifdef HAL_SDRAM_MODULE_ENABLED
#include "stm32h7xx_hal_sdram.h"
#endif /* HAL_SDRAM_MODULE_ENABLED */
#ifdef HAL_SPI_MODULE_ENABLED
#include "stm32h7xx_hal_spi.h"
#endif /* HAL_SPI_MODULE_ENABLED */
#ifdef HAL_SPDIFRX_MODULE_ENABLED
#include "stm32h7xx_hal_spdifrx.h"
#endif /* HAL_SPDIFRX_MODULE_ENABLED */
#ifdef HAL_SWPMI_MODULE_ENABLED
#include "stm32h7xx_hal_swpmi.h"
#endif /* HAL_SWPMI_MODULE_ENABLED */
#ifdef HAL_TIM_MODULE_ENABLED
#include "stm32h7xx_hal_tim.h"
#endif /* HAL_TIM_MODULE_ENABLED */
#ifdef HAL_UART_MODULE_ENABLED
#include "stm32h7xx_hal_uart.h"
#endif /* HAL_UART_MODULE_ENABLED */
#ifdef HAL_USART_MODULE_ENABLED
#include "stm32h7xx_hal_usart.h"
#endif /* HAL_USART_MODULE_ENABLED */
#ifdef HAL_IRDA_MODULE_ENABLED
#include "stm32h7xx_hal_irda.h"
#endif /* HAL_IRDA_MODULE_ENABLED */
#ifdef HAL_SMARTCARD_MODULE_ENABLED
#include "stm32h7xx_hal_smartcard.h"
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
#ifdef HAL_SMBUS_MODULE_ENABLED
#include "stm32h7xx_hal_smbus.h"
#endif /* HAL_SMBUS_MODULE_ENABLED */
#ifdef HAL_WWDG_MODULE_ENABLED
#include "stm32h7xx_hal_wwdg.h"
#endif /* HAL_WWDG_MODULE_ENABLED */
#ifdef HAL_PCD_MODULE_ENABLED
#include "stm32h7xx_hal_pcd.h"
#endif /* HAL_PCD_MODULE_ENABLED */
#ifdef HAL_HCD_MODULE_ENABLED
#include "stm32h7xx_hal_hcd.h"
#endif /* HAL_HCD_MODULE_ENABLED */
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t *file, uint32_t line);
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
#ifdef __cplusplus
}
#endif
#endif /* STM32H7xx_HAL_CONF_H */

77
Core/Inc/stm32h7xx_it.h Normal file
View File

@@ -0,0 +1,77 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32h7xx_it.h
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32H7xx_IT_H
#define __STM32H7xx_IT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void DebugMon_Handler(void);
void DMA1_Stream0_IRQHandler(void);
void DMA1_Stream1_IRQHandler(void);
void DMA1_Stream2_IRQHandler(void);
void DMA1_Stream3_IRQHandler(void);
void DMA1_Stream4_IRQHandler(void);
void FDCAN1_IT0_IRQHandler(void);
void USART2_IRQHandler(void);
void USART3_IRQHandler(void);
void UART4_IRQHandler(void);
void TIM6_DAC_IRQHandler(void);
void TIM7_IRQHandler(void);
void USART6_IRQHandler(void);
void UART7_IRQHandler(void);
void OTG_FS_IRQHandler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
#ifdef __cplusplus
}
#endif
#endif /* __STM32H7xx_IT_H */

52
Core/Inc/tim.h Normal file
View File

@@ -0,0 +1,52 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file tim.h
* @brief This file contains all the function prototypes for
* the tim.c file
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TIM_H__
#define __TIM_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern TIM_HandleTypeDef htim6;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_TIM6_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __TIM_H__ */

70
Core/Inc/usart.h Normal file
View File

@@ -0,0 +1,70 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.h
* @brief This file contains all the function prototypes for
* the usart.c file
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern UART_HandleTypeDef huart4;
extern UART_HandleTypeDef huart5;
extern UART_HandleTypeDef huart7;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart3;
extern UART_HandleTypeDef huart6;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_UART4_Init(void);
void MX_UART5_Init(void);
void MX_UART7_Init(void);
void MX_USART1_UART_Init(void);
void MX_USART2_UART_Init(void);
void MX_USART3_UART_Init(void);
void MX_USART6_UART_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __USART_H__ */

52
Core/Inc/usb_otg.h Normal file
View File

@@ -0,0 +1,52 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usb_otg.h
* @brief This file contains all the function prototypes for
* the usb_otg.c file
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_OTG_H__
#define __USB_OTG_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_USB_OTG_FS_PCD_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __USB_OTG_H__ */

67
Core/Src/dma.c Normal file
View File

@@ -0,0 +1,67 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file dma.c
* @brief This file provides code for the configuration
* of all the requested memory to memory DMA transfers.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "dma.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure DMA */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/**
* Enable DMA controller clock
*/
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
/* DMA1_Stream1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
/* DMA1_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);
/* DMA1_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
/* DMA1_Stream4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
}
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */

149
Core/Src/fdcan.c Normal file
View File

@@ -0,0 +1,149 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file fdcan.c
* @brief This file provides code for the configuration
* of the FDCAN instances.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "fdcan.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
FDCAN_HandleTypeDef hfdcan1;
/* FDCAN1 init function */
void MX_FDCAN1_Init(void)
{
/* USER CODE BEGIN FDCAN1_Init 0 */
/* USER CODE END FDCAN1_Init 0 */
/* USER CODE BEGIN FDCAN1_Init 1 */
/* USER CODE END FDCAN1_Init 1 */
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = ENABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = DISABLE;
hfdcan1.Init.NominalPrescaler = 4;
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 13;
hfdcan1.Init.NominalTimeSeg2 = 2;
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 1;
hfdcan1.Init.DataTimeSeg1 = 1;
hfdcan1.Init.DataTimeSeg2 = 1;
hfdcan1.Init.MessageRAMOffset = 0;
hfdcan1.Init.StdFiltersNbr = 5;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.RxFifo0ElmtsNbr = 16;
hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxFifo1ElmtsNbr = 0;
hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxBuffersNbr = 0;
hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.TxEventsNbr = 0;
hfdcan1.Init.TxBuffersNbr = 0;
hfdcan1.Init.TxFifoQueueElmtsNbr = 8;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN FDCAN1_Init 2 */
/* USER CODE END FDCAN1_Init 2 */
}
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* fdcanHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
if(fdcanHandle->Instance==FDCAN1)
{
/* USER CODE BEGIN FDCAN1_MspInit 0 */
/* USER CODE END FDCAN1_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
PeriphClkInitStruct.FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* FDCAN1 clock enable */
__HAL_RCC_FDCAN_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**FDCAN1 GPIO Configuration
PD0 ------> FDCAN1_RX
PD1 ------> FDCAN1_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* FDCAN1 interrupt Init */
HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
/* USER CODE BEGIN FDCAN1_MspInit 1 */
/* USER CODE END FDCAN1_MspInit 1 */
}
}
void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* fdcanHandle)
{
if(fdcanHandle->Instance==FDCAN1)
{
/* USER CODE BEGIN FDCAN1_MspDeInit 0 */
/* USER CODE END FDCAN1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_FDCAN_CLK_DISABLE();
/**FDCAN1 GPIO Configuration
PD0 ------> FDCAN1_RX
PD1 ------> FDCAN1_TX
*/
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_0|GPIO_PIN_1);
/* FDCAN1 interrupt Deinit */
HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn);
/* USER CODE BEGIN FDCAN1_MspDeInit 1 */
/* USER CODE END FDCAN1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

301
Core/Src/freertos.c Normal file
View File

@@ -0,0 +1,301 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : freertos.c
* Description : Code for freertos applications
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "app_tasks.h"
#include "snc_can_app.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
/* 导航控制任务 (动态创建,不经 CubeMX 管理) */
static osThreadId_t navTaskHandle;
static const osThreadAttr_t navTask_attributes = {
.name = "navTask",
.stack_size = 1024 * 4,
.priority = (osPriority_t) osPriorityAboveNormal,
};
/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for canTxTask */
osThreadId_t canTxTaskHandle;
const osThreadAttr_t canTxTask_attributes = {
.name = "canTxTask",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityAboveNormal,
};
/* Definitions for monitorTask */
osThreadId_t monitorTaskHandle;
const osThreadAttr_t monitorTask_attributes = {
.name = "monitorTask",
.stack_size = 1024 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for laserTestTask */
osThreadId_t laserTestTaskHandle;
const osThreadAttr_t laserTestTask_attributes = {
.name = "laserTestTask",
.stack_size = 4096 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for vl53Task */
osThreadId_t vl53TaskHandle;
const osThreadAttr_t vl53Task_attributes = {
.name = "vl53Task",
.stack_size = 1024 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for imuTask */
osThreadId_t imuTaskHandle;
const osThreadAttr_t imuTask_attributes = {
.name = "imuTask",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityBelowNormal,
};
/* Definitions for logMutex */
osMutexId_t logMutexHandle;
const osMutexAttr_t logMutex_attributes = {
.name = "logMutex"
};
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
/* USER CODE END FunctionPrototypes */
void StartDefaultTask(void *argument);
void StartCanTxTask(void *argument);
void StartMonitorTask(void *argument);
void AppTasks_RunLaserTestTask(void *argument);
void StartVl53Task(void *argument);
void StartImuTask(void *argument);
extern void MX_USB_DEVICE_Init(void);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/**
* @brief FreeRTOS initialization
* @param None
* @retval None
*/
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
AppTasks_Init();
/* USER CODE END Init */
/* Create the mutex(es) */
/* creation of logMutex */
logMutexHandle = osMutexNew(&logMutex_attributes);
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* creation of defaultTask */
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
/* creation of canTxTask */
canTxTaskHandle = osThreadNew(StartCanTxTask, NULL, &canTxTask_attributes);
/* creation of monitorTask */
monitorTaskHandle = osThreadNew(StartMonitorTask, NULL, &monitorTask_attributes);
/* creation of laserTestTask */
laserTestTaskHandle = osThreadNew(AppTasks_RunLaserTestTask, NULL, &laserTestTask_attributes);
/* creation of vl53Task */
vl53TaskHandle = osThreadNew(StartVl53Task, NULL, &vl53Task_attributes);
/* creation of imuTask */
imuTaskHandle = osThreadNew(StartImuTask, NULL, &imuTask_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* 动态孵化导航控制任务,不需要在 CubeMX 中添加 */
navTaskHandle = osThreadNew(AppTasks_RunNavTask_Impl, NULL, &navTask_attributes);
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_EVENTS */
/* add events, ... */
/* USER CODE END RTOS_EVENTS */
}
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
/* init code for USB_DEVICE */
MX_USB_DEVICE_Init();
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;;)
{
osDelay(1);
}
/* USER CODE END StartDefaultTask */
}
/* USER CODE BEGIN Header_StartCanTxTask */
/**
* @brief Function implementing the canTxTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartCanTxTask */
void StartCanTxTask(void *argument)
{
/* USER CODE BEGIN StartCanTxTask */
/*
* 保持 CubeMX 生成的任务壳不变:
* 20ms 发送节拍与具体业务逻辑统一放在 app_tasks.c 中维护,
* 降低后续重新生成代码时的冲突风险。
*/
AppTasks_RunCanTxTask(argument);
/* USER CODE END StartCanTxTask */
}
/* USER CODE BEGIN Header_StartMonitorTask */
/**
* @brief Function implementing the monitorTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartMonitorTask */
void StartMonitorTask(void *argument)
{
/* USER CODE BEGIN StartMonitorTask */
/*
* 保持 CubeMX 生成的任务壳不变:
* 100ms 监控任务逻辑下沉到 app_tasks.c
* 这里仅做入口转发,便于与自动生成框架解耦。
*/
AppTasks_RunMonitorTask(argument);
// (void)argument;
// for (;;)
// {
// osDelay(1000);
// }
/* USER CODE END StartMonitorTask */
}
/* USER CODE BEGIN Header_AppTasks_RunLaserTestTask */
/**
* @brief Function implementing the laserTestTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_AppTasks_RunLaserTestTask */
void AppTasks_RunLaserTestTask(void *argument)
{
/* USER CODE BEGIN AppTasks_RunLaserTestTask */
/* Infinite loop */
// AppTasks_RunLaserTestTask_Impl(argument);
AppTasks_RunLaserTestTask_Impl(argument);
// (void)argument;
// for (;;)
// {
// osDelay(1000);
// }
/* USER CODE END AppTasks_RunLaserTestTask */
}
/* USER CODE BEGIN Header_StartVl53Task */
/**
* @brief Function implementing the vl53Task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartVl53Task */
void StartVl53Task(void *argument)
{
/* USER CODE BEGIN StartVl53Task */
/* Infinite loop */
AppTasks_RunVl53Task_Impl(argument);
/* USER CODE END StartVl53Task */
}
/* USER CODE BEGIN Header_StartImuTask */
/**
* @brief Function implementing the imuTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartImuTask */
void StartImuTask(void *argument)
{
/* USER CODE BEGIN StartImuTask */
/* Infinite loop */
AppTasks_RunImuTask_Impl(argument);
/* USER CODE END StartImuTask */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
/* USER CODE END Application */

100
Core/Src/gpio.c Normal file
View File

@@ -0,0 +1,100 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file gpio.c
* @brief This file provides code for the configuration
* of all used GPIO pins.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "gpio.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure GPIO */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/** Configure pins
PC14-OSC32_IN (OSC32_IN) ------> RCC_OSC32_IN
PC15-OSC32_OUT (OSC32_OUT) ------> RCC_OSC32_OUT
PH0-OSC_IN (PH0) ------> RCC_OSC_IN
PH1-OSC_OUT (PH1) ------> RCC_OSC_OUT
PA13 (JTMS/SWDIO) ------> DEBUG_JTMS-SWDIO
PA14 (JTCK/SWCLK) ------> DEBUG_JTCK-SWCLK
*/
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3|GPIO_PIN_4, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1|GPIO_PIN_2, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14, GPIO_PIN_RESET);
/*Configure GPIO pins : PE3 PE4 */
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/*Configure GPIO pin : PC5 */
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : PB1 PB2 */
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : PD11 PD12 PD13 PD14 */
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */

237
Core/Src/i2c.c Normal file
View File

@@ -0,0 +1,237 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file i2c.c
* @brief This file provides code for the configuration
* of the I2C instances.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "i2c.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
I2C_HandleTypeDef hi2c1;
I2C_HandleTypeDef hi2c2;
/* I2C1 init function */
void MX_I2C1_Init(void)
{
/* USER CODE BEGIN I2C1_Init 0 */
/* USER CODE END I2C1_Init 0 */
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x307075B1;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
/* I2C2 init function */
void MX_I2C2_Init(void)
{
/* USER CODE BEGIN I2C2_Init 0 */
/* USER CODE END I2C2_Init 0 */
/* USER CODE BEGIN I2C2_Init 1 */
/* USER CODE END I2C2_Init 1 */
hi2c2.Instance = I2C2;
hi2c2.Init.Timing = 0x307075B1;
hi2c2.Init.OwnAddress1 = 0;
hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c2.Init.OwnAddress2 = 0;
hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c2) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C2_Init 2 */
/* USER CODE END I2C2_Init 2 */
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
PeriphClkInitStruct.I2c123ClockSelection = RCC_I2C123CLKSOURCE_D2PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* I2C1 clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
else if(i2cHandle->Instance==I2C2)
{
/* USER CODE BEGIN I2C2_MspInit 0 */
/* USER CODE END I2C2_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C2;
PeriphClkInitStruct.I2c123ClockSelection = RCC_I2C123CLKSOURCE_D2PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C2 GPIO Configuration
PB10 ------> I2C2_SCL
PB11 ------> I2C2_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* I2C2 clock enable */
__HAL_RCC_I2C2_CLK_ENABLE();
/* USER CODE BEGIN I2C2_MspInit 1 */
/* USER CODE END I2C2_MspInit 1 */
}
}
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspDeInit 0 */
/* USER CODE END I2C1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_I2C1_CLK_DISABLE();
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7);
/* USER CODE BEGIN I2C1_MspDeInit 1 */
/* USER CODE END I2C1_MspDeInit 1 */
}
else if(i2cHandle->Instance==I2C2)
{
/* USER CODE BEGIN I2C2_MspDeInit 0 */
/* USER CODE END I2C2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_I2C2_CLK_DISABLE();
/**I2C2 GPIO Configuration
PB10 ------> I2C2_SCL
PB11 ------> I2C2_SDA
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_11);
/* USER CODE BEGIN I2C2_MspDeInit 1 */
/* USER CODE END I2C2_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

301
Core/Src/main.c Normal file
View File

@@ -0,0 +1,301 @@
/* USER CODE BEGIN Header */
#include "snc_can_app.h"
#include "usbd_cdc_if.h"
#include <stdio.h>
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"
#include "dma.h"
#include "fdcan.h"
#include "i2c.h"
#include "tim.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MPU_Config(void);
void MX_FREERTOS_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_FDCAN1_Init();
MX_TIM6_Init();
MX_I2C1_Init();
MX_I2C2_Init();
MX_UART4_Init();
MX_UART5_Init();
MX_UART7_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_USART3_UART_Init();
MX_USART6_UART_Init();
/* USER CODE BEGIN 2 */
MX_USB_DEVICE_Init();
/* USER CODE END 2 */
/* Init scheduler */
osKernelInitialize(); /* Call init function for freertos objects (in cmsis_os2.c) */
MX_FREERTOS_Init();
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 5;
RCC_OscInitStruct.PLL.PLLN = 192;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 15;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/*
* 保留中断接收链路:
* HAL FDCAN FIFO0 回调仅做桥接,把收到的帧交给协议层解析。
* 这样可避免与任务/主循环轮询形成双接收路径。
*/
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
SNC_CAN_RxFifo0Callback(hfdcan, RxFifo0ITs);
}
/* USER CODE END 4 */
/* MPU Configuration */
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
/* Disables the MPU */
HAL_MPU_Disable();
/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x0;
MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
MPU_InitStruct.SubRegionDisable = 0x87;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.BaseAddress = 0x30000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_32KB;
MPU_InitStruct.SubRegionDisable = 0x0;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enables the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
/**
* @brief Period elapsed callback in non blocking mode
* @note This function is called when TIM7 interrupt took place, inside
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
* a global variable "uwTick" used as application time base.
* @param htim : TIM handle
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM7)
{
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
/* USER CODE END Callback 1 */
}
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

View File

@@ -0,0 +1,83 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32h7xx_hal_msp.c
* @brief This file provides code for the MSP Initialization
* and de-Initialization codes.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN Define */
/* USER CODE END Define */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN Macro */
/* USER CODE END Macro */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* External functions --------------------------------------------------------*/
/* USER CODE BEGIN ExternalFunctions */
/* USER CODE END ExternalFunctions */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void)
{
/* USER CODE BEGIN MspInit 0 */
/* USER CODE END MspInit 0 */
__HAL_RCC_SYSCFG_CLK_ENABLE();
/* System interrupt init*/
/* PendSV_IRQn interrupt configuration */
HAL_NVIC_SetPriority(PendSV_IRQn, 15, 0);
/* USER CODE BEGIN MspInit 1 */
/* USER CODE END MspInit 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@@ -0,0 +1,130 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32h7xx_hal_timebase_tim.c
* @brief HAL time base based on the hardware TIM.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "stm32h7xx_hal.h"
#include "stm32h7xx_hal_tim.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim7;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief This function configures the TIM7 as a time base source.
* The time source is configured to have 1ms time base with a dedicated
* Tick interrupt priority.
* @note This function is called automatically at the beginning of program after
* reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
* @param TickPriority: Tick interrupt priority.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
RCC_ClkInitTypeDef clkconfig;
uint32_t uwTimclock, uwAPB1Prescaler;
uint32_t uwPrescalerValue;
uint32_t pFLatency;
/*Configure the TIM7 IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(TIM7_IRQn, TickPriority ,0);
/* Enable the TIM7 global Interrupt */
HAL_NVIC_EnableIRQ(TIM7_IRQn);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
/* Enable TIM7 clock */
__HAL_RCC_TIM7_CLK_ENABLE();
/* Get clock configuration */
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
/* Get APB1 prescaler */
uwAPB1Prescaler = clkconfig.APB1CLKDivider;
/* Compute TIM7 clock */
if (uwAPB1Prescaler == RCC_HCLK_DIV1)
{
uwTimclock = HAL_RCC_GetPCLK1Freq();
}
else
{
uwTimclock = 2UL * HAL_RCC_GetPCLK1Freq();
}
/* Compute the prescaler value to have TIM7 counter clock equal to 1MHz */
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);
/* Initialize TIM7 */
htim7.Instance = TIM7;
/* Initialize TIMx peripheral as follow:
* Period = [(TIM7CLK/1000) - 1]. to have a (1/1000) s time base.
* Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
* ClockDivision = 0
* Counter direction = Up
*/
htim7.Init.Period = (1000000U / 1000U) - 1U;
htim7.Init.Prescaler = uwPrescalerValue;
htim7.Init.ClockDivision = 0;
htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
if(HAL_TIM_Base_Init(&htim7) == HAL_OK)
{
/* Start the TIM time Base generation in interrupt mode */
return HAL_TIM_Base_Start_IT(&htim7);
}
/* Return function status */
return HAL_ERROR;
}
/**
* @brief Suspend Tick increment.
* @note Disable the tick increment by disabling TIM7 update interrupt.
* @param None
* @retval None
*/
void HAL_SuspendTick(void)
{
/* Disable TIM7 update Interrupt */
__HAL_TIM_DISABLE_IT(&htim7, TIM_IT_UPDATE);
}
/**
* @brief Resume Tick increment.
* @note Enable the tick increment by Enabling TIM7 update interrupt.
* @param None
* @retval None
*/
void HAL_ResumeTick(void)
{
/* Enable TIM7 Update interrupt */
__HAL_TIM_ENABLE_IT(&htim7, TIM_IT_UPDATE);
}

373
Core/Src/stm32h7xx_it.c Normal file
View File

@@ -0,0 +1,373 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32h7xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32h7xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
extern FDCAN_HandleTypeDef hfdcan1;
extern TIM_HandleTypeDef htim6;
extern DMA_HandleTypeDef hdma_uart4_rx;
extern DMA_HandleTypeDef hdma_uart7_rx;
extern DMA_HandleTypeDef hdma_usart2_rx;
extern DMA_HandleTypeDef hdma_usart3_rx;
extern DMA_HandleTypeDef hdma_usart6_rx;
extern UART_HandleTypeDef huart4;
extern UART_HandleTypeDef huart7;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart3;
extern UART_HandleTypeDef huart6;
extern TIM_HandleTypeDef htim7;
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
{
}
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Pre-fetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/******************************************************************************/
/* STM32H7xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32h7xx.s). */
/******************************************************************************/
/**
* @brief This function handles DMA1 stream0 global interrupt.
*/
void DMA1_Stream0_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream0_IRQn 0 */
/* USER CODE END DMA1_Stream0_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart2_rx);
/* USER CODE BEGIN DMA1_Stream0_IRQn 1 */
/* USER CODE END DMA1_Stream0_IRQn 1 */
}
/**
* @brief This function handles DMA1 stream1 global interrupt.
*/
void DMA1_Stream1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream1_IRQn 0 */
/* USER CODE END DMA1_Stream1_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_uart4_rx);
/* USER CODE BEGIN DMA1_Stream1_IRQn 1 */
/* USER CODE END DMA1_Stream1_IRQn 1 */
}
/**
* @brief This function handles DMA1 stream2 global interrupt.
*/
void DMA1_Stream2_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream2_IRQn 0 */
/* USER CODE END DMA1_Stream2_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart3_rx);
/* USER CODE BEGIN DMA1_Stream2_IRQn 1 */
/* USER CODE END DMA1_Stream2_IRQn 1 */
}
/**
* @brief This function handles DMA1 stream3 global interrupt.
*/
void DMA1_Stream3_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream3_IRQn 0 */
/* USER CODE END DMA1_Stream3_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart6_rx);
/* USER CODE BEGIN DMA1_Stream3_IRQn 1 */
/* USER CODE END DMA1_Stream3_IRQn 1 */
}
/**
* @brief This function handles DMA1 stream4 global interrupt.
*/
void DMA1_Stream4_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream4_IRQn 0 */
/* USER CODE END DMA1_Stream4_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_uart7_rx);
/* USER CODE BEGIN DMA1_Stream4_IRQn 1 */
/* USER CODE END DMA1_Stream4_IRQn 1 */
}
/**
* @brief This function handles FDCAN1 interrupt 0.
*/
void FDCAN1_IT0_IRQHandler(void)
{
/* USER CODE BEGIN FDCAN1_IT0_IRQn 0 */
/* USER CODE END FDCAN1_IT0_IRQn 0 */
HAL_FDCAN_IRQHandler(&hfdcan1);
/* USER CODE BEGIN FDCAN1_IT0_IRQn 1 */
/* USER CODE END FDCAN1_IT0_IRQn 1 */
}
/**
* @brief This function handles USART2 global interrupt.
*/
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
/**
* @brief This function handles USART3 global interrupt.
*/
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&huart3);
/* USER CODE BEGIN USART3_IRQn 1 */
/* USER CODE END USART3_IRQn 1 */
}
/**
* @brief This function handles UART4 global interrupt.
*/
void UART4_IRQHandler(void)
{
/* USER CODE BEGIN UART4_IRQn 0 */
/* USER CODE END UART4_IRQn 0 */
HAL_UART_IRQHandler(&huart4);
/* USER CODE BEGIN UART4_IRQn 1 */
/* USER CODE END UART4_IRQn 1 */
}
/**
* @brief This function handles TIM6 global interrupt, DAC1_CH1 and DAC1_CH2 underrun error interrupts.
*/
void TIM6_DAC_IRQHandler(void)
{
/* USER CODE BEGIN TIM6_DAC_IRQn 0 */
/* USER CODE END TIM6_DAC_IRQn 0 */
HAL_TIM_IRQHandler(&htim6);
/* USER CODE BEGIN TIM6_DAC_IRQn 1 */
/* USER CODE END TIM6_DAC_IRQn 1 */
}
/**
* @brief This function handles TIM7 global interrupt.
*/
void TIM7_IRQHandler(void)
{
/* USER CODE BEGIN TIM7_IRQn 0 */
/* USER CODE END TIM7_IRQn 0 */
HAL_TIM_IRQHandler(&htim7);
/* USER CODE BEGIN TIM7_IRQn 1 */
/* USER CODE END TIM7_IRQn 1 */
}
/**
* @brief This function handles USART6 global interrupt.
*/
void USART6_IRQHandler(void)
{
/* USER CODE BEGIN USART6_IRQn 0 */
/* USER CODE END USART6_IRQn 0 */
HAL_UART_IRQHandler(&huart6);
/* USER CODE BEGIN USART6_IRQn 1 */
/* USER CODE END USART6_IRQn 1 */
}
/**
* @brief This function handles UART7 global interrupt.
*/
void UART7_IRQHandler(void)
{
/* USER CODE BEGIN UART7_IRQn 0 */
/* USER CODE END UART7_IRQn 0 */
HAL_UART_IRQHandler(&huart7);
/* USER CODE BEGIN UART7_IRQn 1 */
/* USER CODE END UART7_IRQn 1 */
}
/**
* @brief This function handles USB On The Go FS global interrupt.
*/
void OTG_FS_IRQHandler(void)
{
/* USER CODE BEGIN OTG_FS_IRQn 0 */
/* USER CODE END OTG_FS_IRQn 0 */
HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
/* USER CODE BEGIN OTG_FS_IRQn 1 */
/* USER CODE END OTG_FS_IRQn 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

244
Core/Src/syscalls.c Normal file
View File

@@ -0,0 +1,244 @@
/**
******************************************************************************
* @file syscalls.c
* @author Auto-generated by STM32CubeMX
* @brief Minimal System calls file
*
* For more information about which c-functions
* need which of these lowlevel functions
* please consult the Newlib or Picolibc libc-manual
******************************************************************************
* @attention
*
* Copyright (c) 2020-2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes */
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>
/* Variables */
extern int __io_putchar(int ch) __attribute__((weak));
extern int __io_getchar(void) __attribute__((weak));
char *__env[1] = { 0 };
char **environ = __env;
/* Functions */
void initialise_monitor_handles()
{
}
int _getpid(void)
{
return 1;
}
int _kill(int pid, int sig)
{
(void)pid;
(void)sig;
errno = EINVAL;
return -1;
}
void _exit (int status)
{
_kill(status, -1);
while (1) {} /* Make sure we hang here */
}
__attribute__((weak)) int _read(int file, char *ptr, int len)
{
(void)file;
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++)
{
*ptr++ = __io_getchar();
}
return len;
}
__attribute__((weak)) int _write(int file, char *ptr, int len)
{
(void)file;
int DataIdx;
for (DataIdx = 0; DataIdx < len; DataIdx++)
{
__io_putchar(*ptr++);
}
return len;
}
int _close(int file)
{
(void)file;
return -1;
}
int _fstat(int file, struct stat *st)
{
(void)file;
st->st_mode = S_IFCHR;
return 0;
}
int _isatty(int file)
{
(void)file;
return 1;
}
int _lseek(int file, int ptr, int dir)
{
(void)file;
(void)ptr;
(void)dir;
return 0;
}
int _open(char *path, int flags, ...)
{
(void)path;
(void)flags;
/* Pretend like we always fail */
return -1;
}
int _wait(int *status)
{
(void)status;
errno = ECHILD;
return -1;
}
int _unlink(char *name)
{
(void)name;
errno = ENOENT;
return -1;
}
clock_t _times(struct tms *buf)
{
(void)buf;
return -1;
}
int _stat(const char *file, struct stat *st)
{
(void)file;
st->st_mode = S_IFCHR;
return 0;
}
int _link(char *old, char *new)
{
(void)old;
(void)new;
errno = EMLINK;
return -1;
}
int _fork(void)
{
errno = EAGAIN;
return -1;
}
int _execve(char *name, char **argv, char **env)
{
(void)name;
(void)argv;
(void)env;
errno = ENOMEM;
return -1;
}
// --- Picolibc Specific Section ---
#if defined(__PICOLIBC__)
/**
* @brief Picolibc helper function to output a character to a FILE stream.
* This redirects the output to the low-level __io_putchar function.
* @param c Character to write.
* @param file FILE stream pointer (ignored).
* @retval int The character written.
*/
static int starm_putc(char c, FILE *file)
{
(void) file;
__io_putchar(c);
return c;
}
/**
* @brief Picolibc helper function to input a character from a FILE stream.
* This redirects the input from the low-level __io_getchar function.
* @param file FILE stream pointer (ignored).
* @retval int The character read, cast to an unsigned char then int.
*/
static int starm_getc(FILE *file)
{
unsigned char c;
(void) file;
c = __io_getchar();
return c;
}
// Define and initialize the standard I/O streams for Picolibc.
// FDEV_SETUP_STREAM connects the starm_putc and starm_getc helper functions to a FILE structure.
// _FDEV_SETUP_RW indicates the stream is for reading and writing.
static FILE __stdio = FDEV_SETUP_STREAM(starm_putc,
starm_getc,
NULL,
_FDEV_SETUP_RW);
// Assign the standard stream pointers (stdin, stdout, stderr) to the initialized stream.
// Picolibc uses these pointers for standard I/O operations (printf, scanf, etc.).
FILE *const stdin = &__stdio;
__strong_reference(stdin, stdout);
__strong_reference(stdin, stderr);
// Create strong aliases mapping standard C library function names (without underscore)
// to the implemented system call stubs (with underscore). Picolibc uses these
// standard names internally, so this linking is required.
__strong_reference(_read, read);
__strong_reference(_write, write);
__strong_reference(_times, times);
__strong_reference(_execve, execve);
__strong_reference(_fork, fork);
__strong_reference(_link, link);
__strong_reference(_unlink, unlink);
__strong_reference(_stat, stat);
__strong_reference(_wait, wait);
__strong_reference(_open, open);
__strong_reference(_close, close);
__strong_reference(_lseek, lseek);
__strong_reference(_isatty, isatty);
__strong_reference(_fstat, fstat);
__strong_reference(_exit, exit);
__strong_reference(_kill, kill);
__strong_reference(_getpid, getpid);
#endif //__PICOLIBC__

87
Core/Src/sysmem.c Normal file
View File

@@ -0,0 +1,87 @@
/**
******************************************************************************
* @file sysmem.c
* @author Generated by STM32CubeMX
* @brief System Memory calls file
*
* For more information about which C functions
* need which of these lowlevel functions
* please consult the Newlib or Picolibc libc manual
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes */
#include <errno.h>
#include <stdint.h>
#include <stddef.h>
/**
* Pointer to the current high watermark of the heap usage
*/
static uint8_t *__sbrk_heap_end = NULL;
/**
* @brief _sbrk() allocates memory to the newlib heap and is used by malloc
* and others from the C library
*
* @verbatim
* ############################################################################
* # .data # .bss # newlib heap # MSP stack #
* # # # # Reserved by _Min_Stack_Size #
* ############################################################################
* ^-- RAM start ^-- _end _estack, RAM end --^
* @endverbatim
*
* This implementation starts allocating at the '_end' linker symbol
* The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack
* The implementation considers '_estack' linker symbol to be RAM end
* NOTE: If the MSP stack, at any point during execution, grows larger than the
* reserved size, please increase the '_Min_Stack_Size'.
*
* @param incr Memory size
* @return Pointer to allocated memory
*/
void *_sbrk(ptrdiff_t incr)
{
extern uint8_t _end; /* Symbol defined in the linker script */
extern uint8_t _estack; /* Symbol defined in the linker script */
extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */
const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size;
const uint8_t *max_heap = (uint8_t *)stack_limit;
uint8_t *prev_heap_end;
/* Initialize heap end at first call */
if (NULL == __sbrk_heap_end)
{
__sbrk_heap_end = &_end;
}
/* Protect heap from growing into the reserved MSP stack */
if (__sbrk_heap_end + incr > max_heap)
{
errno = ENOMEM;
return (void *)-1;
}
prev_heap_end = __sbrk_heap_end;
__sbrk_heap_end += incr;
return (void *)prev_heap_end;
}
#if defined(__PICOLIBC__)
// Picolibc expects syscalls without the leading underscore.
// This creates a strong alias so that
// calls to `sbrk()` are resolved to our `_sbrk()` implementation.
__strong_reference(_sbrk, sbrk);
#endif

556
Core/Src/system_stm32h7xx.c Normal file
View File

@@ -0,0 +1,556 @@
/**
******************************************************************************
* @file system_stm32h7xx.c
* @author MCD Application Team
* @brief CMSIS Cortex-Mx Device Peripheral Access Layer System Source File.
*
* This file provides two functions and one global variable to be called from
* user application:
* - ExitRun0Mode(): Specifies the Power Supply source. This function is
* called at startup just after reset and before the call
* of SystemInit(). This call is made inside
* the "startup_stm32h7xx.s" file.
*
* - SystemInit(): This function is called at startup just after reset and
* before branch to main program. This call is made inside
* the "startup_stm32h7xx.s" file.
*
* - SystemCoreClock variable: Contains the core clock, it can be used
* by the user application to setup the SysTick
* timer or configure other parameters.
*
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
* be called whenever the core clock is changed
* during program execution.
*
*
******************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup stm32h7xx_system
* @{
*/
/** @addtogroup STM32H7xx_System_Private_Includes
* @{
*/
#include "stm32h7xx.h"
#include <math.h>
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (CSI_VALUE)
#define CSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* CSI_VALUE */
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)64000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @}
*/
/** @addtogroup STM32H7xx_System_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @addtogroup STM32H7xx_System_Private_Defines
* @{
*/
/************************* Miscellaneous Configuration ************************/
/*!< Uncomment the following line if you need to use initialized data in D2 domain SRAM (AHB SRAM) */
/* #define DATA_IN_D2_SRAM */
/* Note: Following vector table addresses must be defined in line with linker
configuration. */
/*!< Uncomment the following line if you need to relocate the vector table
anywhere in FLASH BANK1 or AXI SRAM, else the vector table is kept at the automatic
remap of boot address selected */
/* #define USER_VECT_TAB_ADDRESS */
#if defined(USER_VECT_TAB_ADDRESS)
#if defined(DUAL_CORE) && defined(CORE_CM4)
/*!< Uncomment the following line if you need to relocate your vector Table
in D2 AXI SRAM else user remap will be done in FLASH BANK2. */
/* #define VECT_TAB_SRAM */
#if defined(VECT_TAB_SRAM)
#define VECT_TAB_BASE_ADDRESS D2_AXISRAM_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x400. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x400. */
#else
#define VECT_TAB_BASE_ADDRESS FLASH_BANK2_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x400. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x400. */
#endif /* VECT_TAB_SRAM */
#else
/*!< Uncomment the following line if you need to relocate your vector Table
in D1 AXI SRAM else user remap will be done in FLASH BANK1. */
/* #define VECT_TAB_SRAM */
#if defined(VECT_TAB_SRAM)
#define VECT_TAB_BASE_ADDRESS D1_AXISRAM_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x400. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x400. */
#else
#define VECT_TAB_BASE_ADDRESS FLASH_BANK1_BASE /*!< Vector Table base address field.
This value must be a multiple of 0x400. */
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
This value must be a multiple of 0x400. */
#endif /* VECT_TAB_SRAM */
#endif /* DUAL_CORE && CORE_CM4 */
#endif /* USER_VECT_TAB_ADDRESS */
/******************************************************************************/
/**
* @}
*/
/** @addtogroup STM32H7xx_System_Private_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32H7xx_System_Private_Variables
* @{
*/
/* This variable is updated in three ways:
1) by calling CMSIS function SystemCoreClockUpdate()
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
Note: If you use this function to configure the system clock; then there
is no need to call the 2 first functions listed above, since SystemCoreClock
variable is updated automatically.
*/
uint32_t SystemCoreClock = 64000000;
uint32_t SystemD2Clock = 64000000;
const uint8_t D1CorePrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
/**
* @}
*/
/** @addtogroup STM32H7xx_System_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @addtogroup STM32H7xx_System_Private_Functions
* @{
*/
/**
* @brief Setup the microcontroller system
* Initialize the FPU setting and vector table location
* configuration.
* @param None
* @retval None
*/
void SystemInit (void)
{
#if defined (DATA_IN_D2_SRAM)
__IO uint32_t tmpreg;
#endif /* DATA_IN_D2_SRAM */
/* 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 RCC clock configuration to the default reset state ------------*/
/* Increasing the CPU frequency */
if(FLASH_LATENCY_DEFAULT > (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
{
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
}
/* Set HSION bit */
RCC->CR |= RCC_CR_HSION;
/* Reset CFGR register */
RCC->CFGR = 0x00000000;
/* Reset HSEON, HSECSSON, CSION, HSI48ON, CSIKERON, PLL1ON, PLL2ON and PLL3ON bits */
RCC->CR &= 0xEAF6ED7FU;
/* Decreasing the number of wait states because of lower CPU frequency */
if(FLASH_LATENCY_DEFAULT < (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
{
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
}
#if defined(D3_SRAM_BASE)
/* Reset D1CFGR register */
RCC->D1CFGR = 0x00000000;
/* Reset D2CFGR register */
RCC->D2CFGR = 0x00000000;
/* Reset D3CFGR register */
RCC->D3CFGR = 0x00000000;
#else
/* Reset CDCFGR1 register */
RCC->CDCFGR1 = 0x00000000;
/* Reset CDCFGR2 register */
RCC->CDCFGR2 = 0x00000000;
/* Reset SRDCFGR register */
RCC->SRDCFGR = 0x00000000;
#endif
/* Reset PLLCKSELR register */
RCC->PLLCKSELR = 0x02020200;
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x01FF0000;
/* Reset PLL1DIVR register */
RCC->PLL1DIVR = 0x01010280;
/* Reset PLL1FRACR register */
RCC->PLL1FRACR = 0x00000000;
/* Reset PLL2DIVR register */
RCC->PLL2DIVR = 0x01010280;
/* Reset PLL2FRACR register */
RCC->PLL2FRACR = 0x00000000;
/* Reset PLL3DIVR register */
RCC->PLL3DIVR = 0x01010280;
/* Reset PLL3FRACR register */
RCC->PLL3FRACR = 0x00000000;
/* Reset HSEBYP bit */
RCC->CR &= 0xFFFBFFFFU;
/* Disable all interrupts */
RCC->CIER = 0x00000000;
#if (STM32H7_DEV_ID == 0x450UL)
/* dual core CM7 or single core line */
if((DBGMCU->IDCODE & 0xFFFF0000U) < 0x20000000U)
{
/* if stm32h7 revY*/
/* Change the switch matrix read issuing capability to 1 for the AXI SRAM target (Target 7) */
*((__IO uint32_t*)0x51008108) = 0x000000001U;
}
#endif /* STM32H7_DEV_ID */
#if defined(DATA_IN_D2_SRAM)
/* in case of initialized data in D2 SRAM (AHB SRAM), enable the D2 SRAM clock (AHB SRAM clock) */
#if defined(RCC_AHB2ENR_D2SRAM3EN)
RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN);
#elif defined(RCC_AHB2ENR_D2SRAM2EN)
RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN);
#else
RCC->AHB2ENR |= (RCC_AHB2ENR_AHBSRAM1EN | RCC_AHB2ENR_AHBSRAM2EN);
#endif /* RCC_AHB2ENR_D2SRAM3EN */
tmpreg = RCC->AHB2ENR;
(void) tmpreg;
#endif /* DATA_IN_D2_SRAM */
#if defined(DUAL_CORE) && defined(CORE_CM4)
/* Configure the Vector Table location add offset address for cortex-M4 ------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D2 AXI-RAM or in Internal FLASH */
#endif /* USER_VECT_TAB_ADDRESS */
#else
if(READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN) == 0U)
{
/* Enable the FMC interface clock */
SET_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
/*
* Disable the FMC bank1 (enabled after reset).
* This, prevents CPU speculation access on this bank which blocks the use of FMC during
* 24us. During this time the others FMC master (such as LTDC) cannot use it!
*/
FMC_Bank1_R->BTCR[0] = 0x000030D2;
/* Disable the FMC interface clock */
CLEAR_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
}
/* Configure the Vector Table location -------------------------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D1 AXI-RAM or in Internal FLASH */
#endif /* USER_VECT_TAB_ADDRESS */
#endif /*DUAL_CORE && CORE_CM4*/
}
/**
* @brief Update SystemCoreClock variable according to Clock Register Values.
* The SystemCoreClock variable contains the core clock , it can
* be used by the user application to setup the SysTick timer or configure
* other parameters.
*
* @note Each time the core clock changes, this function must be called
* to update SystemCoreClock variable value. Otherwise, any configuration
* based on this variable will be incorrect.
*
* @note - The system frequency computed by this function is not the real
* frequency in the chip. It is calculated based on the predefined
* constant and the selected clock source:
*
* - If SYSCLK source is CSI, SystemCoreClock will contain the CSI_VALUE(*)
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**)
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
* - If SYSCLK source is PLL, SystemCoreClock will contain the CSI_VALUE(*),
* HSI_VALUE(**) or HSE_VALUE(***) multiplied/divided by the PLL factors.
*
* (*) CSI_VALUE is a constant defined in stm32h7xx_hal.h file (default value
* 4 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
* (**) HSI_VALUE is a constant defined in stm32h7xx_hal.h file (default value
* 64 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
*
* (***)HSE_VALUE is a constant defined in stm32h7xx_hal.h file (default value
* 25 MHz), user has to ensure that HSE_VALUE is same as the real
* frequency of the crystal used. Otherwise, this function may
* have wrong result.
*
* - The result of this function could be not correct when using fractional
* value for HSE crystal.
* @param None
* @retval None
*/
void SystemCoreClockUpdate (void)
{
uint32_t pllp, pllsource, pllm, pllfracen, hsivalue, tmp;
uint32_t common_system_clock;
float_t fracn1, pllvco;
/* Get SYSCLK source -------------------------------------------------------*/
switch (RCC->CFGR & RCC_CFGR_SWS)
{
case RCC_CFGR_SWS_HSI: /* HSI used as system clock source */
common_system_clock = (uint32_t) (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3));
break;
case RCC_CFGR_SWS_CSI: /* CSI used as system clock source */
common_system_clock = CSI_VALUE;
break;
case RCC_CFGR_SWS_HSE: /* HSE used as system clock source */
common_system_clock = HSE_VALUE;
break;
case RCC_CFGR_SWS_PLL1: /* PLL1 used as system clock source */
/* PLL_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLLM) * PLLN
SYSCLK = PLL_VCO / PLLR
*/
pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC);
pllm = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM1)>> 4) ;
pllfracen = ((RCC->PLLCFGR & RCC_PLLCFGR_PLL1FRACEN)>>RCC_PLLCFGR_PLL1FRACEN_Pos);
fracn1 = (float_t)(uint32_t)(pllfracen* ((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN1)>> 3));
if (pllm != 0U)
{
switch (pllsource)
{
case RCC_PLLCKSELR_PLLSRC_HSI: /* HSI used as PLL clock source */
hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3)) ;
pllvco = ( (float_t)hsivalue / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 );
break;
case RCC_PLLCKSELR_PLLSRC_CSI: /* CSI used as PLL clock source */
pllvco = ((float_t)CSI_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 );
break;
case RCC_PLLCKSELR_PLLSRC_HSE: /* HSE used as PLL clock source */
pllvco = ((float_t)HSE_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 );
break;
default:
hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3)) ;
pllvco = ((float_t)hsivalue / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 );
break;
}
pllp = (((RCC->PLL1DIVR & RCC_PLL1DIVR_P1) >>9) + 1U ) ;
common_system_clock = (uint32_t)(float_t)(pllvco/(float_t)pllp);
}
else
{
common_system_clock = 0U;
}
break;
default:
common_system_clock = (uint32_t) (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3));
break;
}
/* Compute SystemClock frequency --------------------------------------------------*/
#if defined (RCC_D1CFGR_D1CPRE)
tmp = D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_D1CPRE)>> RCC_D1CFGR_D1CPRE_Pos];
/* common_system_clock frequency : CM7 CPU frequency */
common_system_clock >>= tmp;
/* SystemD2Clock frequency : CM4 CPU, AXI and AHBs Clock frequency */
SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_HPRE)>> RCC_D1CFGR_HPRE_Pos]) & 0x1FU));
#else
tmp = D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_CDCPRE)>> RCC_CDCFGR1_CDCPRE_Pos];
/* common_system_clock frequency : CM7 CPU frequency */
common_system_clock >>= tmp;
/* SystemD2Clock frequency : AXI and AHBs Clock frequency */
SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_HPRE)>> RCC_CDCFGR1_HPRE_Pos]) & 0x1FU));
#endif
#if defined(DUAL_CORE) && defined(CORE_CM4)
SystemCoreClock = SystemD2Clock;
#else
SystemCoreClock = common_system_clock;
#endif /* DUAL_CORE && CORE_CM4 */
}
/**
* @brief Exit Run* mode and Configure the system Power Supply
*
* @note This function exits the Run* mode and configures the system power supply
* according to the definition to be used at compilation preprocessing level.
* The application shall set one of the following configuration option:
* - PWR_LDO_SUPPLY
* - PWR_DIRECT_SMPS_SUPPLY
* - PWR_EXTERNAL_SOURCE_SUPPLY
* - PWR_SMPS_1V8_SUPPLIES_LDO
* - PWR_SMPS_2V5_SUPPLIES_LDO
* - PWR_SMPS_1V8_SUPPLIES_EXT_AND_LDO
* - PWR_SMPS_2V5_SUPPLIES_EXT_AND_LDO
* - PWR_SMPS_1V8_SUPPLIES_EXT
* - PWR_SMPS_2V5_SUPPLIES_EXT
*
* @note The function modifies the PWR->CR3 register to enable or disable specific
* power supply modes and waits until the voltage level flag is set, indicating
* that the power supply configuration is stable.
*
* @param None
* @retval None
*/
void ExitRun0Mode(void)
{
#if defined(USE_PWR_LDO_SUPPLY)
#if defined(SMPS)
/* Exit Run* mode by disabling SMPS and enabling LDO */
PWR->CR3 = (PWR->CR3 & ~PWR_CR3_SMPSEN) | PWR_CR3_LDOEN;
#else
/* Enable LDO mode */
PWR->CR3 |= PWR_CR3_LDOEN;
#endif /* SMPS */
/* Wait till voltage level flag is set */
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
{}
#elif defined(USE_PWR_EXTERNAL_SOURCE_SUPPLY)
#if defined(SMPS)
/* Exit Run* mode */
PWR->CR3 = (PWR->CR3 & ~(PWR_CR3_SMPSEN | PWR_CR3_LDOEN)) | PWR_CR3_BYPASS;
#else
PWR->CR3 = (PWR->CR3 & ~(PWR_CR3_LDOEN)) | PWR_CR3_BYPASS;
#endif /* SMPS */
/* Wait till voltage level flag is set */
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
{}
#elif defined(USE_PWR_DIRECT_SMPS_SUPPLY) && defined(SMPS)
/* Exit Run* mode */
PWR->CR3 &= ~(PWR_CR3_LDOEN);
/* Wait till voltage level flag is set */
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
{}
#elif defined(USE_PWR_SMPS_1V8_SUPPLIES_LDO) && defined(SMPS)
/* Exit Run* mode */
PWR->CR3 |= PWR_CR3_SMPSLEVEL_0 | PWR_CR3_SMPSEN | PWR_CR3_LDOEN;
/* Wait till voltage level flag is set */
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
{}
#elif defined(USE_PWR_SMPS_2V5_SUPPLIES_LDO) && defined(SMPS)
/* Exit Run* mode */
PWR->CR3 |= PWR_CR3_SMPSLEVEL_1 | PWR_CR3_SMPSEN | PWR_CR3_LDOEN;
/* Wait till voltage level flag is set */
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
{}
#elif defined(USE_PWR_SMPS_1V8_SUPPLIES_EXT_AND_LDO) && defined(SMPS)
/* Exit Run* mode */
PWR->CR3 |= PWR_CR3_SMPSLEVEL_0 | PWR_CR3_SMPSEXTHP | PWR_CR3_SMPSEN | PWR_CR3_LDOEN;
/* Wait till voltage level flag is set */
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
{}
#elif defined(USE_PWR_SMPS_2V5_SUPPLIES_EXT_AND_LDO) && defined(SMPS)
/* Exit Run* mode */
PWR->CR3 |= PWR_CR3_SMPSLEVEL_1 | PWR_CR3_SMPSEXTHP | PWR_CR3_SMPSEN | PWR_CR3_LDOEN;
/* Wait till voltage level flag is set */
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
{}
#elif defined(USE_PWR_SMPS_1V8_SUPPLIES_EXT) && defined(SMPS)
/* Exit Run* mode */
PWR->CR3 = (PWR->CR3 & ~(PWR_CR3_LDOEN)) | PWR_CR3_SMPSLEVEL_0 | PWR_CR3_SMPSEXTHP | PWR_CR3_SMPSEN | PWR_CR3_BYPASS;
/* Wait till voltage level flag is set */
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
{}
#elif defined(USE_PWR_SMPS_2V5_SUPPLIES_EXT) && defined(SMPS)
/* Exit Run* mode */
PWR->CR3 = (PWR->CR3 & ~(PWR_CR3_LDOEN)) | PWR_CR3_SMPSLEVEL_1 | PWR_CR3_SMPSEXTHP | PWR_CR3_SMPSEN | PWR_CR3_BYPASS;
/* Wait till voltage level flag is set */
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U)
{}
#else
/* No system power supply configuration is selected at exit Run* mode */
#endif /* USE_PWR_LDO_SUPPLY */
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/

104
Core/Src/tim.c Normal file
View File

@@ -0,0 +1,104 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file tim.c
* @brief This file provides code for the configuration
* of the TIM instances.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "tim.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
TIM_HandleTypeDef htim6;
/* TIM6 init function */
void MX_TIM6_Init(void)
{
/* USER CODE BEGIN TIM6_Init 0 */
/* USER CODE END TIM6_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM6_Init 1 */
/* USER CODE END TIM6_Init 1 */
htim6.Instance = TIM6;
htim6.Init.Prescaler = 24000 - 1;
htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
htim6.Init.Period = 100 - 1;
htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM6_Init 2 */
/* USER CODE END TIM6_Init 2 */
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM6)
{
/* USER CODE BEGIN TIM6_MspInit 0 */
/* USER CODE END TIM6_MspInit 0 */
/* TIM6 clock enable */
__HAL_RCC_TIM6_CLK_ENABLE();
/* TIM6 interrupt Init */
HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
/* USER CODE BEGIN TIM6_MspInit 1 */
/* USER CODE END TIM6_MspInit 1 */
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM6)
{
/* USER CODE BEGIN TIM6_MspDeInit 0 */
/* USER CODE END TIM6_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM6_CLK_DISABLE();
/* TIM6 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM6_DAC_IRQn);
/* USER CODE BEGIN TIM6_MspDeInit 1 */
/* USER CODE END TIM6_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

901
Core/Src/usart.c Normal file
View File

@@ -0,0 +1,901 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.c
* @brief This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
UART_HandleTypeDef huart4;
UART_HandleTypeDef huart5;
UART_HandleTypeDef huart7;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
UART_HandleTypeDef huart3;
UART_HandleTypeDef huart6;
DMA_HandleTypeDef hdma_uart4_rx;
DMA_HandleTypeDef hdma_uart7_rx;
DMA_HandleTypeDef hdma_usart2_rx;
DMA_HandleTypeDef hdma_usart3_rx;
DMA_HandleTypeDef hdma_usart6_rx;
/* UART4 init function */
void MX_UART4_Init(void)
{
/* USER CODE BEGIN UART4_Init 0 */
/* USER CODE END UART4_Init 0 */
/* USER CODE BEGIN UART4_Init 1 */
/* USER CODE END UART4_Init 1 */
huart4.Instance = UART4;
huart4.Init.BaudRate = 230400;
huart4.Init.WordLength = UART_WORDLENGTH_8B;
huart4.Init.StopBits = UART_STOPBITS_1;
huart4.Init.Parity = UART_PARITY_NONE;
huart4.Init.Mode = UART_MODE_TX_RX;
huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart4.Init.OverSampling = UART_OVERSAMPLING_16;
huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart4) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart4) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN UART4_Init 2 */
/* USER CODE END UART4_Init 2 */
}
/* UART5 init function */
void MX_UART5_Init(void)
{
/* USER CODE BEGIN UART5_Init 0 */
/* USER CODE END UART5_Init 0 */
/* USER CODE BEGIN UART5_Init 1 */
/* USER CODE END UART5_Init 1 */
huart5.Instance = UART5;
huart5.Init.BaudRate = 115200;
huart5.Init.WordLength = UART_WORDLENGTH_8B;
huart5.Init.StopBits = UART_STOPBITS_1;
huart5.Init.Parity = UART_PARITY_NONE;
huart5.Init.Mode = UART_MODE_TX_RX;
huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart5.Init.OverSampling = UART_OVERSAMPLING_16;
huart5.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart5.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart5.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_HalfDuplex_Init(&huart5) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart5, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart5, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart5) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN UART5_Init 2 */
/* USER CODE END UART5_Init 2 */
}
/* UART7 init function */
void MX_UART7_Init(void)
{
/* USER CODE BEGIN UART7_Init 0 */
/* USER CODE END UART7_Init 0 */
/* USER CODE BEGIN UART7_Init 1 */
/* USER CODE END UART7_Init 1 */
huart7.Instance = UART7;
huart7.Init.BaudRate = 115200;
huart7.Init.WordLength = UART_WORDLENGTH_8B;
huart7.Init.StopBits = UART_STOPBITS_1;
huart7.Init.Parity = UART_PARITY_NONE;
huart7.Init.Mode = UART_MODE_TX_RX;
huart7.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart7.Init.OverSampling = UART_OVERSAMPLING_16;
huart7.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart7.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart7.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart7) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart7, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart7, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart7) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN UART7_Init 2 */
/* USER CODE END UART7_Init 2 */
}
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/* USART2 init function */
void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 230400;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
/* USART3 init function */
void MX_USART3_UART_Init(void)
{
/* USER CODE BEGIN USART3_Init 0 */
/* USER CODE END USART3_Init 0 */
/* USER CODE BEGIN USART3_Init 1 */
/* USER CODE END USART3_Init 1 */
huart3.Instance = USART3;
huart3.Init.BaudRate = 115200;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart3.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART3_Init 2 */
/* USER CODE END USART3_Init 2 */
}
/* USART6 init function */
void MX_USART6_UART_Init(void)
{
/* USER CODE BEGIN USART6_Init 0 */
/* USER CODE END USART6_Init 0 */
/* USER CODE BEGIN USART6_Init 1 */
/* USER CODE END USART6_Init 1 */
huart6.Instance = USART6;
huart6.Init.BaudRate = 115200;
huart6.Init.WordLength = UART_WORDLENGTH_8B;
huart6.Init.StopBits = UART_STOPBITS_1;
huart6.Init.Parity = UART_PARITY_NONE;
huart6.Init.Mode = UART_MODE_TX_RX;
huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart6.Init.OverSampling = UART_OVERSAMPLING_16;
huart6.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart6.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart6.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart6) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart6, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart6, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart6) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART6_Init 2 */
/* USER CODE END USART6_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
if(uartHandle->Instance==UART4)
{
/* USER CODE BEGIN UART4_MspInit 0 */
/* USER CODE END UART4_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_UART4;
PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* UART4 clock enable */
__HAL_RCC_UART4_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**UART4 GPIO Configuration
PA0 ------> UART4_TX
PA1 ------> UART4_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* UART4 DMA Init */
/* UART4_RX Init */
hdma_uart4_rx.Instance = DMA1_Stream1;
hdma_uart4_rx.Init.Request = DMA_REQUEST_UART4_RX;
hdma_uart4_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_uart4_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_uart4_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_uart4_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_uart4_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_uart4_rx.Init.Mode = DMA_CIRCULAR;
hdma_uart4_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_uart4_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_uart4_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_uart4_rx);
/* UART4 interrupt Init */
HAL_NVIC_SetPriority(UART4_IRQn, 6, 0);
HAL_NVIC_EnableIRQ(UART4_IRQn);
/* USER CODE BEGIN UART4_MspInit 1 */
/* USER CODE END UART4_MspInit 1 */
}
else if(uartHandle->Instance==UART5)
{
/* USER CODE BEGIN UART5_MspInit 0 */
/* USER CODE END UART5_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_UART5;
PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* UART5 clock enable */
__HAL_RCC_UART5_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**UART5 GPIO Configuration
PB13 ------> UART5_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF14_UART5;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN UART5_MspInit 1 */
/* USER CODE END UART5_MspInit 1 */
}
else if(uartHandle->Instance==UART7)
{
/* USER CODE BEGIN UART7_MspInit 0 */
/* USER CODE END UART7_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_UART7;
PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* UART7 clock enable */
__HAL_RCC_UART7_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
/**UART7 GPIO Configuration
PE7 ------> UART7_RX
PE8 ------> UART7_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_UART7;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/* UART7 DMA Init */
/* UART7_RX Init */
hdma_uart7_rx.Instance = DMA1_Stream4;
hdma_uart7_rx.Init.Request = DMA_REQUEST_UART7_RX;
hdma_uart7_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_uart7_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_uart7_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_uart7_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_uart7_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_uart7_rx.Init.Mode = DMA_CIRCULAR;
hdma_uart7_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_uart7_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_uart7_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_uart7_rx);
/* UART7 interrupt Init */
HAL_NVIC_SetPriority(UART7_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(UART7_IRQn);
/* USER CODE BEGIN UART7_MspInit 1 */
/* USER CODE END UART7_MspInit 1 */
}
else if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1;
PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**USART1 GPIO Configuration
PB14 ------> USART1_TX
PB15 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF4_USART1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
else if(uartHandle->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspInit 0 */
/* USER CODE END USART2_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART2;
PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* USART2 clock enable */
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART2 DMA Init */
/* USART2_RX Init */
hdma_usart2_rx.Instance = DMA1_Stream0;
hdma_usart2_rx.Init.Request = DMA_REQUEST_USART2_RX;
hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart2_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart2_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart2_rx);
/* USART2 interrupt Init */
HAL_NVIC_SetPriority(USART2_IRQn, 6, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_MspInit 1 */
/* USER CODE END USART2_MspInit 1 */
}
else if(uartHandle->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspInit 0 */
/* USER CODE END USART3_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3;
PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* USART3 clock enable */
__HAL_RCC_USART3_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**USART3 GPIO Configuration
PD8 ------> USART3_TX
PD9 ------> USART3_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* USART3 DMA Init */
/* USART3_RX Init */
hdma_usart3_rx.Instance = DMA1_Stream2;
hdma_usart3_rx.Init.Request = DMA_REQUEST_USART3_RX;
hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart3_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart3_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_usart3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart3_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart3_rx);
/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, 6, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspInit 1 */
/* USER CODE END USART3_MspInit 1 */
}
else if(uartHandle->Instance==USART6)
{
/* USER CODE BEGIN USART6_MspInit 0 */
/* USER CODE END USART6_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART6;
PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* USART6 clock enable */
__HAL_RCC_USART6_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**USART6 GPIO Configuration
PC6 ------> USART6_TX
PC7 ------> USART6_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF7_USART6;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* USART6 DMA Init */
/* USART6_RX Init */
hdma_usart6_rx.Instance = DMA1_Stream3;
hdma_usart6_rx.Init.Request = DMA_REQUEST_USART6_RX;
hdma_usart6_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart6_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart6_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart6_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart6_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart6_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart6_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_usart6_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart6_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart6_rx);
/* USART6 interrupt Init */
HAL_NVIC_SetPriority(USART6_IRQn, 6, 0);
HAL_NVIC_EnableIRQ(USART6_IRQn);
/* USER CODE BEGIN USART6_MspInit 1 */
/* USER CODE END USART6_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==UART4)
{
/* USER CODE BEGIN UART4_MspDeInit 0 */
/* USER CODE END UART4_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_UART4_CLK_DISABLE();
/**UART4 GPIO Configuration
PA0 ------> UART4_TX
PA1 ------> UART4_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1);
/* UART4 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmarx);
/* UART4 interrupt Deinit */
HAL_NVIC_DisableIRQ(UART4_IRQn);
/* USER CODE BEGIN UART4_MspDeInit 1 */
/* USER CODE END UART4_MspDeInit 1 */
}
else if(uartHandle->Instance==UART5)
{
/* USER CODE BEGIN UART5_MspDeInit 0 */
/* USER CODE END UART5_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_UART5_CLK_DISABLE();
/**UART5 GPIO Configuration
PB13 ------> UART5_TX
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13);
/* USER CODE BEGIN UART5_MspDeInit 1 */
/* USER CODE END UART5_MspDeInit 1 */
}
else if(uartHandle->Instance==UART7)
{
/* USER CODE BEGIN UART7_MspDeInit 0 */
/* USER CODE END UART7_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_UART7_CLK_DISABLE();
/**UART7 GPIO Configuration
PE7 ------> UART7_RX
PE8 ------> UART7_TX
*/
HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8);
/* UART7 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmarx);
/* UART7 interrupt Deinit */
HAL_NVIC_DisableIRQ(UART7_IRQn);
/* USER CODE BEGIN UART7_MspDeInit 1 */
/* USER CODE END UART7_MspDeInit 1 */
}
else if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PB14 ------> USART1_TX
PB15 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_14|GPIO_PIN_15);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
else if(uartHandle->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspDeInit 0 */
/* USER CODE END USART2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART2_CLK_DISABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
/* USART2 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmarx);
/* USART2 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_MspDeInit 1 */
/* USER CODE END USART2_MspDeInit 1 */
}
else if(uartHandle->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspDeInit 0 */
/* USER CODE END USART3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART3_CLK_DISABLE();
/**USART3 GPIO Configuration
PD8 ------> USART3_TX
PD9 ------> USART3_RX
*/
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9);
/* USART3 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmarx);
/* USART3 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspDeInit 1 */
/* USER CODE END USART3_MspDeInit 1 */
}
else if(uartHandle->Instance==USART6)
{
/* USER CODE BEGIN USART6_MspDeInit 0 */
/* USER CODE END USART6_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART6_CLK_DISABLE();
/**USART6 GPIO Configuration
PC6 ------> USART6_TX
PC7 ------> USART6_RX
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_6|GPIO_PIN_7);
/* USART6 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmarx);
/* USART6 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART6_IRQn);
/* USER CODE BEGIN USART6_MspDeInit 1 */
/* USER CODE END USART6_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
#include "laser/laser_manager.h"
#include "IMU/hwt101.h"
/**
* @brief 全局 UART 接收完成回调分发器
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// 分发给激光雷达管理器
LASER_UART_RxCpltCallback(huart);
// 如果 IMU 以后需要用到定长接收中断,也可以在这里加:
// HWT101_UART_RxCpltCallback(huart);
}
/**
* @brief 全局 UART 接收过半回调分发器
*/
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
{
// 分发给激光雷达管理器
LASER_UART_RxHalfCpltCallback(huart);
}
/**
* @brief 全局 UART 空闲/扩展接收回调分发器
*/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
// 分发给激光雷达管理器
LASER_UARTEx_RxEventCallback(huart, Size);
}
/**
* @brief 全局 UART 错误回调分发器 (极其关键,防止外设死机)
*/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
// 分发给激光雷达管理器进行自动恢复
LASER_UART_ErrorRecovery(huart);
// 分发给 IMU 进行自动恢复 (暴力清除错误标志并重启 DMA)
HWT101_ErrorRecovery(huart);
}
/* USER CODE END 1 */

View File

@@ -0,0 +1,894 @@
/**************************************************************************//**
* @file cmsis_armcc.h
* @brief CMSIS compiler ARMCC (Arm Compiler 5) header file
* @version V5.1.0
* @date 08. May 2019
******************************************************************************/
/*
* Copyright (c) 2009-2019 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.
*/
#ifndef __CMSIS_ARMCC_H
#define __CMSIS_ARMCC_H
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
#error "Please use Arm Compiler Toolchain V4.0.677 or later!"
#endif
/* CMSIS compiler control architecture macros */
#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \
(defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) )
#define __ARM_ARCH_6M__ 1
#endif
#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1))
#define __ARM_ARCH_7M__ 1
#endif
#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1))
#define __ARM_ARCH_7EM__ 1
#endif
/* __ARM_ARCH_8M_BASE__ not applicable */
/* __ARM_ARCH_8M_MAIN__ not applicable */
/* CMSIS compiler control DSP macros */
#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
#define __ARM_FEATURE_DSP 1
#endif
/* CMSIS compiler specific defines */
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE __inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static __inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE static __forceinline
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __declspec(noreturn)
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT __packed struct
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION __packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
#define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x)))
#endif
#ifndef __UNALIGNED_UINT16_WRITE
#define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
#define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr)))
#endif
#ifndef __UNALIGNED_UINT32_WRITE
#define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
#define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr)))
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
#ifndef __COMPILER_BARRIER
#define __COMPILER_BARRIER() __memory_changed()
#endif
/* ######################### Startup and Lowlevel Init ######################## */
#ifndef __PROGRAM_START
#define __PROGRAM_START __main
#endif
#ifndef __INITIAL_SP
#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit
#endif
#ifndef __STACK_LIMIT
#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base
#endif
#ifndef __VECTOR_TABLE
#define __VECTOR_TABLE __Vectors
#endif
#ifndef __VECTOR_TABLE_ATTRIBUTE
#define __VECTOR_TABLE_ATTRIBUTE __attribute((used, section("RESET")))
#endif
/* ########################### Core Function Access ########################### */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
@{
*/
/**
\brief Enable IRQ Interrupts
\details Enables IRQ interrupts by clearing the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
/* intrinsic void __enable_irq(); */
/**
\brief Disable IRQ Interrupts
\details Disables IRQ interrupts by setting the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
/* intrinsic void __disable_irq(); */
/**
\brief Get Control Register
\details Returns the content of the Control Register.
\return Control Register value
*/
__STATIC_INLINE uint32_t __get_CONTROL(void)
{
register uint32_t __regControl __ASM("control");
return(__regControl);
}
/**
\brief Set Control Register
\details Writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__STATIC_INLINE void __set_CONTROL(uint32_t control)
{
register uint32_t __regControl __ASM("control");
__regControl = control;
}
/**
\brief Get IPSR Register
\details Returns the content of the IPSR Register.
\return IPSR Register value
*/
__STATIC_INLINE uint32_t __get_IPSR(void)
{
register uint32_t __regIPSR __ASM("ipsr");
return(__regIPSR);
}
/**
\brief Get APSR Register
\details Returns the content of the APSR Register.
\return APSR Register value
*/
__STATIC_INLINE uint32_t __get_APSR(void)
{
register uint32_t __regAPSR __ASM("apsr");
return(__regAPSR);
}
/**
\brief Get xPSR Register
\details Returns the content of the xPSR Register.
\return xPSR Register value
*/
__STATIC_INLINE uint32_t __get_xPSR(void)
{
register uint32_t __regXPSR __ASM("xpsr");
return(__regXPSR);
}
/**
\brief Get Process Stack Pointer
\details Returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__STATIC_INLINE uint32_t __get_PSP(void)
{
register uint32_t __regProcessStackPointer __ASM("psp");
return(__regProcessStackPointer);
}
/**
\brief Set Process Stack Pointer
\details Assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
{
register uint32_t __regProcessStackPointer __ASM("psp");
__regProcessStackPointer = topOfProcStack;
}
/**
\brief Get Main Stack Pointer
\details Returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__STATIC_INLINE uint32_t __get_MSP(void)
{
register uint32_t __regMainStackPointer __ASM("msp");
return(__regMainStackPointer);
}
/**
\brief Set Main Stack Pointer
\details Assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{
register uint32_t __regMainStackPointer __ASM("msp");
__regMainStackPointer = topOfMainStack;
}
/**
\brief Get Priority Mask
\details Returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__STATIC_INLINE uint32_t __get_PRIMASK(void)
{
register uint32_t __regPriMask __ASM("primask");
return(__regPriMask);
}
/**
\brief Set Priority Mask
\details Assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
{
register uint32_t __regPriMask __ASM("primask");
__regPriMask = (priMask);
}
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
/**
\brief Enable FIQ
\details Enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __enable_fault_irq __enable_fiq
/**
\brief Disable FIQ
\details Disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __disable_fault_irq __disable_fiq
/**
\brief Get Base Priority
\details Returns the current value of the Base Priority register.
\return Base Priority register value
*/
__STATIC_INLINE uint32_t __get_BASEPRI(void)
{
register uint32_t __regBasePri __ASM("basepri");
return(__regBasePri);
}
/**
\brief Set Base Priority
\details Assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
{
register uint32_t __regBasePri __ASM("basepri");
__regBasePri = (basePri & 0xFFU);
}
/**
\brief Set Base Priority with condition
\details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled,
or the new value increases the BASEPRI priority level.
\param [in] basePri Base Priority value to set
*/
__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri)
{
register uint32_t __regBasePriMax __ASM("basepri_max");
__regBasePriMax = (basePri & 0xFFU);
}
/**
\brief Get Fault Mask
\details Returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__STATIC_INLINE uint32_t __get_FAULTMASK(void)
{
register uint32_t __regFaultMask __ASM("faultmask");
return(__regFaultMask);
}
/**
\brief Set Fault Mask
\details Assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
register uint32_t __regFaultMask __ASM("faultmask");
__regFaultMask = (faultMask & (uint32_t)1U);
}
#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
/**
\brief Get FPSCR
\details Returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__STATIC_INLINE uint32_t __get_FPSCR(void)
{
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
register uint32_t __regfpscr __ASM("fpscr");
return(__regfpscr);
#else
return(0U);
#endif
}
/**
\brief Set FPSCR
\details Assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
register uint32_t __regfpscr __ASM("fpscr");
__regfpscr = (fpscr);
#else
(void)fpscr;
#endif
}
/*@} end of CMSIS_Core_RegAccFunctions */
/* ########################## Core Instruction Access ######################### */
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
Access to dedicated instructions
@{
*/
/**
\brief No Operation
\details No Operation does nothing. This instruction can be used for code alignment purposes.
*/
#define __NOP __nop
/**
\brief Wait For Interrupt
\details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
*/
#define __WFI __wfi
/**
\brief Wait For Event
\details Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
#define __WFE __wfe
/**
\brief Send Event
\details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
#define __SEV __sev
/**
\brief Instruction Synchronization Barrier
\details Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or memory,
after the instruction has been completed.
*/
#define __ISB() do {\
__schedule_barrier();\
__isb(0xF);\
__schedule_barrier();\
} while (0U)
/**
\brief Data Synchronization Barrier
\details Acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
#define __DSB() do {\
__schedule_barrier();\
__dsb(0xF);\
__schedule_barrier();\
} while (0U)
/**
\brief Data Memory Barrier
\details Ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
#define __DMB() do {\
__schedule_barrier();\
__dmb(0xF);\
__schedule_barrier();\
} while (0U)
/**
\brief Reverse byte order (32 bit)
\details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
\param [in] value Value to reverse
\return Reversed value
*/
#define __REV __rev
/**
\brief Reverse byte order (16 bit)
\details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
{
rev16 r0, r0
bx lr
}
#endif
/**
\brief Reverse byte order (16 bit)
\details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value)
{
revsh r0, r0
bx lr
}
#endif
/**
\brief Rotate Right in unsigned value (32 bit)
\details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
\param [in] op1 Value to rotate
\param [in] op2 Number of Bits to rotate
\return Rotated value
*/
#define __ROR __ror
/**
\brief Breakpoint
\details Causes the processor to enter Debug state.
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
\param [in] value is ignored by the processor.
If required, a debugger can use it to store additional information about the breakpoint.
*/
#define __BKPT(value) __breakpoint(value)
/**
\brief Reverse bit order of value
\details Reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
#define __RBIT __rbit
#else
__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
{
uint32_t result;
uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
result = value; /* r will be reversed bits of v; first get LSB of v */
for (value >>= 1U; value != 0U; value >>= 1U)
{
result <<= 1U;
result |= value & 1U;
s--;
}
result <<= s; /* shift when v's highest bits are zero */
return result;
}
#endif
/**
\brief Count leading zeros
\details Counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
#define __CLZ __clz
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
/**
\brief LDR Exclusive (8 bit)
\details Executes a exclusive LDR instruction for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
#else
#define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop")
#endif
/**
\brief LDR Exclusive (16 bit)
\details Executes a exclusive LDR instruction for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
#else
#define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop")
#endif
/**
\brief LDR Exclusive (32 bit)
\details Executes a exclusive LDR instruction for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
#else
#define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop")
#endif
/**
\brief STR Exclusive (8 bit)
\details Executes a exclusive STR instruction for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __STREXB(value, ptr) __strex(value, ptr)
#else
#define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
#endif
/**
\brief STR Exclusive (16 bit)
\details Executes a exclusive STR instruction for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __STREXH(value, ptr) __strex(value, ptr)
#else
#define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
#endif
/**
\brief STR Exclusive (32 bit)
\details Executes a exclusive STR instruction for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
#define __STREXW(value, ptr) __strex(value, ptr)
#else
#define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
#endif
/**
\brief Remove the exclusive lock
\details Removes the exclusive lock which is created by LDREX.
*/
#define __CLREX __clrex
/**
\brief Signed Saturate
\details Saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT __ssat
/**
\brief Unsigned Saturate
\details Saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT __usat
/**
\brief Rotate Right with Extend (32 bit)
\details Moves each bit of a bitstring right by one bit.
The carry input is shifted in at the left end of the bitstring.
\param [in] value Value to rotate
\return Rotated value
*/
#ifndef __NO_EMBEDDED_ASM
__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value)
{
rrx r0, r0
bx lr
}
#endif
/**
\brief LDRT Unprivileged (8 bit)
\details Executes a Unprivileged LDRT instruction for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr))
/**
\brief LDRT Unprivileged (16 bit)
\details Executes a Unprivileged LDRT instruction for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr))
/**
\brief LDRT Unprivileged (32 bit)
\details Executes a Unprivileged LDRT instruction for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr))
/**
\brief STRT Unprivileged (8 bit)
\details Executes a Unprivileged STRT instruction for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
*/
#define __STRBT(value, ptr) __strt(value, ptr)
/**
\brief STRT Unprivileged (16 bit)
\details Executes a Unprivileged STRT instruction for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
*/
#define __STRHT(value, ptr) __strt(value, ptr)
/**
\brief STRT Unprivileged (32 bit)
\details Executes a Unprivileged STRT instruction for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
*/
#define __STRT(value, ptr) __strt(value, ptr)
#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
/**
\brief Signed Saturate
\details Saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat)
{
if ((sat >= 1U) && (sat <= 32U))
{
const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
const int32_t min = -1 - max ;
if (val > max)
{
return max;
}
else if (val < min)
{
return min;
}
}
return val;
}
/**
\brief Unsigned Saturate
\details Saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat)
{
if (sat <= 31U)
{
const uint32_t max = ((1U << sat) - 1U);
if (val > (int32_t)max)
{
return max;
}
else if (val < 0)
{
return 0U;
}
}
return (uint32_t)val;
}
#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
/* ################### Compiler specific Intrinsics ########################### */
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
Access to dedicated SIMD instructions
@{
*/
#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
#define __SADD8 __sadd8
#define __QADD8 __qadd8
#define __SHADD8 __shadd8
#define __UADD8 __uadd8
#define __UQADD8 __uqadd8
#define __UHADD8 __uhadd8
#define __SSUB8 __ssub8
#define __QSUB8 __qsub8
#define __SHSUB8 __shsub8
#define __USUB8 __usub8
#define __UQSUB8 __uqsub8
#define __UHSUB8 __uhsub8
#define __SADD16 __sadd16
#define __QADD16 __qadd16
#define __SHADD16 __shadd16
#define __UADD16 __uadd16
#define __UQADD16 __uqadd16
#define __UHADD16 __uhadd16
#define __SSUB16 __ssub16
#define __QSUB16 __qsub16
#define __SHSUB16 __shsub16
#define __USUB16 __usub16
#define __UQSUB16 __uqsub16
#define __UHSUB16 __uhsub16
#define __SASX __sasx
#define __QASX __qasx
#define __SHASX __shasx
#define __UASX __uasx
#define __UQASX __uqasx
#define __UHASX __uhasx
#define __SSAX __ssax
#define __QSAX __qsax
#define __SHSAX __shsax
#define __USAX __usax
#define __UQSAX __uqsax
#define __UHSAX __uhsax
#define __USAD8 __usad8
#define __USADA8 __usada8
#define __SSAT16 __ssat16
#define __USAT16 __usat16
#define __UXTB16 __uxtb16
#define __UXTAB16 __uxtab16
#define __SXTB16 __sxtb16
#define __SXTAB16 __sxtab16
#define __SMUAD __smuad
#define __SMUADX __smuadx
#define __SMLAD __smlad
#define __SMLADX __smladx
#define __SMLALD __smlald
#define __SMLALDX __smlaldx
#define __SMUSD __smusd
#define __SMUSDX __smusdx
#define __SMLSD __smlsd
#define __SMLSDX __smlsdx
#define __SMLSLD __smlsld
#define __SMLSLDX __smlsldx
#define __SEL __sel
#define __QADD __qadd
#define __QSUB __qsub
#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \
((int64_t)(ARG3) << 32U) ) >> 32U))
#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
/*@} end of group CMSIS_SIMD_intrinsics */
#endif /* __CMSIS_ARMCC_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,283 @@
/**************************************************************************//**
* @file cmsis_compiler.h
* @brief CMSIS compiler generic header file
* @version V5.1.0
* @date 09. October 2018
******************************************************************************/
/*
* Copyright (c) 2009-2018 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.
*/
#ifndef __CMSIS_COMPILER_H
#define __CMSIS_COMPILER_H
#include <stdint.h>
/*
* Arm Compiler 4/5
*/
#if defined ( __CC_ARM )
#include "cmsis_armcc.h"
/*
* Arm Compiler 6.6 LTM (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100)
#include "cmsis_armclang_ltm.h"
/*
* Arm Compiler above 6.10.1 (armclang)
*/
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
#include "cmsis_armclang.h"
/*
* GNU Compiler
*/
#elif defined ( __GNUC__ )
#include "cmsis_gcc.h"
/*
* IAR Compiler
*/
#elif defined ( __ICCARM__ )
#include <cmsis_iccarm.h>
/*
* TI Arm Compiler
*/
#elif defined ( __TI_ARM__ )
#include <cmsis_ccs.h>
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed))
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed))
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
/*
* TASKING Compiler
*/
#elif defined ( __TASKING__ )
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((noreturn))
#endif
#ifndef __USED
#define __USED __attribute__((used))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __PACKED
#define __PACKED __packed__
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __packed__
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION union __packed__
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
struct __packed__ T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#define __ALIGNED(x) __align(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
/*
* COSMIC Compiler
*/
#elif defined ( __CSMC__ )
#include <cmsis_csm.h>
#ifndef __ASM
#define __ASM _asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __STATIC_INLINE
#endif
#ifndef __NO_RETURN
// NO RETURN is automatically detected hence no warning here
#define __NO_RETURN
#endif
#ifndef __USED
#warning No compiler specific solution for __USED. __USED is ignored.
#define __USED
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
#ifndef __PACKED
#define __PACKED @packed
#endif
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT @packed struct
#endif
#ifndef __PACKED_UNION
#define __PACKED_UNION @packed union
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
@packed struct T_UINT32 { uint32_t v; };
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
#ifndef __ALIGNED
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
#define __ALIGNED(x)
#endif
#ifndef __RESTRICT
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
#define __RESTRICT
#endif
#ifndef __COMPILER_BARRIER
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
#define __COMPILER_BARRIER() (void)0
#endif
#else
#error Unknown compiler.
#endif
#endif /* __CMSIS_COMPILER_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,964 @@
/**************************************************************************//**
* @file cmsis_iccarm.h
* @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file
* @version V5.1.0
* @date 08. May 2019
******************************************************************************/
//------------------------------------------------------------------------------
//
// Copyright (c) 2017-2019 IAR Systems
// Copyright (c) 2017-2019 Arm Limited. All rights reserved.
//
// 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
// http://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.
//
//------------------------------------------------------------------------------
#ifndef __CMSIS_ICCARM_H__
#define __CMSIS_ICCARM_H__
#ifndef __ICCARM__
#error This file should only be compiled by ICCARM
#endif
#pragma system_include
#define __IAR_FT _Pragma("inline=forced") __intrinsic
#if (__VER__ >= 8000000)
#define __ICCARM_V8 1
#else
#define __ICCARM_V8 0
#endif
#ifndef __ALIGNED
#if __ICCARM_V8
#define __ALIGNED(x) __attribute__((aligned(x)))
#elif (__VER__ >= 7080000)
/* Needs IAR language extensions */
#define __ALIGNED(x) __attribute__((aligned(x)))
#else
#warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored.
#define __ALIGNED(x)
#endif
#endif
/* Define compiler macros for CPU architecture, used in CMSIS 5.
*/
#if __ARM_ARCH_6M__ || __ARM_ARCH_7M__ || __ARM_ARCH_7EM__ || __ARM_ARCH_8M_BASE__ || __ARM_ARCH_8M_MAIN__
/* Macros already defined */
#else
#if defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__)
#define __ARM_ARCH_8M_MAIN__ 1
#elif defined(__ARM8M_BASELINE__)
#define __ARM_ARCH_8M_BASE__ 1
#elif defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M'
#if __ARM_ARCH == 6
#define __ARM_ARCH_6M__ 1
#elif __ARM_ARCH == 7
#if __ARM_FEATURE_DSP
#define __ARM_ARCH_7EM__ 1
#else
#define __ARM_ARCH_7M__ 1
#endif
#endif /* __ARM_ARCH */
#endif /* __ARM_ARCH_PROFILE == 'M' */
#endif
/* Alternativ core deduction for older ICCARM's */
#if !defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__) && \
!defined(__ARM_ARCH_8M_BASE__) && !defined(__ARM_ARCH_8M_MAIN__)
#if defined(__ARM6M__) && (__CORE__ == __ARM6M__)
#define __ARM_ARCH_6M__ 1
#elif defined(__ARM7M__) && (__CORE__ == __ARM7M__)
#define __ARM_ARCH_7M__ 1
#elif defined(__ARM7EM__) && (__CORE__ == __ARM7EM__)
#define __ARM_ARCH_7EM__ 1
#elif defined(__ARM8M_BASELINE__) && (__CORE == __ARM8M_BASELINE__)
#define __ARM_ARCH_8M_BASE__ 1
#elif defined(__ARM8M_MAINLINE__) && (__CORE == __ARM8M_MAINLINE__)
#define __ARM_ARCH_8M_MAIN__ 1
#elif defined(__ARM8EM_MAINLINE__) && (__CORE == __ARM8EM_MAINLINE__)
#define __ARM_ARCH_8M_MAIN__ 1
#else
#error "Unknown target."
#endif
#endif
#if defined(__ARM_ARCH_6M__) && __ARM_ARCH_6M__==1
#define __IAR_M0_FAMILY 1
#elif defined(__ARM_ARCH_8M_BASE__) && __ARM_ARCH_8M_BASE__==1
#define __IAR_M0_FAMILY 1
#else
#define __IAR_M0_FAMILY 0
#endif
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __COMPILER_BARRIER
#define __COMPILER_BARRIER() __ASM volatile("":::"memory")
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __NO_RETURN
#if __ICCARM_V8
#define __NO_RETURN __attribute__((__noreturn__))
#else
#define __NO_RETURN _Pragma("object_attribute=__noreturn")
#endif
#endif
#ifndef __PACKED
#if __ICCARM_V8
#define __PACKED __attribute__((packed, aligned(1)))
#else
/* Needs IAR language extensions */
#define __PACKED __packed
#endif
#endif
#ifndef __PACKED_STRUCT
#if __ICCARM_V8
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
#else
/* Needs IAR language extensions */
#define __PACKED_STRUCT __packed struct
#endif
#endif
#ifndef __PACKED_UNION
#if __ICCARM_V8
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
#else
/* Needs IAR language extensions */
#define __PACKED_UNION __packed union
#endif
#endif
#ifndef __RESTRICT
#if __ICCARM_V8
#define __RESTRICT __restrict
#else
/* Needs IAR language extensions */
#define __RESTRICT restrict
#endif
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __FORCEINLINE
#define __FORCEINLINE _Pragma("inline=forced")
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __FORCEINLINE __STATIC_INLINE
#endif
#ifndef __UNALIGNED_UINT16_READ
#pragma language=save
#pragma language=extended
__IAR_FT uint16_t __iar_uint16_read(void const *ptr)
{
return *(__packed uint16_t*)(ptr);
}
#pragma language=restore
#define __UNALIGNED_UINT16_READ(PTR) __iar_uint16_read(PTR)
#endif
#ifndef __UNALIGNED_UINT16_WRITE
#pragma language=save
#pragma language=extended
__IAR_FT void __iar_uint16_write(void const *ptr, uint16_t val)
{
*(__packed uint16_t*)(ptr) = val;;
}
#pragma language=restore
#define __UNALIGNED_UINT16_WRITE(PTR,VAL) __iar_uint16_write(PTR,VAL)
#endif
#ifndef __UNALIGNED_UINT32_READ
#pragma language=save
#pragma language=extended
__IAR_FT uint32_t __iar_uint32_read(void const *ptr)
{
return *(__packed uint32_t*)(ptr);
}
#pragma language=restore
#define __UNALIGNED_UINT32_READ(PTR) __iar_uint32_read(PTR)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
#pragma language=save
#pragma language=extended
__IAR_FT void __iar_uint32_write(void const *ptr, uint32_t val)
{
*(__packed uint32_t*)(ptr) = val;;
}
#pragma language=restore
#define __UNALIGNED_UINT32_WRITE(PTR,VAL) __iar_uint32_write(PTR,VAL)
#endif
#ifndef __UNALIGNED_UINT32 /* deprecated */
#pragma language=save
#pragma language=extended
__packed struct __iar_u32 { uint32_t v; };
#pragma language=restore
#define __UNALIGNED_UINT32(PTR) (((struct __iar_u32 *)(PTR))->v)
#endif
#ifndef __USED
#if __ICCARM_V8
#define __USED __attribute__((used))
#else
#define __USED _Pragma("__root")
#endif
#endif
#ifndef __WEAK
#if __ICCARM_V8
#define __WEAK __attribute__((weak))
#else
#define __WEAK _Pragma("__weak")
#endif
#endif
#ifndef __PROGRAM_START
#define __PROGRAM_START __iar_program_start
#endif
#ifndef __INITIAL_SP
#define __INITIAL_SP CSTACK$$Limit
#endif
#ifndef __STACK_LIMIT
#define __STACK_LIMIT CSTACK$$Base
#endif
#ifndef __VECTOR_TABLE
#define __VECTOR_TABLE __vector_table
#endif
#ifndef __VECTOR_TABLE_ATTRIBUTE
#define __VECTOR_TABLE_ATTRIBUTE @".intvec"
#endif
#ifndef __ICCARM_INTRINSICS_VERSION__
#define __ICCARM_INTRINSICS_VERSION__ 0
#endif
#if __ICCARM_INTRINSICS_VERSION__ == 2
#if defined(__CLZ)
#undef __CLZ
#endif
#if defined(__REVSH)
#undef __REVSH
#endif
#if defined(__RBIT)
#undef __RBIT
#endif
#if defined(__SSAT)
#undef __SSAT
#endif
#if defined(__USAT)
#undef __USAT
#endif
#include "iccarm_builtin.h"
#define __disable_fault_irq __iar_builtin_disable_fiq
#define __disable_irq __iar_builtin_disable_interrupt
#define __enable_fault_irq __iar_builtin_enable_fiq
#define __enable_irq __iar_builtin_enable_interrupt
#define __arm_rsr __iar_builtin_rsr
#define __arm_wsr __iar_builtin_wsr
#define __get_APSR() (__arm_rsr("APSR"))
#define __get_BASEPRI() (__arm_rsr("BASEPRI"))
#define __get_CONTROL() (__arm_rsr("CONTROL"))
#define __get_FAULTMASK() (__arm_rsr("FAULTMASK"))
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
#define __get_FPSCR() (__arm_rsr("FPSCR"))
#define __set_FPSCR(VALUE) (__arm_wsr("FPSCR", (VALUE)))
#else
#define __get_FPSCR() ( 0 )
#define __set_FPSCR(VALUE) ((void)VALUE)
#endif
#define __get_IPSR() (__arm_rsr("IPSR"))
#define __get_MSP() (__arm_rsr("MSP"))
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
// without main extensions, the non-secure MSPLIM is RAZ/WI
#define __get_MSPLIM() (0U)
#else
#define __get_MSPLIM() (__arm_rsr("MSPLIM"))
#endif
#define __get_PRIMASK() (__arm_rsr("PRIMASK"))
#define __get_PSP() (__arm_rsr("PSP"))
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
// without main extensions, the non-secure PSPLIM is RAZ/WI
#define __get_PSPLIM() (0U)
#else
#define __get_PSPLIM() (__arm_rsr("PSPLIM"))
#endif
#define __get_xPSR() (__arm_rsr("xPSR"))
#define __set_BASEPRI(VALUE) (__arm_wsr("BASEPRI", (VALUE)))
#define __set_BASEPRI_MAX(VALUE) (__arm_wsr("BASEPRI_MAX", (VALUE)))
#define __set_CONTROL(VALUE) (__arm_wsr("CONTROL", (VALUE)))
#define __set_FAULTMASK(VALUE) (__arm_wsr("FAULTMASK", (VALUE)))
#define __set_MSP(VALUE) (__arm_wsr("MSP", (VALUE)))
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
// without main extensions, the non-secure MSPLIM is RAZ/WI
#define __set_MSPLIM(VALUE) ((void)(VALUE))
#else
#define __set_MSPLIM(VALUE) (__arm_wsr("MSPLIM", (VALUE)))
#endif
#define __set_PRIMASK(VALUE) (__arm_wsr("PRIMASK", (VALUE)))
#define __set_PSP(VALUE) (__arm_wsr("PSP", (VALUE)))
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
// without main extensions, the non-secure PSPLIM is RAZ/WI
#define __set_PSPLIM(VALUE) ((void)(VALUE))
#else
#define __set_PSPLIM(VALUE) (__arm_wsr("PSPLIM", (VALUE)))
#endif
#define __TZ_get_CONTROL_NS() (__arm_rsr("CONTROL_NS"))
#define __TZ_set_CONTROL_NS(VALUE) (__arm_wsr("CONTROL_NS", (VALUE)))
#define __TZ_get_PSP_NS() (__arm_rsr("PSP_NS"))
#define __TZ_set_PSP_NS(VALUE) (__arm_wsr("PSP_NS", (VALUE)))
#define __TZ_get_MSP_NS() (__arm_rsr("MSP_NS"))
#define __TZ_set_MSP_NS(VALUE) (__arm_wsr("MSP_NS", (VALUE)))
#define __TZ_get_SP_NS() (__arm_rsr("SP_NS"))
#define __TZ_set_SP_NS(VALUE) (__arm_wsr("SP_NS", (VALUE)))
#define __TZ_get_PRIMASK_NS() (__arm_rsr("PRIMASK_NS"))
#define __TZ_set_PRIMASK_NS(VALUE) (__arm_wsr("PRIMASK_NS", (VALUE)))
#define __TZ_get_BASEPRI_NS() (__arm_rsr("BASEPRI_NS"))
#define __TZ_set_BASEPRI_NS(VALUE) (__arm_wsr("BASEPRI_NS", (VALUE)))
#define __TZ_get_FAULTMASK_NS() (__arm_rsr("FAULTMASK_NS"))
#define __TZ_set_FAULTMASK_NS(VALUE)(__arm_wsr("FAULTMASK_NS", (VALUE)))
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
// without main extensions, the non-secure PSPLIM is RAZ/WI
#define __TZ_get_PSPLIM_NS() (0U)
#define __TZ_set_PSPLIM_NS(VALUE) ((void)(VALUE))
#else
#define __TZ_get_PSPLIM_NS() (__arm_rsr("PSPLIM_NS"))
#define __TZ_set_PSPLIM_NS(VALUE) (__arm_wsr("PSPLIM_NS", (VALUE)))
#endif
#define __TZ_get_MSPLIM_NS() (__arm_rsr("MSPLIM_NS"))
#define __TZ_set_MSPLIM_NS(VALUE) (__arm_wsr("MSPLIM_NS", (VALUE)))
#define __NOP __iar_builtin_no_operation
#define __CLZ __iar_builtin_CLZ
#define __CLREX __iar_builtin_CLREX
#define __DMB __iar_builtin_DMB
#define __DSB __iar_builtin_DSB
#define __ISB __iar_builtin_ISB
#define __LDREXB __iar_builtin_LDREXB
#define __LDREXH __iar_builtin_LDREXH
#define __LDREXW __iar_builtin_LDREX
#define __RBIT __iar_builtin_RBIT
#define __REV __iar_builtin_REV
#define __REV16 __iar_builtin_REV16
__IAR_FT int16_t __REVSH(int16_t val)
{
return (int16_t) __iar_builtin_REVSH(val);
}
#define __ROR __iar_builtin_ROR
#define __RRX __iar_builtin_RRX
#define __SEV __iar_builtin_SEV
#if !__IAR_M0_FAMILY
#define __SSAT __iar_builtin_SSAT
#endif
#define __STREXB __iar_builtin_STREXB
#define __STREXH __iar_builtin_STREXH
#define __STREXW __iar_builtin_STREX
#if !__IAR_M0_FAMILY
#define __USAT __iar_builtin_USAT
#endif
#define __WFE __iar_builtin_WFE
#define __WFI __iar_builtin_WFI
#if __ARM_MEDIA__
#define __SADD8 __iar_builtin_SADD8
#define __QADD8 __iar_builtin_QADD8
#define __SHADD8 __iar_builtin_SHADD8
#define __UADD8 __iar_builtin_UADD8
#define __UQADD8 __iar_builtin_UQADD8
#define __UHADD8 __iar_builtin_UHADD8
#define __SSUB8 __iar_builtin_SSUB8
#define __QSUB8 __iar_builtin_QSUB8
#define __SHSUB8 __iar_builtin_SHSUB8
#define __USUB8 __iar_builtin_USUB8
#define __UQSUB8 __iar_builtin_UQSUB8
#define __UHSUB8 __iar_builtin_UHSUB8
#define __SADD16 __iar_builtin_SADD16
#define __QADD16 __iar_builtin_QADD16
#define __SHADD16 __iar_builtin_SHADD16
#define __UADD16 __iar_builtin_UADD16
#define __UQADD16 __iar_builtin_UQADD16
#define __UHADD16 __iar_builtin_UHADD16
#define __SSUB16 __iar_builtin_SSUB16
#define __QSUB16 __iar_builtin_QSUB16
#define __SHSUB16 __iar_builtin_SHSUB16
#define __USUB16 __iar_builtin_USUB16
#define __UQSUB16 __iar_builtin_UQSUB16
#define __UHSUB16 __iar_builtin_UHSUB16
#define __SASX __iar_builtin_SASX
#define __QASX __iar_builtin_QASX
#define __SHASX __iar_builtin_SHASX
#define __UASX __iar_builtin_UASX
#define __UQASX __iar_builtin_UQASX
#define __UHASX __iar_builtin_UHASX
#define __SSAX __iar_builtin_SSAX
#define __QSAX __iar_builtin_QSAX
#define __SHSAX __iar_builtin_SHSAX
#define __USAX __iar_builtin_USAX
#define __UQSAX __iar_builtin_UQSAX
#define __UHSAX __iar_builtin_UHSAX
#define __USAD8 __iar_builtin_USAD8
#define __USADA8 __iar_builtin_USADA8
#define __SSAT16 __iar_builtin_SSAT16
#define __USAT16 __iar_builtin_USAT16
#define __UXTB16 __iar_builtin_UXTB16
#define __UXTAB16 __iar_builtin_UXTAB16
#define __SXTB16 __iar_builtin_SXTB16
#define __SXTAB16 __iar_builtin_SXTAB16
#define __SMUAD __iar_builtin_SMUAD
#define __SMUADX __iar_builtin_SMUADX
#define __SMMLA __iar_builtin_SMMLA
#define __SMLAD __iar_builtin_SMLAD
#define __SMLADX __iar_builtin_SMLADX
#define __SMLALD __iar_builtin_SMLALD
#define __SMLALDX __iar_builtin_SMLALDX
#define __SMUSD __iar_builtin_SMUSD
#define __SMUSDX __iar_builtin_SMUSDX
#define __SMLSD __iar_builtin_SMLSD
#define __SMLSDX __iar_builtin_SMLSDX
#define __SMLSLD __iar_builtin_SMLSLD
#define __SMLSLDX __iar_builtin_SMLSLDX
#define __SEL __iar_builtin_SEL
#define __QADD __iar_builtin_QADD
#define __QSUB __iar_builtin_QSUB
#define __PKHBT __iar_builtin_PKHBT
#define __PKHTB __iar_builtin_PKHTB
#endif
#else /* __ICCARM_INTRINSICS_VERSION__ == 2 */
#if __IAR_M0_FAMILY
/* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */
#define __CLZ __cmsis_iar_clz_not_active
#define __SSAT __cmsis_iar_ssat_not_active
#define __USAT __cmsis_iar_usat_not_active
#define __RBIT __cmsis_iar_rbit_not_active
#define __get_APSR __cmsis_iar_get_APSR_not_active
#endif
#if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) ))
#define __get_FPSCR __cmsis_iar_get_FPSR_not_active
#define __set_FPSCR __cmsis_iar_set_FPSR_not_active
#endif
#ifdef __INTRINSICS_INCLUDED
#error intrinsics.h is already included previously!
#endif
#include <intrinsics.h>
#if __IAR_M0_FAMILY
/* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */
#undef __CLZ
#undef __SSAT
#undef __USAT
#undef __RBIT
#undef __get_APSR
__STATIC_INLINE uint8_t __CLZ(uint32_t data)
{
if (data == 0U) { return 32U; }
uint32_t count = 0U;
uint32_t mask = 0x80000000U;
while ((data & mask) == 0U)
{
count += 1U;
mask = mask >> 1U;
}
return count;
}
__STATIC_INLINE uint32_t __RBIT(uint32_t v)
{
uint8_t sc = 31U;
uint32_t r = v;
for (v >>= 1U; v; v >>= 1U)
{
r <<= 1U;
r |= v & 1U;
sc--;
}
return (r << sc);
}
__STATIC_INLINE uint32_t __get_APSR(void)
{
uint32_t res;
__asm("MRS %0,APSR" : "=r" (res));
return res;
}
#endif
#if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) ))
#undef __get_FPSCR
#undef __set_FPSCR
#define __get_FPSCR() (0)
#define __set_FPSCR(VALUE) ((void)VALUE)
#endif
#pragma diag_suppress=Pe940
#pragma diag_suppress=Pe177
#define __enable_irq __enable_interrupt
#define __disable_irq __disable_interrupt
#define __NOP __no_operation
#define __get_xPSR __get_PSR
#if (!defined(__ARM_ARCH_6M__) || __ARM_ARCH_6M__==0)
__IAR_FT uint32_t __LDREXW(uint32_t volatile *ptr)
{
return __LDREX((unsigned long *)ptr);
}
__IAR_FT uint32_t __STREXW(uint32_t value, uint32_t volatile *ptr)
{
return __STREX(value, (unsigned long *)ptr);
}
#endif
/* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */
#if (__CORTEX_M >= 0x03)
__IAR_FT uint32_t __RRX(uint32_t value)
{
uint32_t result;
__ASM("RRX %0, %1" : "=r"(result) : "r" (value) : "cc");
return(result);
}
__IAR_FT void __set_BASEPRI_MAX(uint32_t value)
{
__asm volatile("MSR BASEPRI_MAX,%0"::"r" (value));
}
#define __enable_fault_irq __enable_fiq
#define __disable_fault_irq __disable_fiq
#endif /* (__CORTEX_M >= 0x03) */
__IAR_FT uint32_t __ROR(uint32_t op1, uint32_t op2)
{
return (op1 >> op2) | (op1 << ((sizeof(op1)*8)-op2));
}
#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
(defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
__IAR_FT uint32_t __get_MSPLIM(void)
{
uint32_t res;
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
// without main extensions, the non-secure MSPLIM is RAZ/WI
res = 0U;
#else
__asm volatile("MRS %0,MSPLIM" : "=r" (res));
#endif
return res;
}
__IAR_FT void __set_MSPLIM(uint32_t value)
{
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
// without main extensions, the non-secure MSPLIM is RAZ/WI
(void)value;
#else
__asm volatile("MSR MSPLIM,%0" :: "r" (value));
#endif
}
__IAR_FT uint32_t __get_PSPLIM(void)
{
uint32_t res;
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
// without main extensions, the non-secure PSPLIM is RAZ/WI
res = 0U;
#else
__asm volatile("MRS %0,PSPLIM" : "=r" (res));
#endif
return res;
}
__IAR_FT void __set_PSPLIM(uint32_t value)
{
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
// without main extensions, the non-secure PSPLIM is RAZ/WI
(void)value;
#else
__asm volatile("MSR PSPLIM,%0" :: "r" (value));
#endif
}
__IAR_FT uint32_t __TZ_get_CONTROL_NS(void)
{
uint32_t res;
__asm volatile("MRS %0,CONTROL_NS" : "=r" (res));
return res;
}
__IAR_FT void __TZ_set_CONTROL_NS(uint32_t value)
{
__asm volatile("MSR CONTROL_NS,%0" :: "r" (value));
}
__IAR_FT uint32_t __TZ_get_PSP_NS(void)
{
uint32_t res;
__asm volatile("MRS %0,PSP_NS" : "=r" (res));
return res;
}
__IAR_FT void __TZ_set_PSP_NS(uint32_t value)
{
__asm volatile("MSR PSP_NS,%0" :: "r" (value));
}
__IAR_FT uint32_t __TZ_get_MSP_NS(void)
{
uint32_t res;
__asm volatile("MRS %0,MSP_NS" : "=r" (res));
return res;
}
__IAR_FT void __TZ_set_MSP_NS(uint32_t value)
{
__asm volatile("MSR MSP_NS,%0" :: "r" (value));
}
__IAR_FT uint32_t __TZ_get_SP_NS(void)
{
uint32_t res;
__asm volatile("MRS %0,SP_NS" : "=r" (res));
return res;
}
__IAR_FT void __TZ_set_SP_NS(uint32_t value)
{
__asm volatile("MSR SP_NS,%0" :: "r" (value));
}
__IAR_FT uint32_t __TZ_get_PRIMASK_NS(void)
{
uint32_t res;
__asm volatile("MRS %0,PRIMASK_NS" : "=r" (res));
return res;
}
__IAR_FT void __TZ_set_PRIMASK_NS(uint32_t value)
{
__asm volatile("MSR PRIMASK_NS,%0" :: "r" (value));
}
__IAR_FT uint32_t __TZ_get_BASEPRI_NS(void)
{
uint32_t res;
__asm volatile("MRS %0,BASEPRI_NS" : "=r" (res));
return res;
}
__IAR_FT void __TZ_set_BASEPRI_NS(uint32_t value)
{
__asm volatile("MSR BASEPRI_NS,%0" :: "r" (value));
}
__IAR_FT uint32_t __TZ_get_FAULTMASK_NS(void)
{
uint32_t res;
__asm volatile("MRS %0,FAULTMASK_NS" : "=r" (res));
return res;
}
__IAR_FT void __TZ_set_FAULTMASK_NS(uint32_t value)
{
__asm volatile("MSR FAULTMASK_NS,%0" :: "r" (value));
}
__IAR_FT uint32_t __TZ_get_PSPLIM_NS(void)
{
uint32_t res;
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
// without main extensions, the non-secure PSPLIM is RAZ/WI
res = 0U;
#else
__asm volatile("MRS %0,PSPLIM_NS" : "=r" (res));
#endif
return res;
}
__IAR_FT void __TZ_set_PSPLIM_NS(uint32_t value)
{
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
// without main extensions, the non-secure PSPLIM is RAZ/WI
(void)value;
#else
__asm volatile("MSR PSPLIM_NS,%0" :: "r" (value));
#endif
}
__IAR_FT uint32_t __TZ_get_MSPLIM_NS(void)
{
uint32_t res;
__asm volatile("MRS %0,MSPLIM_NS" : "=r" (res));
return res;
}
__IAR_FT void __TZ_set_MSPLIM_NS(uint32_t value)
{
__asm volatile("MSR MSPLIM_NS,%0" :: "r" (value));
}
#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */
#endif /* __ICCARM_INTRINSICS_VERSION__ == 2 */
#define __BKPT(value) __asm volatile ("BKPT %0" : : "i"(value))
#if __IAR_M0_FAMILY
__STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat)
{
if ((sat >= 1U) && (sat <= 32U))
{
const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
const int32_t min = -1 - max ;
if (val > max)
{
return max;
}
else if (val < min)
{
return min;
}
}
return val;
}
__STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat)
{
if (sat <= 31U)
{
const uint32_t max = ((1U << sat) - 1U);
if (val > (int32_t)max)
{
return max;
}
else if (val < 0)
{
return 0U;
}
}
return (uint32_t)val;
}
#endif
#if (__CORTEX_M >= 0x03) /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */
__IAR_FT uint8_t __LDRBT(volatile uint8_t *addr)
{
uint32_t res;
__ASM("LDRBT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
return ((uint8_t)res);
}
__IAR_FT uint16_t __LDRHT(volatile uint16_t *addr)
{
uint32_t res;
__ASM("LDRHT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
return ((uint16_t)res);
}
__IAR_FT uint32_t __LDRT(volatile uint32_t *addr)
{
uint32_t res;
__ASM("LDRT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
return res;
}
__IAR_FT void __STRBT(uint8_t value, volatile uint8_t *addr)
{
__ASM("STRBT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory");
}
__IAR_FT void __STRHT(uint16_t value, volatile uint16_t *addr)
{
__ASM("STRHT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory");
}
__IAR_FT void __STRT(uint32_t value, volatile uint32_t *addr)
{
__ASM("STRT %1, [%0]" : : "r" (addr), "r" (value) : "memory");
}
#endif /* (__CORTEX_M >= 0x03) */
#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
(defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
__IAR_FT uint8_t __LDAB(volatile uint8_t *ptr)
{
uint32_t res;
__ASM volatile ("LDAB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
return ((uint8_t)res);
}
__IAR_FT uint16_t __LDAH(volatile uint16_t *ptr)
{
uint32_t res;
__ASM volatile ("LDAH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
return ((uint16_t)res);
}
__IAR_FT uint32_t __LDA(volatile uint32_t *ptr)
{
uint32_t res;
__ASM volatile ("LDA %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
return res;
}
__IAR_FT void __STLB(uint8_t value, volatile uint8_t *ptr)
{
__ASM volatile ("STLB %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
}
__IAR_FT void __STLH(uint16_t value, volatile uint16_t *ptr)
{
__ASM volatile ("STLH %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
}
__IAR_FT void __STL(uint32_t value, volatile uint32_t *ptr)
{
__ASM volatile ("STL %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
}
__IAR_FT uint8_t __LDAEXB(volatile uint8_t *ptr)
{
uint32_t res;
__ASM volatile ("LDAEXB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
return ((uint8_t)res);
}
__IAR_FT uint16_t __LDAEXH(volatile uint16_t *ptr)
{
uint32_t res;
__ASM volatile ("LDAEXH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
return ((uint16_t)res);
}
__IAR_FT uint32_t __LDAEX(volatile uint32_t *ptr)
{
uint32_t res;
__ASM volatile ("LDAEX %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
return res;
}
__IAR_FT uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr)
{
uint32_t res;
__ASM volatile ("STLEXB %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
return res;
}
__IAR_FT uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr)
{
uint32_t res;
__ASM volatile ("STLEXH %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
return res;
}
__IAR_FT uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr)
{
uint32_t res;
__ASM volatile ("STLEX %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
return res;
}
#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */
#undef __IAR_FT
#undef __IAR_M0_FAMILY
#undef __ICCARM_V8
#pragma diag_default=Pe940
#pragma diag_default=Pe177
#endif /* __CMSIS_ICCARM_H__ */

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