Index: firmware/.cproject
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/.cproject (.../.cproject) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/.cproject (.../.cproject) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -52,6 +52,8 @@
@@ -100,53 +102,73 @@
-
-
Index: firmware/.gitignore
===================================================================
diff -u -r792764062d7b7826af10e030277f18379af4fcd1 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/.gitignore (.../.gitignore) (revision 792764062d7b7826af10e030277f18379af4fcd1)
+++ firmware/.gitignore (.../.gitignore) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -12,7 +12,6 @@
*.pch
# Libraries
-*.lib
*.a
*.la
*.lo
Index: firmware/.settings/org.eclipse.cdt.codan.core.prefs
===================================================================
diff -u -r792764062d7b7826af10e030277f18379af4fcd1 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/.settings/org.eclipse.cdt.codan.core.prefs (.../org.eclipse.cdt.codan.core.prefs) (revision 792764062d7b7826af10e030277f18379af4fcd1)
+++ firmware/.settings/org.eclipse.cdt.codan.core.prefs (.../org.eclipse.cdt.codan.core.prefs) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,3 +1,75 @@
eclipse.preferences.version=1
inEditor=false
onBuild=false
+org.eclipse.cdt.codan.checkers.errnoreturn=Warning
+org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false}
+org.eclipse.cdt.codan.checkers.errreturnvalue=Error
+org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"}
+org.eclipse.cdt.codan.checkers.nocommentinside=-Error
+org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"}
+org.eclipse.cdt.codan.checkers.nolinecomment=-Error
+org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"}
+org.eclipse.cdt.codan.checkers.noreturn=Error
+org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false}
+org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
+org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"}
+org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
+org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"}
+org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"}
+org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error
+org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"}
+org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false}
+org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
+org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()}
+org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
+org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"}
+org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
+org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true}
+org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error
+org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"}
+org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"}
+org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"}
+org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
+org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"}
+org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
+org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"}
+org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
+org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"}
+org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
+org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"}
+org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"}
+org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
+org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
+org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"}
+org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
+org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"}
+org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
+org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"}
+org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"}
+org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
+org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"}
+org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
+org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"}
+org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()}
+org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false}
+org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false}
+org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"}
+org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true}
+org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true}
+org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")}
+org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"}
Index: firmware/.settings/org.eclipse.core.resources.prefs
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/.settings/org.eclipse.core.resources.prefs (.../org.eclipse.core.resources.prefs) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/.settings/org.eclipse.core.resources.prefs (.../org.eclipse.core.resources.prefs) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -12,3 +12,16 @@
encoding//Debug/source/subdir_rules.mk=UTF-8
encoding//Debug/source/subdir_vars.mk=UTF-8
encoding//Debug/sources.mk=UTF-8
+encoding//Release/App/Modes/subdir_rules.mk=UTF-8
+encoding//Release/App/Modes/subdir_vars.mk=UTF-8
+encoding//Release/App/Services/FlashAPI/subdir_rules.mk=UTF-8
+encoding//Release/App/Services/FlashAPI/subdir_vars.mk=UTF-8
+encoding//Release/App/Services/subdir_rules.mk=UTF-8
+encoding//Release/App/Services/subdir_vars.mk=UTF-8
+encoding//Release/App/Tasks/subdir_rules.mk=UTF-8
+encoding//Release/App/Tasks/subdir_vars.mk=UTF-8
+encoding//Release/makefile=UTF-8
+encoding//Release/objects.mk=UTF-8
+encoding//Release/source/subdir_rules.mk=UTF-8
+encoding//Release/source/subdir_vars.mk=UTF-8
+encoding//Release/sources.mk=UTF-8
Index: firmware/App/BLCommon.h
===================================================================
diff -u -rf2652e85c8676d0356fea2690cfd9cac716ca795 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/BLCommon.h (.../BLCommon.h) (revision f2652e85c8676d0356fea2690cfd9cac716ca795)
+++ firmware/App/BLCommon.h (.../BLCommon.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,9 +1,3 @@
-/*
- * BLCommon.h
- *
- * Created on: Aug 1, 2024
- * Author: fw
- */
#ifndef __BLCOMMON_H__
#define __BLCOMMON_H__
Index: firmware/App/Common.h
===================================================================
diff -u -rf2652e85c8676d0356fea2690cfd9cac716ca795 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Common.h (.../Common.h) (revision f2652e85c8676d0356fea2690cfd9cac716ca795)
+++ firmware/App/Common.h (.../Common.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,50 +1,98 @@
-/*
- * Common.h
- *
- * Created on: Aug 5, 2024
- * Author: fw
- */
#ifndef __COMMON_H__
#define __COMMON_H__
-#define SW_UPDATE_FLASH_BUFFER_SIZE 128
+#include "BLCommon.h"
+/**
+ * @defgroup CommonHeader CommonHeader
+ * @brief Provides commonly used definitions and macros.
+ *
+ * @addtogroup CommonHeader
+ * @{
+ */
+
+// ********** public definitions **********
+
+#define NUM_OF_FW_STACKS 3 ///< Number of firmware stacks (TD, DD, RO).
+#define CAN_MESSAGE_PAYLOAD_SIZE 8 ///< CAN message payload size in bytes.
+#define FIRMWARE_START_ADDRESS 0x00010000 ///< Firmware start address.
+#define FIRMWARE_CRC_TABLE_ADDRESS 0x10020 ///< The starting address of CRC table for firmware image.
+#define SW_UPDATE_FLASH_BUFFER_SIZE 256 ///< Software update flash buffer bytes.
+#define MASK_OFF_MSB 0x00FF ///< Bits to mask off the most significant byte of a 2-byte word
+#define MASK_OFF_LSB 0xFF00 ///< Bits to mask off the least significant byte of a 2-byte word
+#define SHIFT_8_BITS_FOR_BYTE_SHIFT 8 ///< Number of bits to shift in order to shift a byte
+#define MASK_OFF_NIBBLE_MSB 0x0F ///< Bits to mask off the most significant nibble of a byte
+
+#define NUM_OF_CMD_CAN_FRAMES 1 ///< Number of command CAN frames.
+
+#define GET_LSB_OF_WORD(w) ((U08)((w) & MASK_OFF_MSB)) ///< Macro returns the least signficant byte of a 2-byte word.
+#define GET_MSB_OF_WORD(w) ((U08)(((w) >> SHIFT_8_BITS_FOR_BYTE_SHIFT) & MASK_OFF_MSB)) ///< Macro returns the most signficant byte of a 2-byte word.
+#define MAKE_WORD_OF_BYTES(h, l) ((((U16)(h) << SHIFT_8_BITS_FOR_BYTE_SHIFT) & MASK_OFF_LSB) \
+ | ((U16)(l) & MASK_OFF_MSB)) ///< Macro merges two bytes into a 2-byte word.
+#define INC_WRAP(v, l, u) ((v) >= (u) ? (l) : ((v) + 1)) ///< Macro increments a value and wraps to a minimum when a maximum is reached.
+
// **** Types ****
-typedef float F32; ///< 32-bit floating point type
-typedef double F64; ///< 64-bit floating point type
-typedef long long S64; ///< 64-bit signed integer type
-typedef unsigned int U32; ///< 32-bit unsigned integer type
-typedef int S32; ///< 32-bit signed integer type
-typedef unsigned short U16; ///< 16-bit unsigned integer type
-typedef short S16; ///< 16-bit signed integer type
-typedef unsigned char U08; ///< 8-bit unsigned integer type
-typedef unsigned int BOOL; ///< 32-bit boolean type
-typedef unsigned char BYTE; ///< 8-bit byte type
+typedef float F32; ///< 32-bit floating point type.
+typedef double F64; ///< 64-bit floating point type.
+typedef long long S64; ///< 64-bit signed integer type.
+typedef unsigned int U32; ///< 32-bit unsigned integer type.
+typedef int S32; ///< 32-bit signed integer type.
+typedef unsigned short U16; ///< 16-bit unsigned integer type.
+typedef short S16; ///< 16-bit signed integer type.
+typedef unsigned char U08; ///< 8-bit unsigned integer type.
+typedef unsigned int BOOL; ///< 32-bit boolean type.
+typedef unsigned char BYTE; ///< 8-bit byte type.
+/// Bootloader operations modes enumeration
+typedef enum BL_Op_Modes
+{
+ MODE_STAND = 0, ///< Mode standby.
+ MODE_UPDATE, ///< Mode update.
+ NUM_OF_MODES ///< Number of modes.
+} BL_OP_MODE_T;
+/// Mode standby states enumeration
+typedef enum SW_Mode_Standby_States
+{
+ STANDBY_CHECK_FOR_UPDATE_STATE = 0, ///< Standby check for update state.
+ STANDBY_CHECK_FW_AND_FPGA_IMAGES_STATE, ///< Standby check firmware and FPGA images state.
+ STANDBY_IDLE_STATE, ///< Standby idle state.
+ NUM_OF_MODE_STANDBY_STATES ///< Number of standby states.
+} MODE_STANDBY_STATE_T;
+
+/// Mode update states enumeration
+typedef enum SW_Mode_Update_States
+{
+ SW_UPDATE_UPDATE_STATE = 0, ///< Update update state.
+ SW_UPDATE_VERIFY_STATE, ///< Update verify state.
+ SW_UPDATE_ABORT_STATE, ///< Update abort state.
+ NUM_OF_MODE_SW_UPDATE_STATES ///< Number of update states.
+} MODE_SW_UPDATE_STATE_T;
+
+/// Software update destinations enumeration
typedef enum SW_Update_Destinations
{
- //UPDATE_NONE = 0,
- UPDATE_FIRMWARE = 0,
- UPDATE_FPGA,
- NUM_OF_UPDAT_DESTS
-} SW_UPDATE_DESINTATIONS_T;
+ UPDATE_FIRMWARE = 0, ///< Update firmware.
+ UPDATE_FPGA, ///< Update FPGA.
+ NUM_OF_UPDATE_DESTS ///< Number of update destinations.
+} SW_UPDATE_DESINTATION_T;
+/// Software update CAN mailboxes enumeration
typedef enum SW_Update_CAN_Mail_Boxes
{
- SW_UPDATE_NOT_USED = 0,
- SW_UPDATE_COMMAD,
- SW_UPDATE_TD_UPDATE,
- SW_UPDATE_DD_UPDATE,
- SW_UPDATE_RO_UPDATE,
- PLACE_HOLDER_TO_REMOVE_CAN,
- SW_UPDATE_RESP,
- NUM_OF_SW_UPDATE_MBOXES,
-} SW_UPDATE_CAN_MAIL_BOXES_T;
+ SW_UPDATE_NOT_USED = 0, // 0 ///< Software update not used mailbox.
+ SW_UPDATE_COMMAD, // 0x601 ///< Software update command mailbox.
+ SW_UPDATE_TD_UPDATE, // 0x602 ///< Software update TD update mailbox.
+ SW_UPDATE_DD_UPDATE, // 0x603 ///< Software update DD update mailbox.
+ SW_UPDATE_RO_UPDATE, // 0x604 ///< Software update RO update mailbox.
+ PLACE_HOLDER_TO_REMOVE_CAN, // 0x605 // TODO remove
+ SW_UPDATE_RESP, // 0x606 ///< Software update respond mailbox.
+ SW_TEST, // 0x607 // TODO remove
+ NUM_OF_SW_UPDATE_MBOXES, ///< Number of software update mailboxes.
+} SW_UPDATE_CAN_MAIL_BOX_T;
-
/*!
Normal Protocol:
UI->FW: SwUpdateCommand[cmd=start]
@@ -69,31 +117,36 @@
If streaming encounters problems we use a command with Resync
so that the FW will dump it's indexes and be ready for new data.
*/
+/// Software update commands enumeration
typedef enum SW_Update_Commands
{
- UPDATE_CMD_START = 0,
- UPDATE_CMD_ABORT,
+ UPDATE_CMD_START = 0, ///< Update command start.
+ UPDATE_CMD_ABORT, ///< Update command abort.
UPDATE_CMD_RUNAPP, // TODO is this needed?
- UPDATE_CMD_VERIFY,
+ UPDATE_CMD_VERIFY, ///< Update command verify.
UPDATE_CMD_VERSION, // TODO is this needed?
- UPDATE_CMD_VERIFIED,
- UPDATE_CMD_RESYNC,
- NUM_OF_UPDATE_CMDS
-} SW_UPDATE_CMDS_T;
+ UPDATE_CMD_VERIFIED, // TODO is this needed?
+ UPDATE_CMD_RESYNC, ///< Update command resync.
+ UPDATE_CMD_IDLE, ///< Update command idle.
+ NUM_OF_UPDATE_CMDS ///< Number of update commands.
+} SW_UPDATE_CMD_T;
+/// Acknowledge or not acknowledge enumeration
typedef enum Ack_Nack
{
- NACK = 0,
- ACK,
- NUM_OF_ACK_NACK
+ NACK = 0, ///< Nack.
+ ACK, ///< Ack.
+ NUM_OF_ACK_NACK ///< Number of ack/nack states.
} ACK_NACK_STATUS_T;
-
-typedef struct
+/// Software update corresponding stack mailbox
+static const SW_UPDATE_CAN_MAIL_BOX_T RECEIVE_MSG_ID[ NUM_OF_FW_STACKS ] =
{
- BOOL isSWUpdateBufferReady;
- SW_UPDATE_DESINTATIONS_T dest;
-} SW_UPDATE_BUFFER_STATUS_T;
+ SW_UPDATE_TD_UPDATE, ///< Software update TD.
+ SW_UPDATE_DD_UPDATE, ///< Software update DD.
+ SW_UPDATE_RO_UPDATE ///< Software update RO.
+};
+/**@}*/
#endif
Fisheye: Tag 0c085209bea23f66011059a7c19796c1e4b246fa refers to a dead (removed) revision in file `firmware/App/Modes/ModeInitPOST.c'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 0c085209bea23f66011059a7c19796c1e4b246fa refers to a dead (removed) revision in file `firmware/App/Modes/ModeInitPOST.h'.
Fisheye: No comparison available. Pass `N' to diff?
Index: firmware/App/Modes/ModeStandby.c
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,8 +1,224 @@
-/*
- * ModeStandby.c
- *
- * Created on: Jul 31, 2024
- * Author: fw
- */
+#include // For memcpy and memset
+
+#include "sys_core.h" // To disable RAM and Flash ECC
+#include "sys_mpu.h" // To disable MPU
+
+#include "Download.h"
+#include "FPGA.h"
#include "ModeStandby.h"
+#include "NVDataMgmt.h"
+#include "OperationModes.h"
+#include "Timers.h"
+#include "Utilities.h"
+
+/**
+ * @addtogroup BLStandbyMode
+ * @{
+ */
+
+// ********** private definitions **********
+
+#define WAIT_FOR_UPDATE_FROM_UI_MS 1000 ///< Wait for update timeout in milliseconds.
+
+// ********** private data **********
+
+static MODE_STANDBY_STATE_T standbyCurrentState; ///< Standby current state.
+static U32 waitForUpdateMsgStartTimeMS; ///< Wait for update start time in milliseconds.
+
+// ********** private function prototypes **********
+
+static MODE_STANDBY_STATE_T handleStandbyModeCheckForUpdateState( void );
+static MODE_STANDBY_STATE_T handleStandbyModeCheckFWAndFPGAImages( void );
+static MODE_STANDBY_STATE_T handleStandbyModeIdleState( void );
+
+static void jumpToApplication( void );
+
+/*********************************************************************//**
+ * @brief
+ * The initStandbyMode function initializes the standby mode.
+ * @details \b Inputs: none
+ * @details \b Outputs: standbyCurrentState, waitForUpdateMsgStartTimeMS
+ * @return none
+ *************************************************************************/
+void initStandbyMode( void )
+{
+ standbyCurrentState = STANDBY_CHECK_FOR_UPDATE_STATE;
+ waitForUpdateMsgStartTimeMS = getMSTimerCount();
+}
+
+/*********************************************************************//**
+ * @brief
+ * The transitionToStandbyMode function prepares for transition to Standby Mode.
+ * @details \b Inputs: none
+ * @details \b Outputs: Standby Mode unit re-initialized
+ * @return none
+ *************************************************************************/
+U32 transitionToStandbyMode( void )
+{
+ initStandbyMode();
+
+ return standbyCurrentState;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The execStandbyMode function executes the Standby Mode state machine.
+ * @details \b Inputs: standbyCurrentState
+ * @details \b Outputs: standbyCurrentState
+ * @return current state (sub-mode)
+ *************************************************************************/
+U32 execStandbyMode( void )
+{
+ // If the bootloader is in standby mode and update request is received at any time, request a transition to update mode
+ if ( ( UPDATE_CMD_START == getSWUpdateCommandState() ) || ( TRUE == hasUpdateBeenRequested() ) )
+ {
+ // TODO if we are here because of the FPGA register, clear it so it won't be called again.
+ requestNewOperationMode( MODE_UPDATE );
+ }
+
+ switch( standbyCurrentState )
+ {
+ case STANDBY_CHECK_FOR_UPDATE_STATE:
+ standbyCurrentState = handleStandbyModeCheckForUpdateState();
+ break;
+
+ case STANDBY_CHECK_FW_AND_FPGA_IMAGES_STATE:
+ standbyCurrentState = handleStandbyModeCheckFWAndFPGAImages();
+ break;
+
+ case STANDBY_IDLE_STATE:
+ standbyCurrentState = handleStandbyModeIdleState();
+ break;
+
+ default:
+ // Do nothing
+ break;
+ }
+
+ return standbyCurrentState;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleStandbyModeCheckForUpdateState function handles the standby
+ * check for update state.
+ * This state waits for a software update command (i.e. verify or abort) and
+ * then transitions accordingly. Also, if the wait for update has timed out
+ * it transitions to the verifying firmware and FPGA images.
+ * @details \b Inputs: waitForUpdateMsgStartTimeMS
+ * @details \b Outputs: none
+ * @return next state of the standby mode state machine
+ *************************************************************************/
+static MODE_STANDBY_STATE_T handleStandbyModeCheckForUpdateState( void )
+{
+ MODE_STANDBY_STATE_T state = STANDBY_CHECK_FOR_UPDATE_STATE;
+ SW_UPDATE_CMD_T cmd = getSWUpdateCommandState();
+
+ switch ( cmd )
+ {
+ case UPDATE_CMD_ABORT:
+ state = STANDBY_IDLE_STATE;
+ break;
+
+ case UPDATE_CMD_VERIFY:
+ state = STANDBY_CHECK_FW_AND_FPGA_IMAGES_STATE;
+ break;
+
+ default:
+ // Do nothing
+ break;
+ }
+
+ if ( TRUE == didTimeout( waitForUpdateMsgStartTimeMS, WAIT_FOR_UPDATE_FROM_UI_MS ) )
+ {
+ state = STANDBY_CHECK_FW_AND_FPGA_IMAGES_STATE;
+ }
+
+ return state;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleStandbyModeCheckFWAndFPGAImages function handles the standby
+ * check firmware and FPGA images state.
+ * This state checks the integrity of the firmware as well as the FPGA header
+ * to make sure the images are valid.
+ * @details \b Inputs: none
+ * @details \b Outputs: none
+ * @return next state of the standby mode state machine
+ *************************************************************************/
+static MODE_STANDBY_STATE_T handleStandbyModeCheckFWAndFPGAImages( void )
+{
+ MODE_STANDBY_STATE_T state = STANDBY_IDLE_STATE;
+ BOOL isFirmwareImageValid = FALSE;
+ BOOL isFPGAImageValid = FALSE;
+ // TODO why a bad code passes the CRC?
+ // TODO send the results back (pass/fail) up to be sent to the cloud.
+ if ( TRUE == isFWCRCTableValid() )
+ {
+ isFirmwareImageValid = runFWIntegrityTest();
+ }
+
+ if ( TRUE == isFPGAIDValid() )
+ {
+ isFPGAImageValid = TRUE;
+ }
+
+ // NOTE: If either of the images (firmware or FPGA) failed, go to the idle state until another update request is received
+ if ( ( TRUE == isFirmwareImageValid ) && ( TRUE == isFPGAImageValid ) )
+ {
+ // All good, jump to application
+ jumpToApplication();
+ }
+
+ return state;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleStandbyModeIdleState function handles the standby idle state.
+ * This state waits until a new update request arrives.
+ * @details \b Inputs: none
+ * @details \b Outputs: none
+ * @return next state of the standby mode state machine
+ *************************************************************************/
+static MODE_STANDBY_STATE_T handleStandbyModeIdleState( void )
+{
+ MODE_STANDBY_STATE_T state = STANDBY_IDLE_STATE;
+
+ // This state does nothing and waits until another update request is received. This could be because the update was aborted or
+ // the firmware or FPGA have bad images. So we cannot jump to the application.
+
+ return state;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The jumpToApplication function handles the jump to application commands.
+ * This function, disables interrupts that were used in the bootloader and
+ * then it jumps to the fimrware start address.
+ * @details \b Inputs: none
+ * @details \b Outputs: none
+ * @return none
+ *************************************************************************/
+static void jumpToApplication( void )
+{
+ U32 jumpAddress = (U32)FIRMWARE_START_ADDRESS;
+
+ // Disable various memory protections
+ _coreDisableRamEcc_();
+ _coreDisableFlashEcc_();
+ _mpuDisable_();
+
+ // Disable all interrupts
+ _disable_interrupt_();
+ _disable_IRQ_interrupt_();
+ _disable_FIQ_interrupt_();
+
+ ((void (*)(void))jumpAddress)();
+ while(1);
+}
+
+/**@}*/
+
Index: firmware/App/Modes/ModeStandby.h
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Modes/ModeStandby.h (.../ModeStandby.h) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/App/Modes/ModeStandby.h (.../ModeStandby.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,13 +1,28 @@
-/*
- * ModeStandby.h
- *
- * Created on: Jul 31, 2024
- * Author: fw
- */
#ifndef __MODESTANDBY_H__
#define __MODESTANDBY_H__
+#include "BLCommon.h"
+/**
+ * @defgroup BLStandbyMode BLStandbyMode
+ * @brief Standby mode unit. Manages the Standby mode functions via a state
+ * machine.
+ *
+ * @addtogroup BLStandbyMode
+ * @{
+ */
+// ********** public definitions **********
+
+// ********** public function prototypes **********
+
+void initStandbyMode( void );
+
+U32 transitionToStandbyMode( void );
+
+U32 execStandbyMode( void );
+
+/**@}*/
+
#endif
Index: firmware/App/Modes/ModeUpdate.c
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Modes/ModeUpdate.c (.../ModeUpdate.c) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/App/Modes/ModeUpdate.c (.../ModeUpdate.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,8 +1,173 @@
-/*
- * ModeUpdate.c
- *
- * Created on: Jul 31, 2024
- * Author: fw
- */
+#include "CommBuffers.h"
+#include "Download.h"
+#include "FPGA.h"
#include "ModeUpdate.h"
+#include "NVDataMgmt.h"
+#include "OperationModes.h"
+
+/**
+ * @addtogroup UpdateMode
+ * @{
+ */
+
+// ********** private definitions **********
+
+// ********** private data **********
+
+static MODE_SW_UPDATE_STATE_T updateCurrentState;
+
+// ********** private function prototypes **********
+
+static MODE_SW_UPDATE_STATE_T handleUpdateModeUpdateState( void );
+static MODE_SW_UPDATE_STATE_T handleUpdateModeVerifyState( void );
+static MODE_SW_UPDATE_STATE_T handleUpdateModeAbortState( void );
+
+/*********************************************************************//**
+ * @brief
+ * The initUpdateMode function initializes the Update Mode Unit.
+ * @details \b Inputs: none
+ * @details \b Outputs: updateCurrentState
+ * @return none
+ *************************************************************************/
+void initUpdateMode( void )
+{
+ updateCurrentState = SW_UPDATE_UPDATE_STATE;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The transitionToUpdateMode function prepares for transition to Update Mode.
+ * @details \b Inputs: none
+ * @details \b Outputs: Update Mode unit re-initialized
+ * @return none
+ *************************************************************************/
+U32 transitionToUpdateMode( void )
+{
+ initUpdateMode();
+ // Clear the NV status to start from the start address of the firmware
+ clearSWUpdateNVStatus();
+ // TODO clear FPGA clear stuff here
+ // Got the update command so we are in the update mode. Clear the command
+ clearSWUpdateCommandState();
+
+ return updateCurrentState;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The execUpdateMode function executes the Update Mode state machine.
+ * @details \b Inputs: updateCurrentState
+ * @details \b Outputs: updateCurrentState
+ * @return current state (sub-mode)
+ *************************************************************************/
+U32 execUpdateMode( void )
+{
+ switch( updateCurrentState )
+ {
+ case SW_UPDATE_UPDATE_STATE:
+ updateCurrentState = handleUpdateModeUpdateState();
+ break;
+
+ case SW_UPDATE_ABORT_STATE:
+ updateCurrentState = handleUpdateModeAbortState();
+ break;
+
+ case SW_UPDATE_VERIFY_STATE:
+ updateCurrentState = handleUpdateModeVerifyState();
+ break;
+
+ default:
+ // Do nothing
+ break;
+ }
+
+ return updateCurrentState;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleUpdateModeUpdateState function handles the update mode update state.
+ * This state checks for the SW update command to transition to the proper state.
+ * @details \b Inputs: none
+ * @details \b Outputs: none
+ * @return next state of the update mode state machine
+ *************************************************************************/
+static MODE_SW_UPDATE_STATE_T handleUpdateModeUpdateState( void )
+{
+ MODE_SW_UPDATE_STATE_T state = SW_UPDATE_UPDATE_STATE;
+ SW_UPDATE_CMD_T cmd = getSWUpdateCommandState();
+
+ switch( cmd )
+ {
+ case UPDATE_CMD_VERIFY:
+ state = SW_UPDATE_VERIFY_STATE;
+ break;
+
+ case UPDATE_CMD_ABORT:
+ state = SW_UPDATE_ABORT_STATE;
+ break;
+
+ default:
+ // Do nothing, keep updating
+ break;
+ }
+
+ return state;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleUpdateModeVerifyState function handles the update mode verify state.
+ * This state checks for the destination of the current update which can be
+ * either firmware or FPGA. If the update destination was FPGA it makes sure
+ * the FPGA update has been completed and then transitions to standby mode.
+ * If the update destination was firmware, it transitions to standby mode.
+ * @details \b Inputs: none
+ * @details \b Outputs: none
+ * @return next state of the update mode state machine
+ *************************************************************************/
+static MODE_SW_UPDATE_STATE_T handleUpdateModeVerifyState( void )
+{
+ MODE_SW_UPDATE_STATE_T state = SW_UPDATE_VERIFY_STATE;
+ SW_UPDATE_DESINTATION_T dest = getSWUpdateDestination();
+
+ switch( dest )
+ {
+ case UPDATE_FPGA:
+ if ( TRUE == isFPGAFlashComplete() )
+ {
+ requestNewOperationMode( MODE_STAND );
+ }
+ break;
+
+ case UPDATE_FIRMWARE:
+ requestNewOperationMode( MODE_STAND );
+ break;
+
+ default:
+ // Do nothing
+ break;
+ }
+
+ return state;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleUpdateModeAbortState function handles the update mode abort state.
+ * This state transitions to standby mode upon requesting to abort the update.
+ * @details \b Inputs: none
+ * @details \b Outputs: none
+ * @return next state of the update mode state machine
+ *************************************************************************/
+static MODE_SW_UPDATE_STATE_T handleUpdateModeAbortState( void )
+{
+ MODE_SW_UPDATE_STATE_T state = SW_UPDATE_ABORT_STATE;
+
+ requestNewOperationMode( MODE_STAND );
+
+ return state;
+}
+
+/**@}*/
Index: firmware/App/Modes/ModeUpdate.h
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Modes/ModeUpdate.h (.../ModeUpdate.h) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/App/Modes/ModeUpdate.h (.../ModeUpdate.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,13 +1,28 @@
-/*
- * ModeUpdate.h
- *
- * Created on: Jul 31, 2024
- * Author: fw
- */
#ifndef _MODEUPDATE_H__
#define _MODEUPDATE_H__
+#include "BLCommon.h"
+/**
+ * @defgroup UpdateMode UpdateMode
+ * @brief Update mode unit. Manages the Update mode functions via a state
+ * machine.
+ *
+ * @addtogroup UpdateMode
+ * @{
+ */
+// ********** public definitions **********
+
+// ********** public function prototypes **********
+
+void initUpdateMode( void );
+
+U32 transitionToUpdateMode( void );
+
+U32 execUpdateMode( void );
+
+/**@}*/
+
#endif
Index: firmware/App/Modes/OperationModes.c
===================================================================
diff -u
--- firmware/App/Modes/OperationModes.c (revision 0)
+++ firmware/App/Modes/OperationModes.c (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -0,0 +1,122 @@
+
+#include "ModeStandby.h"
+#include "ModeUpdate.h"
+#include "OperationModes.h"
+
+/**
+ * @addtogroup BLOperationModes
+ * @{
+ */
+
+// ********** private definitions **********
+
+// ********** private data **********
+
+static BL_OP_MODE_T currentMode; ///< The currently active state of the active mode.
+static BL_OP_MODE_T previousMode; ///< Previous state of the operations mode.
+static BL_OP_MODE_T requestedMode; ///< Request a new mode.
+static U32 currentSubMode; ///< The currently active state of the active mode.
+
+// ********** private function prototypes **********
+
+static void transitionToNewOperationMode( BL_OP_MODE_T newMode );
+
+/*********************************************************************//**
+ * @brief
+ * The initOperationModes function initializes the Operation Modes unit.
+ * @details \b Inputs: none
+ * @details \b Outputs: Operation Modes unit initialized.
+ * @return none
+ *************************************************************************/
+void initOperationModes( void )
+{
+ currentMode = MODE_STAND;
+ previousMode = MODE_STAND;
+ requestedMode = MODE_STAND;
+ currentSubMode = 0;
+
+ initStandbyMode();
+ initUpdateMode();
+}
+
+/*********************************************************************//**
+ * @brief
+ * The execOperationModes function executes the Operation Modes state machine.
+ * @details \b Inputs: previousMode, currentMode, requestedMode
+ * @details \b Outputs: previousMode, currentMode, requestedMode
+ * @return none
+ *************************************************************************/
+void execOperationModes( void )
+{
+ if ( requestedMode != currentMode )
+ {
+ previousMode = currentMode;
+ currentMode = requestedMode;
+
+ transitionToNewOperationMode( currentMode );
+ }
+
+ switch ( currentMode )
+ {
+ case MODE_STAND:
+ currentSubMode = execStandbyMode();
+ break;
+
+ case MODE_UPDATE:
+ currentSubMode = execUpdateMode();
+ break;
+
+ default:
+ // Do nothing
+ // TODO alarm?
+ break;
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The requestNewOperationMode function requests transition to a new
+ * operation mode. The request will be arbitrated when the state machine
+ * is next executed.
+ * @details \b Inputs: none
+ * @details \b Outputs: requestedMode
+ * @param new mode request
+ * @return none
+ *************************************************************************/
+void requestNewOperationMode( BL_OP_MODE_T newMode )
+{
+ if ( newMode < NUM_OF_MODES )
+ {
+ requestedMode = newMode;
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The transitionToNewOperationMode function calls the transition to function
+ * for a new operation mode that we are transitioning to.
+ * @details \b Inputs: none
+ * @details \b Outputs: transition function called for new mode
+ * @param new mode that is transitioning to.
+ * @return none
+ *************************************************************************/
+static void transitionToNewOperationMode( BL_OP_MODE_T newMode )
+{
+ switch ( newMode )
+ {
+ case MODE_STAND:
+ currentSubMode = transitionToStandbyMode();
+ break;
+
+ case MODE_UPDATE:
+ currentSubMode = transitionToUpdateMode();
+ break;
+
+ default:
+ // Do nothing for now
+ // TODO alarm?
+ break;
+ }
+}
+
+/**@}*/
Index: firmware/App/Modes/OperationModes.h
===================================================================
diff -u
--- firmware/App/Modes/OperationModes.h (revision 0)
+++ firmware/App/Modes/OperationModes.h (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -0,0 +1,25 @@
+
+#ifndef __OPERATIONMODES_H__
+#define __OPERATIONMODES_H__
+
+#include "BLCommon.h"
+
+/**
+ * @defgroup BLOperationModes BLOperationModes
+ * @brief Operation Modes unit.
+ *
+ * @addtogroup BLOperationModes
+ * @{
+ */
+
+// ********** public definitions **********
+
+void initOperationModes( void );
+
+void execOperationModes( void );
+
+void requestNewOperationMode( BL_OP_MODE_T newMode );
+
+/**@}*/
+
+#endif
Index: firmware/App/Services/Comm.c
===================================================================
diff -u
--- firmware/App/Services/Comm.c (revision 0)
+++ firmware/App/Services/Comm.c (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -0,0 +1,68 @@
+
+#include "sci.h"
+#include "sys_dma.h"
+
+#include "Comm.h"
+
+/**
+ * @addtogroup CommInterrupts
+ * @{
+ */
+
+// ********** private definitions **********
+
+// ********** private data **********
+
+/*********************************************************************//**
+ * @brief
+ * The setSCI2DMAReceiveInterrupt function enables DMA receive interrupts
+ * for the SCI2 peripheral.
+ * @details Inputs: none
+ * @details Outputs: DMA receive interrupt is enabled.
+ * @return none
+ *************************************************************************/
+void setSCI2DMAReceiveInterrupt( void )
+{
+ scilinREG->SETINT = SCI_DMA_RECEIVE_INT;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The setSCI2DMATransmitInterrupt function enables DMA transmit interrupts
+ * for the SCI2 peripheral.
+ * @details Inputs: none
+ * @details Outputs: DMA transmit interrupt is enabled.
+ * @return none
+ *************************************************************************/
+void setSCI2DMATransmitInterrupt( void )
+{
+ scilinREG->SETINT = SCI_DMA_TRANSMIT_INT;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The clearSCI2DMAReceiveInterrupt function disables DMA receive interrupts
+ * for the SCI2 peripheral.
+ * @details Inputs: none
+ * @details Outputs: DMA receive interrupt is disabled.
+ * @return none
+ *************************************************************************/
+void clearSCI2DMAReceiveInterrupt( void )
+{
+ scilinREG->CLEARINT = SCI_DMA_RECEIVE_INT;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The clearSCI2DMATransmitInterrupt function disables DMA transmit interrupts
+ * for the SCI2 peripheral.
+ * @details Inputs: none
+ * @details Outputs: DMA transmit interrupt is disabled.
+ * @return none
+ *************************************************************************/
+void clearSCI2DMATransmitInterrupt( void )
+{
+ scilinREG->CLEARINT = SCI_DMA_TRANSMIT_INT;
+}
+
+/**@}*/
Index: firmware/App/Services/Comm.h
===================================================================
diff -u
--- firmware/App/Services/Comm.h (revision 0)
+++ firmware/App/Services/Comm.h (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -0,0 +1,28 @@
+
+#ifndef __COMM_H__
+#define __COMM_H__
+
+#include "BLCommon.h"
+
+/**
+ * @defgroup CommInterrupts CommInterrupts
+ * @brief The communication unit provides low level comm signal,
+ * status, and some interrupt handling functions.
+ *
+ * @addtogroup CommInterrupts
+ * @{
+ */
+
+// ********** public definitions **********
+
+#define SCI_DMA_TRANSMIT_INT 0x00010000 ///< Bit mask for setting/clearing serial DMA transmit interrupts.
+#define SCI_DMA_RECEIVE_INT 0x00060000 ///< Bit mask for setting/clearing serial DMA receive interrupts.
+
+void setSCI2DMAReceiveInterrupt( void );
+void setSCI2DMATransmitInterrupt( void );
+void clearSCI2DMAReceiveInterrupt( void );
+void clearSCI2DMATransmitInterrupt( void );
+
+/**@}*/
+
+#endif
Index: firmware/App/Services/CommBuffers.c
===================================================================
diff -u -rf2652e85c8676d0356fea2690cfd9cac716ca795 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Services/CommBuffers.c (.../CommBuffers.c) (revision f2652e85c8676d0356fea2690cfd9cac716ca795)
+++ firmware/App/Services/CommBuffers.c (.../CommBuffers.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,257 +1,160 @@
-/*
- * CommBuffers.c
- *
- * Created on: Aug 2, 2024
- * Author: fw
- */
-#include "string.h" // For memcpy
-#include "can.h"
+#include // For memcpy
#include "CommBuffers.h"
#include "Utilities.h"
-#define NUM_OF_FW_STACKS 3
-#define CAN_MESSAGE_PAYLOAD_SIZE 8
-#define SW_UPDATE_FINAL_MSG_INDEX 0xFFFF
+/**
+ * @addtogroup CommBuffers
+ * @{
+ */
-typedef struct
-{
- U08 msgID;
- U08 updateCmd;
- U16 cyberRandom;
- U32 msgCRC;
-} SW_UPDATE_CMD_STATUS_T;
+// ********** private definitions **********
-typedef struct
-{
- U32 SWUpdateFrameCount;
- U08 msgID;
- U08 updateDest;
- U16 cyberIndex;
- U32 msgCRC;
- U08 SWUpdateBuffer[ SW_UPDATE_FLASH_BUFFER_SIZE ];
-} SW_UPDATE_RCV_STATUS_T;
+#define UPDATE_PACKET_SIZE_BYTES ( SW_UPDATE_FLASH_BUFFER_SIZE + CAN_MESSAGE_PAYLOAD_SIZE ) ///< Software update packet size in bytes.
+/// Software update buffer structure
typedef struct
{
- U08 msgID;
- U08 msgAckNackStatus;
- U16 cyberRandom;
- U32 msgCRC;
-} SW_UPDATE_RESP_STATUS_T;
+ U32 SWUpdateFrameCount; ///< Software update frame count.
+ U08 SWUpdateBuffer[ UPDATE_PACKET_SIZE_BYTES ]; ///< Software update buffer.
+} SW_UPDATE_BUFFER_T;
-static const U32 NUM_OF_CAN_FRAMES_TO_UPDATE = ( SW_UPDATE_FLASH_BUFFER_SIZE + CAN_MESSAGE_PAYLOAD_SIZE ) / CAN_MESSAGE_PAYLOAD_SIZE;
+// ********** private data **********
-static const SW_UPDATE_CAN_MAIL_BOXES_T RECEIVE_MSG_ID[ NUM_OF_FW_STACKS ] =
-{
- SW_UPDATE_TD_UPDATE,
- SW_UPDATE_DD_UPDATE,
- SW_UPDATE_RO_UPDATE
-};
+static SW_UPDATE_BUFFER_T SWUpdateBuffer[ NUM_OF_SW_UPDATE_MBOXES ]; ///< Software update buffer array.
-static SW_UPDATE_CMD_STATUS_T SWUpdateCmdStatus;
-static SW_UPDATE_RCV_STATUS_T SWUpdateRcvStatus;
-static SW_UPDATE_BUFFER_STATUS_T SWUpdateBufferStatus;
+// ********** private function prototypes ********
-static U32 FORTESTREMOVE = 0;
-
-static void consumeReceivedUpdateCANFrame( U08* data );
-static void processReceivedUpdateCANFrame( void );
-static void processRecievedCmdCANFrame( U08* data );
-
+/*********************************************************************//**
+ * @brief
+ * The initCommBuffers function initializes the CommBuffers unit.
+ * @details Inputs: none
+ * @details Outputs: CommBuffers unit initialized.
+ * @return none
+ *************************************************************************/
void initCommBuffers( void )
{
- clearSWUpdateBuffer( TRUE );
- clearSWUpdateBuffer( FALSE );
+ SW_UPDATE_CAN_MAIL_BOX_T mailBox;
+
+ for ( mailBox = SW_UPDATE_NOT_USED; mailBox < NUM_OF_SW_UPDATE_MBOXES; mailBox++ )
+ {
+ clearCommBuffer( mailBox );
+ }
}
-void handleCANMsgInterrupt( SW_UPDATE_CAN_MAIL_BOXES_T MailBox )
+/*********************************************************************//**
+ * @brief
+ * The addToCommBuffer function adds data of specified length to a given
+ * communication buffer.
+ * @note This function is thread safe. IRQ interrupts are disabled during
+ * buffer operations.
+ * @details Inputs: SWUpdateBuffer[]
+ * @details Outputs: SWUpdateBuffer[]
+ * @param mailbox ID of buffer to add data to
+ * @param data Pointer to byte array containing data to add to buffer
+ * @param len Length of data (in bytes)
+ * @return TRUE if data added to buffer successfully, FALSE if not
+ *************************************************************************/
+BOOL addToCommBuffer( SW_UPDATE_CAN_MAIL_BOX_T mailBox, U08* data, U32 len )
{
- // TODO do we need check the range of the messages?
+ BOOL status = FALSE;
- U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ];
-
- if ( SW_UPDATE_COMMAD == MailBox )
+ if ( mailBox < NUM_OF_SW_UPDATE_MBOXES )
{
- if ( FALSE != canIsRxMessageArrived( canREG1, MailBox ) )
- {
- U32 result = canGetData( canREG1, MailBox, data );
+ _disable_IRQ();
+ U32 currentFrameCount = SWUpdateBuffer[ mailBox ].SWUpdateFrameCount;
- if ( result != 0 )
- {
- processRecievedCmdCANFrame( data );
- }
- }
- }
- else
- {
- SW_UPDATE_CAN_MAIL_BOXES_T thisStackMailBox = RECEIVE_MSG_ID[ BL_STACK_ID ];
-
- if ( thisStackMailBox == MailBox )
+ // Check if the number of bytes is less than the allowed bytes in the mailbox buffer.
+ if ( ( currentFrameCount * CAN_MESSAGE_PAYLOAD_SIZE ) <= UPDATE_PACKET_SIZE_BYTES )
{
- if ( FALSE != canIsRxMessageArrived( canREG1, MailBox ) )
- {
- U32 result = canGetData( canREG1, MailBox, data );
+ U32 currentBufferIndex = currentFrameCount * len;
- if ( result != 0 )
- {
- consumeReceivedUpdateCANFrame( data );
- }
- }
+ // Copy the received can frame into the buffer
+ memcpy( SWUpdateBuffer[ mailBox ].SWUpdateBuffer + currentBufferIndex, data, len );
+
+ // Increment the current frame count
+ SWUpdateBuffer[ mailBox ].SWUpdateFrameCount += 1;
+ status = TRUE;
}
+ _enable_IRQ();
}
-}
-void getSWUpdateBufferStatus( SW_UPDATE_BUFFER_STATUS_T* status )
-{
- memcpy( status, &SWUpdateBufferStatus, sizeof( SW_UPDATE_BUFFER_STATUS_T ) );
+ return status;
}
-
-void getSWUpdateBuffer( U08* data )
+/*********************************************************************//**
+ * @brief
+ * The getFromCommBuffer function fills a given byte array with a specified
+ * number of bytes from a given buffer and returns the number of bytes
+ * retrieved from the buffer.
+ * and, if needed, switch double buffers to draw the rest of the requested data.
+ * @note This function is thread safe. IRQ interrupts are disabled during buffer
+ * operations.
+ * @details Inputs: SWUpdateBuffer[]
+ * @details Outputs: none
+ * @param mailbox ID of buffer to retrieve data from
+ * @param data Pointer to byte array to populate with buffer data
+ * @param len Number of bytes to retrieve from buffer into given byte array.
+ * @return the number of bytes retrieved.
+ *************************************************************************/
+BOOL getCommBuffer( SW_UPDATE_CAN_MAIL_BOX_T mailBox, U08* data, U32 len )
{
- memcpy( data, &SWUpdateRcvStatus.SWUpdateBuffer, sizeof( SWUpdateRcvStatus.SWUpdateBuffer ) );
-}
+ BOOL status = FALSE;
-void sendAckNackStatusFromFirmware( ACK_NACK_STATUS_T status, BOOL cmd )
-{
- SW_UPDATE_RESP_STATUS_T resp;
-
- U32 calcCRC = 0;
-
- resp.msgID = ( TRUE == cmd ? SWUpdateCmdStatus.msgID : SWUpdateRcvStatus.msgID );
- resp.msgAckNackStatus = status;
- resp.cyberRandom = 0;
- resp.msgCRC = crc32( calcCRC, (U08*)&resp, sizeof( SW_UPDATE_RESP_STATUS_T ) - sizeof( U32 ) );
-
- if ( 0 != canTransmit( canREG1, (U32)SW_UPDATE_RESP, (U08*)&resp ) )
+ if ( ( mailBox < NUM_OF_SW_UPDATE_MBOXES ) && ( len <= UPDATE_PACKET_SIZE_BYTES ) )
{
- clearSWUpdateBuffer( cmd );
+ _disable_IRQ();
+ memcpy( data, SWUpdateBuffer[ mailBox ].SWUpdateBuffer, len );
+ status = TRUE;
+ _enable_IRQ();
}
-}
-void clearSWUpdateBuffer( BOOL cmd )
-{
- if ( FALSE == cmd )
- {
- memset( &SWUpdateRcvStatus, 0x0, sizeof( SW_UPDATE_RCV_STATUS_T ) );
- memset( &SWUpdateBufferStatus, 0x0, sizeof( SW_UPDATE_BUFFER_STATUS_T ) );
- }
- else
- {
- memset( &SWUpdateCmdStatus, 0x0, sizeof( SW_UPDATE_CMD_STATUS_T ) );
- }
+ return status;
}
-
-// ********** private functions **********
-
-static void consumeReceivedUpdateCANFrame( U08* data )
+/*********************************************************************//**
+ * @brief
+ * The getNumberOfBytesInBuffer function determines how many bytes
+ * are currently contained in a given comm buffer.
+ * @details Inputs: SWUpdateBuffer[]
+ * @details Outputs: none
+ * @param mailbox ID of buffer to get byte count for
+ * @return the number of bytes currently in the given comm buffer.
+ *************************************************************************/
+S32 getNumberOfBytesInBuffer( SW_UPDATE_CAN_MAIL_BOX_T mailBox )
{
- if ( SWUpdateRcvStatus.SWUpdateFrameCount <= NUM_OF_CAN_FRAMES_TO_UPDATE )
- {
- if ( 0 == SWUpdateRcvStatus.SWUpdateFrameCount )
- {
- memcpy( &SWUpdateRcvStatus.msgID, data, sizeof( U08 ) );
- data += sizeof( U08 );
- memcpy( &SWUpdateRcvStatus.updateDest, data, sizeof( U08 ) );
- data += sizeof( U08 );
- memcpy( &SWUpdateRcvStatus.cyberIndex, data, sizeof( U16 ) );
- data += sizeof( U16 );
- memcpy( &SWUpdateRcvStatus.msgCRC, data, sizeof( U32 ) );
- }
- else
- {
- U32 currentBufferIndex = ( SWUpdateRcvStatus.SWUpdateFrameCount - 1 ) * CAN_MESSAGE_PAYLOAD_SIZE;
+ S32 bytes = -1;
- memcpy( SWUpdateRcvStatus.SWUpdateBuffer + currentBufferIndex, data, CAN_MESSAGE_PAYLOAD_SIZE );
- }
-
- SWUpdateRcvStatus.SWUpdateFrameCount++;
-
- //if ( NUM_OF_CAN_FRAMES_TO_UPDATE == SWUpdateRcvStatus.SWUpdateFrameCount )
- if ( SWUpdateRcvStatus.SWUpdateFrameCount % NUM_OF_CAN_FRAMES_TO_UPDATE == 0 )
- {
- processReceivedUpdateCANFrame();
-
- // TODO REmove
- if ( FORTESTREMOVE == 1 )
- {
- BOOL test = FALSE;
- }
- FORTESTREMOVE++;
- //sendAckNackStatusFromFirmware( ACK, FALSE );
- //clearSWUpdateBuffer( FALSE );
- // TODO Remove
- }
- else
- {
- //SWUpdateRcvStatus.SWUpdateFrameCount++;
- }
+ if ( mailBox < NUM_OF_SW_UPDATE_MBOXES )
+ {
+ bytes = SWUpdateBuffer[ mailBox ].SWUpdateFrameCount * CAN_MESSAGE_PAYLOAD_SIZE;
}
+
+ return bytes;
}
-static void processReceivedUpdateCANFrame( void )
+/*********************************************************************//**
+ * @brief
+ * The clearBuffer function clears (empties) a given buffer.
+ * @note This function is thread safe. IRQ interrupts are disabled while
+ * buffers are being cleared.
+ * @details Inputs: none
+ * @details Outputs: given buffer is cleared.
+ * @param buffer ID of the buffer to clear
+ * @return none
+ *************************************************************************/
+void clearCommBuffer( SW_UPDATE_CAN_MAIL_BOX_T mailBox )
{
- U32 calcCRC = 0;
- BOOL hasCRCPassed = FALSE;
-
- calcCRC = crc32( calcCRC, SWUpdateRcvStatus.SWUpdateBuffer, MAX_CRC_CALC_DATA_SIZE );
- hasCRCPassed = ( SWUpdateRcvStatus.msgCRC == calcCRC ? TRUE : FALSE );
-
- // TODO remove
- hasCRCPassed = TRUE;
- // TODO remove
-
- if ( TRUE == hasCRCPassed )
+ _disable_IRQ();
+ if ( mailBox < NUM_OF_SW_UPDATE_MBOXES )
{
- switch ( SWUpdateRcvStatus.updateDest )
- {
- case UPDATE_FIRMWARE:
- if ( SWUpdateRcvStatus.cyberIndex != SW_UPDATE_FINAL_MSG_INDEX )
- {
- SWUpdateBufferStatus.isSWUpdateBufferReady = TRUE;
- SWUpdateBufferStatus.dest = UPDATE_FIRMWARE;
- }
- else
- {
- sendAckNackStatusFromFirmware( ACK, FALSE );
- clearSWUpdateBuffer( FALSE );
- }
- break;
-
- case UPDATE_FPGA:
- SWUpdateBufferStatus.isSWUpdateBufferReady = TRUE;
- SWUpdateBufferStatus.dest = UPDATE_FPGA;
- break;
-
- default:
- // Do nothing
- break;
- }
+ memset( &SWUpdateBuffer[ mailBox ], 0x0, sizeof( SW_UPDATE_BUFFER_T ) );
}
+ _enable_IRQ();
}
-static void processRecievedCmdCANFrame( U08* data )
-{
- ACK_NACK_STATUS_T ackStatus;
+// ********** private functions **********
- U32 calcCRC = 0;
- BOOL hasCRCPassed = FALSE;
+/**@}*/
- memcpy( &SWUpdateCmdStatus.msgID, data, sizeof( U08 ) );
- data += sizeof( U08 );
- memcpy( &SWUpdateCmdStatus.updateCmd, data, sizeof( U08 ) );
- data += sizeof( U08 );
- memcpy( &SWUpdateCmdStatus.cyberRandom, data, sizeof( U16 ) );
- data += sizeof( U16 );
- memcpy( &SWUpdateCmdStatus.msgCRC, data, sizeof( U32 ) );
-
- calcCRC = crc32( calcCRC, (U08*)&SWUpdateCmdStatus, sizeof( SW_UPDATE_CMD_STATUS_T ) - sizeof( U32 ) );
- hasCRCPassed = ( SWUpdateRcvStatus.msgCRC == calcCRC ? TRUE : FALSE );
- ackStatus = ( TRUE == hasCRCPassed ? ACK : NACK );
-
- sendAckNackStatusFromFirmware( ackStatus, TRUE );
-}
-
Index: firmware/App/Services/CommBuffers.h
===================================================================
diff -u -rf2652e85c8676d0356fea2690cfd9cac716ca795 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Services/CommBuffers.h (.../CommBuffers.h) (revision f2652e85c8676d0356fea2690cfd9cac716ca795)
+++ firmware/App/Services/CommBuffers.h (.../CommBuffers.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,25 +1,33 @@
-/*
- * CommBuffers.h
- *
- * Created on: Aug 2, 2024
- * Author: fw
- */
#ifndef __COMMBUFFERS_H__
#define __COMMBUFFERS_H__
#include "BLCommon.h"
+/**
+ * @defgroup CommBuffers CommBuffers
+ * @brief The communication buffers unit provides buffering services for
+ * incoming and outgoing CAN data. A separate buffer is provided for each
+ * CAN ID (channel) so that frame order is maintained for a given channel.
+ *
+ * @addtogroup CommBuffers
+ * @{
+ */
+
+// ********** public definitions **********
+
+// ********** public function prototypes **********
+
void initCommBuffers( void );
-void handleCANMsgInterrupt( SW_UPDATE_CAN_MAIL_BOXES_T MailBox );
+BOOL addToCommBuffer( SW_UPDATE_CAN_MAIL_BOX_T mailBox, U08* data, U32 len );
-void getSWUpdateBufferStatus( SW_UPDATE_BUFFER_STATUS_T* status );
+BOOL getCommBuffer( SW_UPDATE_CAN_MAIL_BOX_T mailBox, U08* data, U32 len );
-void getSWUpdateBuffer( U08* data );
+S32 getNumberOfBytesInBuffer( SW_UPDATE_CAN_MAIL_BOX_T mailBox );
-void sendAckNackStatusFromFirmware( ACK_NACK_STATUS_T status, BOOL cmd );
+void clearCommBuffer( SW_UPDATE_CAN_MAIL_BOX_T mailBox );
-void clearSWUpdateBuffer( BOOL cmd );
+/**@}*/
#endif
Index: firmware/App/Services/CopyFlashAPI2RAM.asm
===================================================================
diff -u
--- firmware/App/Services/CopyFlashAPI2RAM.asm (revision 0)
+++ firmware/App/Services/CopyFlashAPI2RAM.asm (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -0,0 +1,30 @@
+;-------------------------------------------------------------------------------
+;
+; Copy the Flash API from flash to RAM.
+;
+;-------------------------------------------------------------------------------
+
+ .def _copyAPI2RAM_
+ .asmfunc
+
+_copyAPI2RAM_
+
+ .ref apiLoadStart
+flash_load .word apiLoadStart
+ .ref apiRunStart
+flash_run .word apiRunStart
+ .ref apiLoadSize
+flash_size .word apiLoadSize
+
+ ldr r0, flash_load
+ ldr r1, flash_run
+ ldr r2, flash_size
+ add r2, r1, r2
+copy_loop1:
+ ldr r3, [r0], #4
+ str r3, [r1], #4
+ cmp r1, r2
+ blt copy_loop1
+ bx lr
+
+ .endasmfunc
Index: firmware/App/Services/Download.c
===================================================================
diff -u
--- firmware/App/Services/Download.c (revision 0)
+++ firmware/App/Services/Download.c (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -0,0 +1,387 @@
+
+#include "can.h" // TODO remove for testing only
+
+#include // For memcpy and memset
+
+#include "CommBuffers.h"
+#include "Download.h"
+#include "FPGA.h"
+#include "NVDataMgmt.h"
+#include "SystemComm.h"
+#include "Utilities.h"
+
+/**
+ * @addtogroup Download
+ * @{
+ */
+
+// ********** private definitions **********
+
+#define SW_UPDATE_FINAL_MSG_INDEX 0xFFFF ///< Software update final message index.
+#define SHIFT_BITS_TO_GET_TARGET 4 ///< Shift bits by 4 to get the update target.
+
+static const U32 NUM_OF_CAN_BYTES_FOR_UPDATE = SW_UPDATE_FLASH_BUFFER_SIZE + CAN_MESSAGE_PAYLOAD_SIZE; ///< Number of CAN bytes for update.
+
+// ********** private data **********
+
+/// Software update response status structure
+typedef struct
+{
+ U08 msgID; ///< Message ID.
+ U08 msgAckNackStatus; ///< Message ack or nack status.
+ U16 cyberRandom; ///< Message cyber random.
+ U32 msgCRC; ///< Message CRC.
+} SW_UPDATE_RESP_STATUS_T;
+
+/// Software update command status structure
+typedef struct
+{
+ U08 msgID; ///< Message ID.
+ U08 updateCmd; ///< Update command.
+ U16 cyberRandom; ///< Cyber random.
+ U32 msgCRC; ///< Message CRC.
+} SW_UPDATE_CMD_STATUS_T;
+
+/// Software update receive update status structure
+typedef struct
+{
+ U08 msgID; ///< Message ID.
+ U08 updateDest; ///< Update destination (FW, FPGA).
+ U16 updatePayloadLen; ///< Update payload length in bytes.
+ U32 msgCRC; ///< Message CRC.
+ U08 SWUpdateBuffer[ SW_UPDATE_FLASH_BUFFER_SIZE ]; ///< Software update buffer.
+} SW_UPDATE_RCV_STATUS_T;
+
+static SW_UPDATE_RCV_STATUS_T SWUpdateRCVStatus; ///< Software update receive status.
+static SW_UPDATE_CMD_T SWUpdateCommandState; ///< Software update command state.
+static SW_UPDATE_CAN_MAIL_BOX_T thisStackMailBox; ///< The mailbox of this stack.
+static U32 sizeToWrite; ///< Size to write to destination.
+
+static U32 REMOVETHEVAR = 0; // TODO remove
+
+// ********** private function prototypes **********
+
+static void handleIncomingCmdMessage( SW_UPDATE_CAN_MAIL_BOX_T mailBox );
+static void handleIncomingUpdateMessage( SW_UPDATE_CAN_MAIL_BOX_T mailBox );
+static void prepareResponseMessage( U08 respOfMsgID, ACK_NACK_STATUS_T ackNack, SW_UPDATE_RESP_STATUS_T* respBuffer );
+static void clearSWUpdateBuffer( void );
+static ACK_NACK_STATUS_T handleFirmwareUpdate( void );
+static ACK_NACK_STATUS_T handleFPGAUpdate( void );
+
+/*********************************************************************//**
+ * @brief
+ * The initDownload function initializes the download unit.
+ * @details \b Inputs: none
+ * @details \b Outputs: thisStackMailBox
+ * @return none
+ *************************************************************************/
+void initDownload( void )
+{
+ thisStackMailBox = RECEIVE_MSG_ID[ BL_STACK_ID ];
+
+ clearSWUpdateBuffer();
+ clearSWUpdateCommandState();
+}
+
+/*********************************************************************//**
+ * @brief
+ * The execDownload function executes the download state machine.
+ * @details \b Inputs: none
+ * @details \b Outputs: none
+ * @return none
+ *************************************************************************/
+void execDownload( void )
+{
+ handleIncomingCmdMessage( SW_UPDATE_COMMAD );
+ handleIncomingUpdateMessage( thisStackMailBox );
+}
+
+/*********************************************************************//**
+ * @brief
+ * The getSWUpdateCommandState function returns the current software update
+ * command state.
+ * @details \b Inputs: SWUpdateCommandState
+ * @details \b Outputs: none
+ * @return current software update command state
+ *************************************************************************/
+SW_UPDATE_CMD_T getSWUpdateCommandState( void )
+{
+ return SWUpdateCommandState;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The getSWUpdateDestination function returns the current software update
+ * destination (firmware or FPGA).
+ * @details \b Inputs: SWUpdateRCVStatus
+ * @details \b Outputs: none
+ * @return current software update destination
+ *************************************************************************/
+SW_UPDATE_DESINTATION_T getSWUpdateDestination( void )
+{
+ return (SW_UPDATE_DESINTATION_T)SWUpdateRCVStatus.updateDest;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The clearSWUpdateCommandState function clears the software update command
+ * state to idle state.
+ * @details \b Inputs: none
+ * @details \b Outputs: SWUpdateCommandState
+ * @return none
+ *************************************************************************/
+void clearSWUpdateCommandState( void )
+{
+ SWUpdateCommandState = UPDATE_CMD_IDLE;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The sendFPGAAckNackStatus function sends the ack or nack status to the
+ * application.
+ * @details \b Inputs: SWUpdateRCVStatus, thisStackMailBox
+ * @details \b Outputs: none
+ * @param ack or nack status to be sent
+ * @return none
+ *************************************************************************/
+void sendFPGAAckNackStatus( ACK_NACK_STATUS_T ackNackStatus )
+{
+ SW_UPDATE_RESP_STATUS_T resp;
+
+ prepareResponseMessage( SWUpdateRCVStatus.msgID, ackNackStatus, &resp );
+ sendAckNackStatusFromFirmware( (U08*)&resp );
+ clearCommBuffer( thisStackMailBox );
+}
+
+U08 getTempRemoveMSGID()
+{
+ return SWUpdateRCVStatus.msgID;
+}
+
+// ********** private functions **********
+
+/*********************************************************************//**
+ * @brief
+ * The handleIncomingCmdMessage function handles the incoming command message
+ * from the CAN bus. Once the entire message has been received, it is processed
+ * and the corresponding destination is informed that an update is available.
+ * @details \b Inputs: SWUpdateCmdStatus
+ * @details \b Outputs: SWUpdateCmdStatus
+ * @param mailbox of the buffer that has been received
+ * @return none
+ *************************************************************************/
+static void handleIncomingCmdMessage( SW_UPDATE_CAN_MAIL_BOX_T mailBox )
+{
+ // Peek into the number of bytes received for the command buffer
+ S32 bytesInBuffer = getNumberOfBytesInBuffer( mailBox );
+
+ if ( bytesInBuffer == CAN_MESSAGE_PAYLOAD_SIZE )
+ {
+ // If the command buffer has been received, get it from the comm buffer and process it
+ SW_UPDATE_CMD_STATUS_T SWUpdateCmdStatus;
+ SW_UPDATE_RESP_STATUS_T resp;
+
+ getCommBuffer( mailBox, (U08*)&SWUpdateCmdStatus, sizeof( SW_UPDATE_CMD_STATUS_T ) );
+
+ BOOL hasCRCPassed = FALSE;
+ ACK_NACK_STATUS_T ackStatus = NACK;
+ U32 calcCRC = 0;
+ U08 msgID = SWUpdateCmdStatus.msgID;
+ SW_UPDATE_DESINTATION_T dest = (SW_UPDATE_DESINTATION_T)( SWUpdateCmdStatus.updateCmd >> SHIFT_BITS_TO_GET_TARGET ); // TODO add more logic for other stacks
+
+ // Calculate the CRC of the message and ack or nack based on the matching of the CRCs
+ calcCRC = crc32( calcCRC, (U08*)&SWUpdateCmdStatus, sizeof( SW_UPDATE_CMD_STATUS_T ) - sizeof( U32 ) );
+ hasCRCPassed = ( SWUpdateCmdStatus.msgCRC == calcCRC ? TRUE : FALSE );
+
+ // TODO remove
+ hasCRCPassed = TRUE;
+ // TODO remove
+
+ if ( TRUE == hasCRCPassed )
+ {
+ ackStatus = ACK;
+ SWUpdateCommandState = (SW_UPDATE_CMD_T)( SWUpdateCmdStatus.updateCmd & MASK_OFF_NIBBLE_MSB );
+
+ if ( UPDATE_FPGA == dest )
+ {
+ // If the update destination is FPGA, signal FPGA to prepare for the update.
+ signalFPGAToPrepareForUpdate();
+ }
+ }
+
+ // Send the result of the command received
+ prepareResponseMessage( msgID, ackStatus, &resp );
+ sendAckNackStatusFromFirmware( (U08*)&resp );
+ clearCommBuffer( mailBox );
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleIncomingUpdateMessage function handles the incoming update message
+ * from the CAN bus. Once the entire update message has been received, it then
+ * is sent to the corresponding destination that is under update.
+ * @details \b Inputs: SWUpdateRCVStatus
+ * @details \b Outputs: SWUpdateRCVStatus
+ * @param mailbox of the buffer that has been received
+ * @return none
+ *************************************************************************/
+static void handleIncomingUpdateMessage( SW_UPDATE_CAN_MAIL_BOX_T mailBox )
+{
+ // Peek into the comm buffer to see if the entire data has been received
+ S32 bytesInBuffer = getNumberOfBytesInBuffer( mailBox );
+
+ if ( bytesInBuffer == NUM_OF_CAN_BYTES_FOR_UPDATE )
+ {
+ SW_UPDATE_RESP_STATUS_T resp;
+ U08 bufferWithNoCRC[ SW_UPDATE_FLASH_BUFFER_SIZE + sizeof( U32 ) ];
+
+ BOOL status = FALSE;
+ U32 calcCRC = 0;
+ BOOL hasCRCPassed = FALSE;
+ ACK_NACK_STATUS_T ackNackStatus = NACK;
+
+ getCommBuffer( mailBox, (U08*)&SWUpdateRCVStatus, NUM_OF_CAN_BYTES_FOR_UPDATE );
+
+ // Create a local buffer and copy the header into the buffer excluding the CRC so only 4 bytes of ID, Destination, and payload length
+ memcpy( bufferWithNoCRC, (U08*)&SWUpdateRCVStatus, sizeof( U32 ) );
+ // Copy the entire update buffer that is going either to firmware or FPGA into the local buffer.
+ memcpy( &bufferWithNoCRC[ sizeof( U32 ) ], SWUpdateRCVStatus.SWUpdateBuffer, sizeof( SWUpdateRCVStatus.SWUpdateBuffer ) );
+ // Calculate the CRC of the local copied buffer and compare it against the message CRC
+ calcCRC = crc32( calcCRC, bufferWithNoCRC, sizeof( bufferWithNoCRC ) );
+ hasCRCPassed = ( SWUpdateRCVStatus.msgCRC == calcCRC ? TRUE : FALSE );
+
+ // TODO remove
+ hasCRCPassed = TRUE;
+ // TODO remove
+
+ if ( TRUE == hasCRCPassed )
+ {
+ // CRC passed, call the corresponding the handlers to update either FPGA or firmware
+ switch ( SWUpdateRCVStatus.updateDest )
+ {
+ case UPDATE_FIRMWARE:
+ ackNackStatus = handleFirmwareUpdate();
+ break;
+
+ case UPDATE_FPGA:
+ ackNackStatus = handleFPGAUpdate();
+ break;
+
+ default:
+ // Do nothing
+ break;
+ }
+ }
+
+ // TODo send nack if the CRC failed
+
+ //prepareResponseMessage( SWUpdateRCVStatus.msgID, ackNackStatus, &resp );
+ //status = sendAckNackStatusFromFirmware( (U08*)&resp ); // TODO do we have to retry if send failed?
+ clearCommBuffer( mailBox ); // TODo does this need to be here? How about resync?
+ //clearSWUpdateBuffer(); // TODO uncomment
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The prepareResponseMessage function prepares the message body that is
+ * used to respond to the updater app.
+ * @details \b Inputs: none
+ * @details \b Outputs: none
+ * @param message ID that is being responded for
+ * @param ack nack status
+ * @param response buffer which is the pointer to the buffer that is used
+ * to be sent to the app
+ * @return none
+ *************************************************************************/
+static void prepareResponseMessage( U08 respOfMsgID, ACK_NACK_STATUS_T ackNack, SW_UPDATE_RESP_STATUS_T* respBuffer )
+{
+ U32 calcCRC = 0;
+
+ respBuffer->msgID = respOfMsgID;
+ respBuffer->msgAckNackStatus = ackNack;
+ respBuffer->cyberRandom = 0;
+ respBuffer->msgCRC = crc32( calcCRC, (U08*)&respBuffer, sizeof( SW_UPDATE_RESP_STATUS_T ) - sizeof( U32 ) );
+}
+
+/*********************************************************************//**
+ * @brief
+ * The clearSWUpdateBuffer function clears the software update buffer.
+ * @details \b Inputs: none
+ * @details \b Outputs: SWUpdateRCVStatus
+ * @return none
+ *************************************************************************/
+static void clearSWUpdateBuffer( void )
+{
+ memset( &SWUpdateRCVStatus, 0x0, sizeof( SW_UPDATE_RCV_STATUS_T ) );
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleFirmwareUpdate function handles the firmware update data. This
+ * function checks that the message is not the final message and then signal
+ * the non-volatile memory to update the flash.
+ * @details \b Inputs: SWUpdateRCVStatus
+ * @details \b Outputs: none
+ * @return Ack if the write was successful otherwise, Nack
+ *************************************************************************/
+static ACK_NACK_STATUS_T handleFirmwareUpdate( void )
+{
+ SW_UPDATE_RESP_STATUS_T resp;
+
+ ACK_NACK_STATUS_T ackStatus = ACK;
+ BOOL status = FALSE;
+
+ if ( SWUpdateRCVStatus.updatePayloadLen != SW_UPDATE_FINAL_MSG_INDEX )
+ {
+ _disable_IRQ();
+ status = handleUpdatingFlash( SWUpdateRCVStatus.SWUpdateBuffer );
+ ackStatus = ( TRUE == status ? ACK : NACK );
+ _enable_IRQ();
+ }
+
+ prepareResponseMessage( SWUpdateRCVStatus.msgID, ackStatus, &resp );
+ status = sendAckNackStatusFromFirmware( (U08*)&resp ); // TODO do we have to retry if send failed?
+ clearCommBuffer( thisStackMailBox ); // TODo does this need to be here? How about resync?
+
+ return ackStatus;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleFPGAUpdate function handles the FPGA update data. This
+ * function checks that the message is not the final message and then signals
+ * the FPGA driver to update the FPGA.
+ * @details \b Inputs: SWUpdateRCVStatus
+ * @details \b Outputs: none
+ * @return Ack if the write was successful otherwise, Nack
+ *************************************************************************/
+static ACK_NACK_STATUS_T handleFPGAUpdate( void )
+{
+ ACK_NACK_STATUS_T ackStatus = NACK;
+
+ // TODO why the firmware handler is slightly different? Make them consistent.
+
+ if ( SWUpdateRCVStatus.updatePayloadLen != SW_UPDATE_FINAL_MSG_INDEX )
+ {
+ sizeToWrite = SWUpdateRCVStatus.updatePayloadLen;
+ REMOVETHEVAR += sizeToWrite;
+
+ signalFPGAToWriteToFlash( SWUpdateRCVStatus.SWUpdateBuffer, sizeToWrite );
+
+ if ( sizeToWrite < SW_UPDATE_FLASH_BUFFER_SIZE )
+ {
+ signalFPGAToSelfConfigure();
+ }
+ }
+ else
+ {
+ SW_UPDATE_RESP_STATUS_T resp;
+
+ prepareResponseMessage( SWUpdateRCVStatus.msgID, ACK, &resp );
+ sendAckNackStatusFromFirmware( (U08*)&resp );
+ }
+
+ return ackStatus;
+}
Index: firmware/App/Services/Download.h
===================================================================
diff -u
--- firmware/App/Services/Download.h (revision 0)
+++ firmware/App/Services/Download.h (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -0,0 +1,36 @@
+
+#ifndef __DOWNLOAD_H__
+#define __DOWNLOAD_H__
+
+#include "BLCommon.h"
+
+/**
+ * @defgroup Download Download
+ * @brief Download unit. Manages receiving bytes and passing it to the
+ * drivers to update.
+ *
+ * @addtogroup Download
+ * @{
+ */
+
+// ********** public definitions **********
+
+// ********** public function prototypes **********
+
+void initDownload( void );
+
+void execDownload( void );
+
+SW_UPDATE_CMD_T getSWUpdateCommandState( void );
+
+SW_UPDATE_DESINTATION_T getSWUpdateDestination( void );
+
+void clearSWUpdateCommandState( void );
+
+void sendFPGAAckNackStatus( ACK_NACK_STATUS_T ackNackStatus );
+
+U08 getTempRemoveMSGID(); // TODO remove or make is permanent
+
+/**@}*/
+
+#endif
Index: firmware/App/Services/FPGA.c
===================================================================
diff -u
--- firmware/App/Services/FPGA.c (revision 0)
+++ firmware/App/Services/FPGA.c (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -0,0 +1,1119 @@
+
+#include // For memcpy and memset
+
+#include "sci.h"
+#include "sys_dma.h"
+
+#include "Comm.h"
+#include "Download.h"
+#include "FPGA.h"
+#include "Timers.h"
+#include "SystemComm.h"
+#include "Utilities.h"
+
+/**
+ * @addtogroup FPGA
+ * @{
+ */
+
+// ********** private definitions **********
+
+#define QUEUE_MAX_SIZE 20 ///< Max queue size.
+#define FPGA_PAGE_SIZE 256 ///< FPGA register pages are 256 bytes.
+#define FPGA_MAX_READ_SIZE ( FPGA_PAGE_SIZE - 1 ) ///< FGPA max read size.
+#define FPGA_WRITE_CMD_BUFFER_LEN ( FPGA_PAGE_SIZE + 8 ) ///< FPGA write command buffer byte length.
+#define FPGA_READ_CMD_BUFFER_LEN 8 ///< FPGA read command buffer byte length.
+#define FPGA_WRITE_RSP_BUFFER_LEN 8 ///< FPGA write command response buffer byte length.
+#define FPGA_READ_RSP_BUFFER_LEN ( FPGA_PAGE_SIZE + 8 ) ///< FPGA read command response buffer byte length.
+
+#define SCI2_RECEIVE_DMA_REQUEST 28 ///< Serial port 2 receive DMA request line.
+#define SCI2_TRANSMIT_DMA_REQUEST 29 ///< Serial port 2 transmit DMA request line.
+
+#define FPGA_CRC_LEN 2 ///< FPGA CRC byte length.
+#define FPGA_WRITE_CMD_HDR_LEN 4 ///< FPGA write command header byte length.
+#define FPGA_WRITE_RSP_HDR_LEN 3 ///< FPGA write command response header byte length.
+
+#define FPGA_WRITE_CMD_CODE 0x55 ///< FPGA write command code.
+#define FPGA_WRITE_CMD_ACK 0xA5 ///< FPGA write command ACK code.
+#define FPGA_READ_CMD_CODE 0x5A ///< FPGA read command code.
+#define FPGA_READ_CMD_ACK 0xAA ///< FPGA read command ACK code.
+#define FPGA_HEADER_START_ADDR 0x0000 ///< Start address for FPGA header data.
+#define FPGA_BULK_READ_START_ADDR 0x0100 ///< Start address for FPGA continuous priority reads.
+#define FPGA_WRITE_START_ADDR 0x000B ///< Start address for FPGA continuous priority writes. // TODO does this vary?
+#define FPGA_FLASH_CONTROL_REG_ADDR 0x090E
+#define FPGA_FLASH_STATUS_REG_ADDR 0x0900 ///< FPGA flash status register address. // TODO remvoe
+#define FPGA_FIFO_COUNT_REG_ADDR 0x0902 ///< FPGA FIFO count register address. // TODO remvoe
+#define FPGA_FLASH_DATA_REG_ADDR 0x0A00 ///< FPGA flash data register address. // TODO remvoe
+#define FPGA_MULTI_BOOT_STATUS_ADDR 0x0900 ///< FPGA multi boot status register address.
+#define FPGA_ICAP2_REG_ADDR 0x0909 ///< FPGA ICAP 2 command register address.
+
+#define FPGA_UPDATE_REGISTER_ADDR ( FPGA_WRITE_START_ADDR + 4 ) ///< FPGA update register address.
+#define FPGA_READ_CMD_HDR_LEN 4 ///< FPGA read command header byte length.
+#define FPGA_READ_RSP_HDR_LEN 3 ///< FPGA read command response header byte length.
+#define FPGA_UPDATE_REQUEST_INDEX ( FPGA_READ_RSP_HDR_LEN + 1 ) ///< FPGA update request index. // TODO Get this value from Noe, make sure the index is the same in all of the stacks
+#define FPGA_FLASH_STATUS_INDEX ( FPGA_READ_RSP_HDR_LEN + 1 ) ///< FPGA flash status index.
+#define FPGA_FIFO_COUNT_INDEX ( FPGA_READ_RSP_HDR_LEN + 1 ) ///< FPGA FIFO count index.
+
+#define UPDATE_REQUESTED_VALUE 1 ///< The value that indicates and update has been requested.
+
+#define FPGA_FIFO_SIZE_BYTES 1024 ///< FPGA FIFO size in bytes.
+#define FPGA_FIFO_COUNT_MASK 0x03FF ///< FPGA FIFO count in FIFO mask.
+
+#define FPGA_ERASE_FIFO_CMD_OK ( 1 << 11 ) ///< FPGA erase FIFO command status ok value.
+#define FPGA_FLASH_STATUS_OK ( 1 << 15 ) ///< FPGA flash status status ok value.
+
+#define FPGA_PRE_SELF_CONFIG_TIMEOUT_MS 10000 ///< FPGA pre self configure timeout in milliseconds.
+
+/// FPGA communication status enumeration
+typedef enum
+{
+ FPGA_COMM_IDLE = 0, ///< FPGA communication idle.
+ FPGA_COMM_READ_IN_PROGRESS, ///< FPGA communication read in progress.
+ FPGA_COMM_READ_RESP_RECEIVED, ///< FPGA communication read response received.
+ FPGA_COMM_WRITE_IN_PROGRESS, ///< FPGA communication write in progress.
+ FPGA_COMM_WRITE_RESP_RECEIVED, ///< FPGA communication write response received.
+ NUM_OF_FPGA_COMM_STATUS ///< Number of FPGA communication status.
+} FPGA_COMM_STATE_T;
+
+/// FPGA queue jobs enumeration
+typedef enum
+{
+ FPGA_READ_HEADER = 0, ///< FPGA read header.
+ FPGA_READ_UPDATE_REG, ///< FPGA read update request register.
+ FPGA_WRITE_UPDATE_REG, ///< FPGA write to update request register.
+ FPGA_RESET_FLASH, ///< FPGA reset flash.
+ FPGA_ERASE_FIFO, ///< FPGA erase FIFO.
+ FPGA_ENABLE_FLASH, ///< FPGA enable flash.
+ FPGA_READ_MULTI_BOOT_STATUS, ///< FPGA read multi-boot status.
+ FPGA_FLASH_WRITE_DATA, ///< FPGA write flash data.
+ FPGA_SELF_CONFIGURE, ///< FPGA self configure.
+ NUM_OF_FPGA_JOBS, ///< Number of the FPGA jobs.
+} FPGA_JOBS_T;
+
+/// FPGA state machine states enumeration
+typedef enum
+{
+ FPGA_IDLE_STATE = 0, ///< FPGA idle state.
+ FPGA_WRITE_TO_FPGA_STATE, ///< FPGA write to FPGA state.
+ FPGA_RCV_WRITE_RESP_FROM_FPGA_STATE, ///< FPGA receive write response from FPGA state.
+ FPGA_READ_FROM_FPGA_STATE, ///< FPGA read from FPGA state.
+ FPGA_RCV_READ_RESP_FROM_FPGA_STATE, ///< FPGA received read response from FPGA state.
+ NUM_OF_FPGA_STATES ///< Number of FPGA states.
+} FPGA_STATE_T;
+
+#pragma pack(push,1)
+/// FPGA queue job specification structure
+typedef struct
+{
+ U16 fpgaJobAddress; ///< FPGA job address.
+ U16 fpgaJobSize; ///< FPGA job size.
+ U08* fpgaWriteStartAddress; ///< FPGA write buffer start address.
+ U08 fpgaIsJobWrite; ///< FPGA boolean flag to indicate this is a write job or not.
+} FPGA_JOB_SPECS_T;
+
+/// FPGA jobs queue status structure
+typedef struct
+{
+ U08 fpgaJobsQueue[ QUEUE_MAX_SIZE ]; ///< FPGA jobs queue.
+ U08 fpgaJobRearIndex; ///< FPGA job queue rear index.
+ U08 fpgaJobFrontIndex; ///< FPGA job queue front index.
+ U08 fpgaJobsQueueCount; ///< FPGA job queue count.
+ U08 fpgaCurrentJob; ///< FPGA queue current job.
+ FPGA_COMM_STATE_T fpgaCommRead; ///< FPGA DMA read command state.
+ FPGA_COMM_STATE_T fpgaCommWrite; ///< FPGA DMA write command state.
+} FPGA_JOBS_Q_STATUS_T;
+
+/// FPGA flash status structure
+typedef struct
+{
+ BOOL hasUpdateRegsBeenRqstd; ///< Flag to indicate whether update registers request has been requested.
+ U16 fifoRemainingCount; ///< FIFO empty space remaining count.
+ BOOL isFIFOEraseOk; ///< Flag to indicate whether FIFO has been erased or not.
+ BOOL isFlashStatusOk; ///< Flag to indicate whether flash status is okay or not.
+ BOOL isFPGAFlashComplete; ///< Flag to indicate whether flash update has been completed.
+ U16 flashStatusBits; ///< Flash status.
+ U32 preSelfConfigureStartTimeMS; ///< Pre self configure start time in milliseconds.
+ U32 startTime; ///< Start time in milliseconds.
+} FPGA_FLASH_STATUS_T;
+
+/// Record structure for FPGA header read.
+typedef struct
+{
+ U08 fpgaId; ///< Reg 0. FPGA ID code. Checked against expected value at power up to verify basic FPGA communication and operation.
+ U08 fpgaRev; ///< Reg 1. FPGA revision (minor) being reported.
+ U08 fpgaRevMajor; ///< Reg 2. FPGA revision (major) being reported.
+ U08 fpgaRevLab; ///< Reg 3. FPGA revision (lab) being reported.
+} FPGA_HEADER_T; // Read only on FPGA
+#pragma pack(pop)
+
+// ********** private data **********
+
+// FPGA comm buffers
+static U08 fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_BUFFER_LEN ]; ///< FPGA write command buffer. Holds the next FPGA write command to be transmitted.
+static U08 fpgaReadCmdBuffer[ FPGA_READ_CMD_BUFFER_LEN ]; ///< FPGA read command buffer. Holds the next FPGA read command to be transmitted.
+static U08 fpgaWriteResponseBuffer[ FPGA_WRITE_RSP_BUFFER_LEN ]; ///< FPGA write command response buffer. Memory reserved to capture the response to the last FPGA write command.
+static U08 fpgaReadResponseBuffer[ FPGA_READ_RSP_BUFFER_LEN ]; ///< FPGA read command response buffer. Memory reserved to capture the response to the last FPGA read command.
+
+// DMA control records
+static g_dmaCTRL fpgaDMAWriteControlRecord; ///< DMA record for controlling a DMA write command transmission from buffer.
+static g_dmaCTRL fpgaDMAWriteRespControlRecord; ///< DMA record for controlling a DMA write command reception to buffer.
+static g_dmaCTRL fpgaDMAReadControlRecord; ///< DMA record for controlling a DMA read command transmission from buffer.
+static g_dmaCTRL fpgaDMAReadRespControlRecord; ///< DMA record for controlling a DMA read command reception to buffer.
+
+static FPGA_HEADER_T fpgaHeader; ///< Record of last received FPGA header data.
+static FPGA_STATE_T fpgaState; ///< FPGA current state.
+static U08 fpgaUpdateRegisterStatus; ///< FPGA update register status.
+static FPGA_JOBS_Q_STATUS_T fpgaJobsQStatus; ///< FPGA jobs queue status.
+static FPGA_FLASH_STATUS_T fpgaFlashStatus; ///< FPGA flash status.
+static U08 fpgaDataToWriteBuffer[ SW_UPDATE_FLASH_BUFFER_SIZE ]; ///< FPGA data to write to FPGA flash buffer.
+static U32 fpgaDataLenToWrite; ///< FPGA data length to write to FPGA.
+
+static U32 TESTREMOVE = 0; // TODO remove
+static U32 countRemove = 0; // TODO remove
+static U08 tempACkStatus = 0; // TODO remove
+
+/// FPGA stack ID for TD, DD, RO.
+static const U08 STACK_FPGA_ID[ NUM_OF_FW_STACKS ] = { 0x5A, 0x61, 0xFF }; // TODO update with the real FPGA IDs
+// TODO what is this value? 0?
+static const U16 DISABLE_UPDATE_REG_CMD = 5; ///< FPGA disable update register command.
+static const U08 FPGA_RESET_FLASH_CMD = 0x01; ///< FPGA reset flash command.
+static const U08 FPGA_ERASE_FIFO_CMD = 0x08; ///< FPGA erase FIFO command.
+static const U08 FPGA_ENABLE_FLASH_CMD = 0x00; ///< FPGA enable flash command.
+static const U08 FPGA_SELF_CONFIG_CMD = 0x03; ///< FPGA self configure command.
+
+/// FPGA jobs specifications.
+static const FPGA_JOB_SPECS_T JOBS_SPECS[ NUM_OF_FPGA_JOBS ] = {
+ { FPGA_HEADER_START_ADDR, sizeof( FPGA_HEADER_T ), 0, FALSE }, // FPGA_READ_HEADER
+ { FPGA_BULK_READ_START_ADDR, FPGA_MAX_READ_SIZE, 0, FALSE }, // FPGA_READ_UPDATE_REG
+ { FPGA_UPDATE_REGISTER_ADDR, sizeof( U16 ), (U08*)&DISABLE_UPDATE_REG_CMD, TRUE }, // FPGA_WRITE_UPDATE_REG
+ { FPGA_FLASH_CONTROL_REG_ADDR, sizeof( U08 ), (U08*)&FPGA_RESET_FLASH_CMD, TRUE }, // FPGA_RESET_FLASH
+ { FPGA_FLASH_CONTROL_REG_ADDR, sizeof( U08 ), (U08*)&FPGA_ERASE_FIFO_CMD, TRUE }, // FPGA_ERASE_FIFO
+ { FPGA_FLASH_CONTROL_REG_ADDR, sizeof( U08 ), (U08*)&FPGA_ENABLE_FLASH_CMD, TRUE }, // FPGA_ENABLE_FLASH
+ { FPGA_MULTI_BOOT_STATUS_ADDR, sizeof( U32 ), 0, FALSE }, // FPGA_READ_MULTI_BOOT_STATUS
+ { FPGA_FLASH_DATA_REG_ADDR, SW_UPDATE_FLASH_BUFFER_SIZE, fpgaDataToWriteBuffer, TRUE }, // FPGA_FLASH_WRITE_DATA
+ { FPGA_ICAP2_REG_ADDR, sizeof( U08 ), (U08*)&FPGA_SELF_CONFIG_CMD, TRUE } // FPGA_SELF_CONFIGURE
+};
+
+// ********** private function prototypes **********
+
+static void initDMA( void );
+static void consumeUnexpectedData( void );
+static void requestFlashRegistersStatus( void );
+static void processFPGAFlashRegistersRead( void );
+
+static void setupDMAForReadResp( U32 bytes2Receive );
+static void setupDMAForReadCmd( U32 bytes2Transmit );
+static void startDMAReceiptOfReadResp( void );
+static void startDMAReadCmd( void );
+static void setupDMAForWriteCmd( U32 bytes2Transmit );
+static void startDMAWriteCmd( void );
+static void setupDMAForWriteResp( U32 bytes2Receive );
+static void startDMAReceiptOfWriteResp( void );
+
+static void resetFPGACommFlags( void );
+static void enqueue( FPGA_JOBS_T job );
+static void dequeue( void );
+static FPGA_JOBS_T peekFromQueue( void );
+static BOOL isQueueFull( void );
+
+static FPGA_STATE_T handleFPGAIdleState( void );
+
+static FPGA_STATE_T handleFPGAWriteToFPGAState( void );
+static FPGA_STATE_T handleFPGAReceiveWriteRespFromFPGAState( void );
+
+static FPGA_STATE_T handleFPGAReadFromFPGAState( void );
+static FPGA_STATE_T handleFPGAReceiveReadRespFromFPGAState( void );
+
+/*********************************************************************//**
+ * @brief
+ * The initFPGA function initializes the FPGA unit.
+ * @details \b Inputs: none
+ * @details \b Outputs: FPGA unit initialized.
+ * @return none
+ *************************************************************************/
+void initFPGA( void )
+{
+ memset( &fpgaHeader, 0x0, sizeof( FPGA_HEADER_T ) );
+ memset( &fpgaJobsQStatus, 0x0, sizeof( FPGA_JOBS_Q_STATUS_T ) );
+ memset( &fpgaFlashStatus, 0x0, sizeof( FPGA_FLASH_STATUS_T ) );
+
+ initDMA();
+ consumeUnexpectedData();
+
+ enqueue( FPGA_READ_HEADER );
+ enqueue( FPGA_READ_UPDATE_REG );
+
+ fpgaState = FPGA_IDLE_STATE;
+ fpgaUpdateRegisterStatus = 0;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The execFPGA function the FPGA state machine.
+ * @details \b Inputs: fpgaState
+ * @details \b Outputs: fpgaState
+ * @return none
+ *************************************************************************/
+void execFPGA( void )
+{
+ if ( TRUE == fpgaFlashStatus.hasUpdateRegsBeenRqstd )
+ {
+ processFPGAFlashRegistersRead();
+ }
+
+ // TODO test code remove
+ //U08 data[8];
+ //data[0] = getTempRemoveMSGID();
+ //data[1] = (U08)fpgaState;
+ //data[2] = GET_LSB_OF_WORD( fpgaFlashStatus.fifoRemainingCount );
+ //data[3] = GET_MSB_OF_WORD( fpgaFlashStatus.fifoRemainingCount );
+ //data[4] = GET_LSB_OF_WORD( fpgaFlashStatus.flashStatusBits );
+ //data[5] = GET_MSB_OF_WORD( fpgaFlashStatus.flashStatusBits );
+ //data[6] = tempACkStatus;
+ //data[7] = (U08)fpgaFlashStatus.isFlashStatusOk;
+ //broadcastDataTestRemove(data);
+ // TODO test code remove
+
+ switch( fpgaState )
+ {
+ case FPGA_IDLE_STATE:
+ fpgaState = handleFPGAIdleState();
+ break;
+
+ case FPGA_WRITE_TO_FPGA_STATE:
+ fpgaState = handleFPGAWriteToFPGAState();
+ break;
+
+ case FPGA_RCV_WRITE_RESP_FROM_FPGA_STATE:
+ fpgaState = handleFPGAReceiveWriteRespFromFPGAState();
+ break;
+
+ case FPGA_READ_FROM_FPGA_STATE:
+ fpgaState = handleFPGAReadFromFPGAState();
+ break;
+
+ case FPGA_RCV_READ_RESP_FROM_FPGA_STATE:
+ fpgaState = handleFPGAReceiveReadRespFromFPGAState();
+ break;
+
+ default:
+ // Do nothing
+ break;
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The signalFPGAReceiptCompleted function increments a counter to indicate
+ * that another DMA receipt from the FPGA has completed and sets comm flags
+ * indicating pending response from FPGA is completed.
+ * @details \b Inputs: fpgaJobsQStatus
+ * @details \b Outputs: fpgaJobsQStatus
+ * @return none
+ *************************************************************************/
+void signalFPGAReceiptCompleted( void )
+{
+ if ( FPGA_COMM_WRITE_IN_PROGRESS == fpgaJobsQStatus.fpgaCommWrite )
+ {
+ fpgaJobsQStatus.fpgaCommWrite = FPGA_COMM_WRITE_RESP_RECEIVED;
+ requestFlashRegistersStatus();
+ }
+ else if ( FPGA_COMM_READ_IN_PROGRESS == fpgaJobsQStatus.fpgaCommRead )
+ {
+ fpgaJobsQStatus.fpgaCommRead = FPGA_COMM_READ_RESP_RECEIVED;
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The hasUpdateBeenRequested function checks whether an update has been
+ * requested through the FPGA read registers.
+ * @details \b Inputs: fpgaState, fpgaUpdateRegisterStatus
+ * @details \b Outputs: fpgaUpdateRegisterStatus
+ * @return TRUE if an update has been requested otherwise, FALSE
+ *************************************************************************/
+BOOL hasUpdateBeenRequested( void )
+{
+ BOOL status = FALSE;
+
+ if ( ( FPGA_IDLE_STATE == fpgaState ) && ( UPDATE_REQUESTED_VALUE == fpgaUpdateRegisterStatus ) )
+ {
+ status = TRUE;
+ fpgaUpdateRegisterStatus = 0;
+ enqueue( FPGA_WRITE_UPDATE_REG );
+ }
+
+ return status;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The isFPGAIDValid function checks whether the FPGA header is valid.
+ * @details \b Inputs: fpgaHeader
+ * @details \b Outputs: none
+ * @return TRUE if the FPGA header is valid otherwise, FALSE
+ *************************************************************************/
+BOOL isFPGAIDValid( void )
+{
+ BOOL status = ( STACK_FPGA_ID[ BL_STACK_ID ] == fpgaHeader.fpgaId ? TRUE : FALSE );
+
+ return status;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The isFPGAFlashComplete function returns the status of FPGA flash. So
+ * TRUE if the flash is complete, otherwise, FALSE.
+ * @details \b Inputs: fpgaFlashStatus
+ * @details \b Outputs: none
+ * @return TRUE if flash is complete otherwise, FALSE
+ *************************************************************************/
+BOOL isFPGAFlashComplete( void )
+{
+ return fpgaFlashStatus.isFPGAFlashComplete;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The signalFPGAToPrepareForUpdate function enqueues the FPGA update
+ * initialization jobs if the queue is not full.
+ * @details \b Inputs: none
+ * @details \b Outputs: none
+ * @return none
+ *************************************************************************/
+void signalFPGAToPrepareForUpdate( void )
+{
+ if ( FALSE == isQueueFull() )
+ {
+ enqueue( FPGA_RESET_FLASH );
+ enqueue( FPGA_ERASE_FIFO );
+ enqueue( FPGA_ENABLE_FLASH );
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The signalFPGAToWriteToFlash function enqueues the FPGA write to flash
+ * job if the queue is not full.
+ * @details \b Inputs: none
+ * @details \b Outputs: fpgaDataLenToWrite, fpgaDataToWriteBuffer
+ * @return none
+ *************************************************************************/
+void signalFPGAToWriteToFlash( U08* data, U32 len )
+{
+ if ( FALSE == isQueueFull() )
+ {
+ memset( fpgaDataToWriteBuffer, 0x0, SW_UPDATE_FLASH_BUFFER_SIZE );
+
+ fpgaDataLenToWrite = len;
+ memcpy( fpgaDataToWriteBuffer, data, len );
+
+ enqueue( FPGA_FLASH_WRITE_DATA );
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The signalFPGAToSelfConfigure function enqueues the FPGA self configure
+ * job if the queue is not full.
+ * @details \b Inputs: none
+ * @details \b Outputs: fpgaFlashStatus
+ * @return none
+ *************************************************************************/
+void signalFPGAToSelfConfigure( void )
+{
+ if ( FALSE == isQueueFull() )
+ {
+ fpgaFlashStatus.preSelfConfigureStartTimeMS = getMSTimerCount();
+
+ enqueue( FPGA_SELF_CONFIGURE );
+ }
+}
+
+// ********** private functions **********
+
+/*********************************************************************//**
+ * @brief
+ * The initDMA function initializes the DMA communication.
+ * @details \b Inputs: none
+ * @details \b Outputs: FPGA DMA unit initialized.
+ * @return none
+ *************************************************************************/
+static void initDMA( void )
+{
+ // Enable interrupt notifications for FPGA serial port
+ sciEnableNotification( scilinREG, SCI_OE_INT | SCI_FE_INT );
+
+ // Assign DMA channels to h/w DMA requests
+ dmaReqAssign( DMA_CH0, SCI2_RECEIVE_DMA_REQUEST );
+ dmaReqAssign( DMA_CH2, SCI2_TRANSMIT_DMA_REQUEST );
+
+ // Set DMA channel priorities
+ dmaSetPriority( DMA_CH0, HIGHPRIORITY );
+ dmaSetPriority( DMA_CH2, LOWPRIORITY );
+
+ // Enable DMA block transfer complete interrupts
+ dmaEnableInterrupt( DMA_CH0, BTC );
+ dmaEnableInterrupt( DMA_CH2, BTC );
+
+ // Initialize FPGA DMA Write Control Record
+ fpgaDMAWriteControlRecord.PORTASGN = 4; // Port B (only choice per datasheet)
+ fpgaDMAWriteControlRecord.SADD = (U32)fpgaWriteCmdBuffer; // Transfer source address
+ fpgaDMAWriteControlRecord.DADD = (U32)(&(scilinREG->TD)); // Dest. is SCI2 xmit register
+ fpgaDMAWriteControlRecord.CHCTRL = 0; // No chaining
+ fpgaDMAWriteControlRecord.ELCNT = 1; // Frame is 1 element
+ fpgaDMAWriteControlRecord.FRCNT = 0; // Block is TBD frames - will be populated later when known
+ fpgaDMAWriteControlRecord.RDSIZE = ACCESS_8_BIT; // Element size is 1 byte
+ fpgaDMAWriteControlRecord.WRSIZE = ACCESS_8_BIT; //
+ fpgaDMAWriteControlRecord.TTYPE = FRAME_TRANSFER; // Transfer type is block transfer
+ fpgaDMAWriteControlRecord.ADDMODERD = ADDR_INC1; // Source addressing mode is post-increment
+ fpgaDMAWriteControlRecord.ADDMODEWR = ADDR_FIXED; // Dest. addressing mode is fixed
+ fpgaDMAWriteControlRecord.AUTOINIT = AUTOINIT_OFF; // Auto-init off
+ fpgaDMAWriteControlRecord.ELSOFFSET = 0; // Not used
+ fpgaDMAWriteControlRecord.ELDOFFSET = 0; // Not used
+ fpgaDMAWriteControlRecord.FRSOFFSET = 0; // Not used
+ fpgaDMAWriteControlRecord.FRDOFFSET = 0; // Not used
+
+ // Initialize FPGA DMA Write Response Control Record
+ fpgaDMAWriteRespControlRecord.PORTASGN = 4; // Port B (only choice per datasheet)
+ fpgaDMAWriteRespControlRecord.SADD = (U32)(&(scilinREG->RD)); // Source is SCI2 recv register
+ fpgaDMAWriteRespControlRecord.DADD = (U32)fpgaWriteResponseBuffer; // Transfer destination address
+ fpgaDMAWriteRespControlRecord.CHCTRL = 0; // No chaining
+ fpgaDMAWriteRespControlRecord.ELCNT = 1; // Frame is 1 element
+ fpgaDMAWriteRespControlRecord.FRCNT = 0; // Block is TBD frames - will be populated later when known
+ fpgaDMAWriteRespControlRecord.RDSIZE = ACCESS_8_BIT; // Element size is 1 byte
+ fpgaDMAWriteRespControlRecord.WRSIZE = ACCESS_8_BIT; //
+ fpgaDMAWriteRespControlRecord.TTYPE = FRAME_TRANSFER; // Transfer type is block transfer
+ fpgaDMAWriteRespControlRecord.ADDMODERD = ADDR_FIXED; // Source addressing mode is fixed
+ fpgaDMAWriteRespControlRecord.ADDMODEWR = ADDR_INC1; // Dest. addressing mode is post-increment
+ fpgaDMAWriteRespControlRecord.AUTOINIT = AUTOINIT_OFF; // Auto-init off
+ fpgaDMAWriteRespControlRecord.ELDOFFSET = 0; // Not used
+ fpgaDMAWriteRespControlRecord.ELSOFFSET = 0; // Not used
+ fpgaDMAWriteRespControlRecord.FRDOFFSET = 0; // Not used
+ fpgaDMAWriteRespControlRecord.FRSOFFSET = 0; // Not used
+
+ // Initialize FPGA DMA Read Control Record
+ fpgaDMAReadControlRecord.PORTASGN = 4; // Port B (only choice per datasheet)
+ fpgaDMAReadControlRecord.SADD = (U32)fpgaReadCmdBuffer; // Transfer source address
+ fpgaDMAReadControlRecord.DADD = (U32)(&(scilinREG->TD)); // Dest. is SCI2 xmit register
+ fpgaDMAReadControlRecord.CHCTRL = 0; // No chaining
+ fpgaDMAReadControlRecord.ELCNT = 1; // Frame is 1 element
+ fpgaDMAReadControlRecord.FRCNT = 0; // Block is TBD frames - will be populated later when known
+ fpgaDMAReadControlRecord.RDSIZE = ACCESS_8_BIT; // Element size is 1 byte
+ fpgaDMAReadControlRecord.WRSIZE = ACCESS_8_BIT; //
+ fpgaDMAReadControlRecord.TTYPE = FRAME_TRANSFER; // Transfer type is block transfer
+ fpgaDMAReadControlRecord.ADDMODERD = ADDR_INC1; // Source addressing mode is post-increment
+ fpgaDMAReadControlRecord.ADDMODEWR = ADDR_FIXED; // Dest. addressing mode is fixed
+ fpgaDMAReadControlRecord.AUTOINIT = AUTOINIT_OFF; // Auto-init off
+ fpgaDMAReadControlRecord.ELSOFFSET = 0; // Not used
+ fpgaDMAReadControlRecord.ELDOFFSET = 0; // Not used
+ fpgaDMAReadControlRecord.FRSOFFSET = 0; // Not used
+ fpgaDMAReadControlRecord.FRDOFFSET = 0; // Not used
+
+ // Initialize FPGA DMA Read Response Control Record
+ fpgaDMAReadRespControlRecord.PORTASGN = 4; // Port B (only choice per datasheet)
+ fpgaDMAReadRespControlRecord.SADD = (U32)(&(scilinREG->RD)); // Source is SCI2 recv register
+ fpgaDMAReadRespControlRecord.DADD = (U32)fpgaReadResponseBuffer; // Transfer destination address
+ fpgaDMAReadRespControlRecord.CHCTRL = 0; // No chaining
+ fpgaDMAReadRespControlRecord.ELCNT = 1; // Frame is 1 element
+ fpgaDMAReadRespControlRecord.FRCNT = 0; // Block is TBD frames - will be populated later when known
+ fpgaDMAReadRespControlRecord.RDSIZE = ACCESS_8_BIT; // Element size is 1 byte
+ fpgaDMAReadRespControlRecord.WRSIZE = ACCESS_8_BIT; //
+ fpgaDMAReadRespControlRecord.TTYPE = FRAME_TRANSFER; // Transfer type is block transfer
+ fpgaDMAReadRespControlRecord.ADDMODERD = ADDR_FIXED; // Source addressing mode is fixed
+ fpgaDMAReadRespControlRecord.ADDMODEWR = ADDR_INC1; // Dest. addressing mode is post-increment
+ fpgaDMAReadRespControlRecord.AUTOINIT = AUTOINIT_OFF; // Auto-init off
+ fpgaDMAReadRespControlRecord.ELDOFFSET = 0; // Not used
+ fpgaDMAReadRespControlRecord.ELSOFFSET = 0; // Not used
+ fpgaDMAReadRespControlRecord.FRDOFFSET = 0; // Not used
+ fpgaDMAReadRespControlRecord.FRSOFFSET = 0; // Not used
+}
+
+/*********************************************************************//**
+ * @brief
+ * The consumeUnexpectedData function checks to see if a byte is sitting in
+ * the SCI2 received data register and consumes the byte if found.
+ * @details \b Inputs: SCI FLR register
+ * @details \b Outputs: SCI errors cleared, unexpected byte consumed
+ * @return none
+ *************************************************************************/
+static void consumeUnexpectedData( void )
+{
+ // Clear any errors
+ sciRxError( scilinREG );
+
+ // If a byte is pending read, read it
+ if ( sciIsRxReady( scilinREG ) != 0 )
+ {
+ sciReceiveByte( scilinREG );
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The requestFlashRegistersStatus function requests the FPGA flash readings
+ * status.
+ * @details \b Inputs: none
+ * @details \b Outputs: fpgaReadCmdBuffer[], fpgaJobsQStatus, fpgaFlashStatus
+ * @return none
+ *************************************************************************/
+static void requestFlashRegistersStatus( void )
+{
+ U16 jobAddress = JOBS_SPECS[ FPGA_READ_MULTI_BOOT_STATUS ].fpgaJobAddress;
+ U08 jobSize = JOBS_SPECS[ FPGA_READ_MULTI_BOOT_STATUS ].fpgaJobSize;
+ U16 crc = 0;
+
+ // Construct read command to read 3 registers starting at address 0
+ fpgaReadCmdBuffer[ 0 ] = FPGA_READ_CMD_CODE;
+ fpgaReadCmdBuffer[ 1 ] = GET_LSB_OF_WORD( jobAddress );
+ fpgaReadCmdBuffer[ 2 ] = GET_MSB_OF_WORD( jobAddress );
+ fpgaReadCmdBuffer[ 3 ] = jobSize;
+ crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN );
+ fpgaReadCmdBuffer[ 4 ] = GET_MSB_OF_WORD( crc );
+ fpgaReadCmdBuffer[ 5 ] = GET_LSB_OF_WORD( crc );
+
+ // Prep DMA for sending the read cmd and receiving the response
+ fpgaJobsQStatus.fpgaCommRead = FPGA_COMM_READ_IN_PROGRESS;
+ fpgaFlashStatus.hasUpdateRegsBeenRqstd = TRUE;
+
+ setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + jobSize + sizeof( U16 ) );
+ setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + sizeof( U16 ) );
+ startDMAReceiptOfReadResp();
+ startDMAReadCmd();
+}
+
+/*********************************************************************//**
+ * @brief
+ * The processFPGAFlashRegistersRead function processes the read flash readings.
+ * @details \b Inputs: fpgaReadResponseBuffer[]
+ * @details \b Outputs: fpgaFlashStatus
+ * @return none
+ *************************************************************************/
+static void processFPGAFlashRegistersRead( void )
+{
+ if ( FPGA_READ_CMD_ACK == fpgaReadResponseBuffer[ 0 ] )
+ {
+ U32 rspSize = FPGA_READ_RSP_HDR_LEN + JOBS_SPECS[ fpgaJobsQStatus.fpgaCurrentJob ].fpgaJobSize;
+ U32 crcPos = rspSize;
+ U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ crcPos ], fpgaReadResponseBuffer[ crcPos + 1 ] );
+
+ // Does the FPGA response CRC check out?
+ if ( crc == crc16( fpgaReadResponseBuffer, rspSize ) )
+ {
+ U16 flashStatus = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ FPGA_FLASH_STATUS_INDEX ], fpgaReadResponseBuffer[ FPGA_FLASH_STATUS_INDEX - 1 ] );
+ U16 fifoStatus = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ FPGA_FLASH_STATUS_INDEX + sizeof( U16 ) ],
+ fpgaReadResponseBuffer[ FPGA_FLASH_STATUS_INDEX + sizeof( U16 ) - 1 ] );
+
+ fpgaFlashStatus.fifoRemainingCount = FPGA_FIFO_SIZE_BYTES - ( FPGA_FIFO_COUNT_MASK & fifoStatus );
+ fpgaFlashStatus.hasUpdateRegsBeenRqstd = FALSE;
+ fpgaFlashStatus.flashStatusBits = flashStatus;
+ fpgaFlashStatus.isFlashStatusOk = FALSE;
+
+ if ( ( flashStatus & FPGA_ERASE_FIFO_CMD_OK ) == FPGA_ERASE_FIFO_CMD_OK )
+ {
+ fpgaFlashStatus.isFIFOEraseOk = TRUE;
+ }
+
+ if ( ( flashStatus & FPGA_FLASH_STATUS_OK ) == FPGA_FLASH_STATUS_OK )
+ {
+ fpgaFlashStatus.isFlashStatusOk = TRUE;
+ }
+ }
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The setupDMAForReadResp function sets the expected byte count for the
+ * next DMA read command response from the FPGA.
+ * @details \b Inputs: none
+ * @details \b Outputs: fpgaDMAReadRespControlRecord
+ * @param bytes2Receive number of expected bytes to be transmitted via
+ * DMA from the FPGA
+ * @return none
+ *************************************************************************/
+static void setupDMAForReadResp( U32 bytes2Receive )
+{
+ // Verify # of bytes does not exceed buffer length
+ if ( bytes2Receive <= FPGA_READ_RSP_BUFFER_LEN )
+ {
+ fpgaDMAReadRespControlRecord.FRCNT = bytes2Receive;
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The setupDMAForReadCmd function sets the byte count for the next DMA
+ * read command to the FPGA.
+ * @details \b Inputs: none
+ * @details \b Outputs: fpgaDMAReadControlRecord
+ * @param bytes2Transmit number of bytes to be transmitted via DMA to the FPGA
+ * @return none
+ *************************************************************************/
+static void setupDMAForReadCmd( U32 bytes2Transmit )
+{
+ // Verify # of bytes does not exceed buffer length
+ if ( bytes2Transmit <= FPGA_READ_CMD_BUFFER_LEN )
+ {
+ fpgaDMAReadControlRecord.FRCNT = bytes2Transmit;
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The startDMAReceiptOfReadResp function initiates readiness of the DMA
+ * receiver for the next DMA read command response from the FPGA.
+ * @details \b Inputs: fpgaDMAReadRespControlRecord
+ * @details \b Outputs: DMA read command response is ready to be received
+ * from the FPGA
+ * @return none
+ *************************************************************************/
+static void startDMAReceiptOfReadResp( void )
+{
+ dmaSetCtrlPacket( DMA_CH0, fpgaDMAReadRespControlRecord );
+ dmaSetChEnable( DMA_CH0, DMA_HW );
+ setSCI2DMAReceiveInterrupt();
+}
+
+/*********************************************************************//**
+ * @brief
+ * The startDMAReadCmd function initiates the DMA transmit for the next
+ * DMA read command to the FPGA.
+ * @details \b Inputs: fpgaDMAReadControlRecord
+ * @details \b Outputs: DMA read command to FPGA is initiated
+ * @return none
+ *************************************************************************/
+static void startDMAReadCmd( void )
+{
+ dmaSetCtrlPacket( DMA_CH2, fpgaDMAReadControlRecord );
+ dmaSetChEnable( DMA_CH2, DMA_HW );
+ setSCI2DMATransmitInterrupt();
+}
+
+/*********************************************************************//**
+ * @brief
+ * The setupDMAForWriteCmd function sets the byte count for the next DMA
+ * write command to the FPGA.
+ * @details Inputs: none
+ * @details Outputs: number of bytes for next FPGA write command is set
+ * @param bytes2Transmit number of bytes to be transmitted via DMA to the FPGA
+ * @return none
+ *************************************************************************/
+static void setupDMAForWriteCmd( U32 bytes2Transmit )
+{
+ // Verify # of bytes does not exceed buffer length
+ if ( bytes2Transmit <= FPGA_WRITE_CMD_BUFFER_LEN )
+ {
+ fpgaDMAWriteControlRecord.FRCNT = bytes2Transmit;
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The startDMAWriteCmd function initiates the DMA transmit for the next
+ * DMA write command to the FPGA.
+ * @details Inputs: none
+ * @details Outputs: DMA write command to FPGA is initiated
+ * @return none
+ *************************************************************************/
+static void startDMAWriteCmd( void )
+{
+ dmaSetCtrlPacket( DMA_CH2, fpgaDMAWriteControlRecord );
+ dmaSetChEnable( DMA_CH2, DMA_HW );
+ setSCI2DMATransmitInterrupt();
+}
+
+/*********************************************************************//**
+ * @brief
+ * The setupDMAForWriteResp function sets the expected byte count for the
+ * next DMA write command response from the FPGA.
+ * @details Inputs: none
+ * @details Outputs: number of expected bytes for next FPGA write command response is set
+ * @param bytes2Receive number of bytes expected to be transmitted via DMA from the FPGA
+ * @return none
+ *************************************************************************/
+static void setupDMAForWriteResp( U32 bytes2Receive )
+{
+ // Verify # of bytes does not exceed buffer length
+ if ( bytes2Receive <= FPGA_WRITE_RSP_BUFFER_LEN )
+ {
+ fpgaDMAWriteRespControlRecord.FRCNT = bytes2Receive;
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The startDMAReceiptOfWriteResp function initiates readiness of the DMA
+ * receiver for the next DMA write command response from the FPGA.
+ * @details Inputs: none
+ * @details Outputs: DMA write command response is ready to be received from the FPGA
+ * @return none
+ *************************************************************************/
+static void startDMAReceiptOfWriteResp( void )
+{
+ dmaSetCtrlPacket( DMA_CH0, fpgaDMAWriteRespControlRecord );
+ dmaSetChEnable( DMA_CH0, DMA_HW );
+ setSCI2DMAReceiveInterrupt();
+}
+
+/*********************************************************************//**
+ * @brief
+ * The resetFPGACommFlags function resets the various fpga comm flags and
+ * counters.
+ * @details \b Inputs: none
+ * @details \b Outputs: fpgaJobsQStatus
+ * @return none
+ *************************************************************************/
+static void resetFPGACommFlags( void )
+{
+ fpgaJobsQStatus.fpgaCommRead = FPGA_COMM_IDLE;
+ fpgaJobsQStatus.fpgaCommWrite = FPGA_COMM_IDLE;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The enqueue function enqueues a new job into the queue.
+ * @details \b Inputs: none
+ * @details \b Outputs: fpgaJobsQStatus
+ * @return none
+ *************************************************************************/
+static void enqueue( FPGA_JOBS_T job )
+{
+ U08 currentRearIndex = fpgaJobsQStatus.fpgaJobRearIndex;
+
+ fpgaJobsQStatus.fpgaJobsQueue[ currentRearIndex ] = job;
+ fpgaJobsQStatus.fpgaJobsQueueCount++;
+
+ fpgaJobsQStatus.fpgaJobRearIndex = INC_WRAP( currentRearIndex, 0, QUEUE_MAX_SIZE - 1 );
+}
+
+/*********************************************************************//**
+ * @brief
+ * The enqueue function dequeues a job from the queue. This function is thread
+ * safe. Prior to dequeuing a job, the IRQ interrupt is stopped.
+ * @details \b Inputs: fpgaJobsQStatus
+ * @details \b Outputs: fpgaJobsQStatus
+ * @return none
+ *************************************************************************/
+static void dequeue( void )
+{
+ U08 tempIndex;
+
+ _disable_IRQ();
+ tempIndex = fpgaJobsQStatus.fpgaJobFrontIndex;
+
+ if ( fpgaJobsQStatus.fpgaJobsQueueCount > 0 )
+ {
+ U08 frontIndex = fpgaJobsQStatus.fpgaJobFrontIndex;
+
+ fpgaJobsQStatus.fpgaJobFrontIndex = INC_WRAP( frontIndex, 0, QUEUE_MAX_SIZE - 1 );
+ fpgaJobsQStatus.fpgaCurrentJob = fpgaJobsQStatus.fpgaJobsQueue[ tempIndex ];
+ }
+
+ if ( fpgaJobsQStatus.fpgaJobsQueueCount > 0 )
+ {
+ fpgaJobsQStatus.fpgaJobsQueueCount--;
+ }
+ _enable_IRQ();
+}
+
+/*********************************************************************//**
+ * @brief
+ * The peekFromQueue function just reports what is the next job in the queue.
+ * This function does not do the actual dequeue. This function is thread
+ * safe. Prior to peeking into the next job, the IRQ interrupt is stopped.
+ * @details \b Inputs: fpgaJobsQStatus
+ * @details \b Outputs: none
+ * @return the next job that is in the queue
+ *************************************************************************/
+static FPGA_JOBS_T peekFromQueue( void )
+{
+ _disable_IRQ();
+ U08 frontIndex = fpgaJobsQStatus.fpgaJobFrontIndex;
+ FPGA_JOBS_T nextJob = (FPGA_JOBS_T)fpgaJobsQStatus.fpgaJobsQueue[ frontIndex ];
+ _enable_IRQ();
+
+ return nextJob;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The isQueueFull function checks whether the queue is full or not.
+ * @details \b Inputs: fpgaJobsQStatus
+ * @details \b Outputs: none
+ * @return TRUE if the queue is full otherwise, FALSE
+ *************************************************************************/
+static BOOL isQueueFull( void )
+{
+ BOOL isFull = FALSE;
+
+ if ( fpgaJobsQStatus.fpgaJobsQueueCount >= ( QUEUE_MAX_SIZE - 1 ) )
+ {
+ isFull = TRUE;
+ }
+
+ return isFull;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleFPGAIdleState function handles the FPGA idle state. This state
+ * checks whether there are any jobs in the queue and processes them. This
+ * state also requests the flash update registers.
+ * @details \b Inputs: fpgaJobsQStatus, fpgaFlashStatus
+ * @details \b Outputs: none
+ * @return next state of the FPGA state machine
+ *************************************************************************/
+static FPGA_STATE_T handleFPGAIdleState( void )
+{
+ FPGA_STATE_T state = FPGA_IDLE_STATE;
+
+ if ( fpgaJobsQStatus.fpgaJobsQueueCount > 0 )
+ {
+ BOOL isDequeueAllowed = TRUE;
+
+ if ( FPGA_FLASH_WRITE_DATA == peekFromQueue() )
+ {
+ // Check if the next job in the queue is a flash write.
+ // If there is a flash write, only dequeue it if:
+ // 1. There are at least 256 bytes available in the FIFO
+ // 2. The flash status is okay
+ // 3. The FIFO erase is okay
+ if ( ( fpgaFlashStatus.fifoRemainingCount < SW_UPDATE_FLASH_BUFFER_SIZE ) ||
+ ( FALSE == fpgaFlashStatus.isFlashStatusOk ) ||
+ ( FALSE == fpgaFlashStatus.isFIFOEraseOk ) )
+ {
+ isDequeueAllowed = FALSE;
+ }
+ }
+
+ if ( FPGA_SELF_CONFIGURE == peekFromQueue() )
+ {
+ // Check if the next job in the queue is the self configure. Then make sure:
+ // 1. The delay has timed out
+ // 2. The flash status is okay
+ if ( ( FALSE == didTimeout( fpgaFlashStatus.preSelfConfigureStartTimeMS, FPGA_PRE_SELF_CONFIG_TIMEOUT_MS ) ) ||
+ ( FALSE == fpgaFlashStatus.isFlashStatusOk ) )
+ {
+ isDequeueAllowed = FALSE;
+ }
+ }
+
+ if ( TRUE == isDequeueAllowed )
+ {
+ dequeue();
+ // After dequeue based on the job specs transition to either write or read states
+ state = ( FALSE == JOBS_SPECS[ fpgaJobsQStatus.fpgaCurrentJob ].fpgaIsJobWrite ? FPGA_READ_FROM_FPGA_STATE : FPGA_WRITE_TO_FPGA_STATE );
+ }
+ }
+
+ requestFlashRegistersStatus();
+
+ return state;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleFPGAWriteToFPGAState function handles the FPGA write to FPGA
+ * state. This state prepares the buffer to write to FPGA and sets the DMA
+ * to write to the FPGA.
+ * @details \b Inputs: fpgaJobsQStatus, fpgaDataLenToWrite
+ * @details \b Outputs: fpgaFlashStatus, fpgaWriteCmdBuffer[]
+ * @return next state of the FPGA state machine
+ *************************************************************************/
+static FPGA_STATE_T handleFPGAWriteToFPGAState( void )
+{
+ FPGA_STATE_T state = FPGA_RCV_WRITE_RESP_FROM_FPGA_STATE;
+ U16 crc = 0;
+ U16 jobAddress = JOBS_SPECS[ fpgaJobsQStatus.fpgaCurrentJob ].fpgaJobAddress;
+ U16 jobSize = JOBS_SPECS[ fpgaJobsQStatus.fpgaCurrentJob ].fpgaJobSize;
+
+ if ( ( fpgaDataLenToWrite != SW_UPDATE_FLASH_BUFFER_SIZE ) && ( FPGA_FLASH_WRITE_DATA == fpgaJobsQStatus.fpgaCurrentJob ) )
+ {
+ // Set the write length from the buffer length provided
+ jobSize = (U16)fpgaDataLenToWrite;
+ }
+
+ if ( FPGA_SELF_CONFIGURE == fpgaJobsQStatus.fpgaCurrentJob )
+ {
+ // Once self configure is sent the FPGA will be unresponsive so there will be no ack back
+ // Signal FPGA is completed
+ state = FPGA_IDLE_STATE;
+ fpgaFlashStatus.isFPGAFlashComplete = TRUE;
+ }
+
+ U08* value2Write = JOBS_SPECS[ fpgaJobsQStatus.fpgaCurrentJob ].fpgaWriteStartAddress;
+ U16 firstCRCIndex = FPGA_WRITE_CMD_HDR_LEN + jobSize;
+ U16 secondCRCIndex = FPGA_WRITE_CMD_HDR_LEN + jobSize + 1;
+
+ memcpy( &fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_HDR_LEN ], value2Write, jobSize );
+
+ // Construct bulk read command to read sensor data registers starting at address 8
+ fpgaWriteCmdBuffer[ 0 ] = FPGA_WRITE_CMD_CODE;
+ fpgaWriteCmdBuffer[ 1 ] = GET_LSB_OF_WORD( jobAddress );
+ fpgaWriteCmdBuffer[ 2 ] = GET_MSB_OF_WORD( jobAddress );
+ fpgaWriteCmdBuffer[ 3 ] = jobSize % SW_UPDATE_FLASH_BUFFER_SIZE;
+ crc = crc16( fpgaWriteCmdBuffer, FPGA_WRITE_CMD_HDR_LEN + jobSize );
+ fpgaWriteCmdBuffer[ firstCRCIndex ] = GET_MSB_OF_WORD( crc );
+ fpgaWriteCmdBuffer[ secondCRCIndex ] = GET_LSB_OF_WORD( crc );
+
+ // Prep DMA for sending the read cmd and receiving the response
+ fpgaJobsQStatus.fpgaCommWrite = FPGA_COMM_WRITE_IN_PROGRESS;
+
+ // Prep DMA for sending the bulk write cmd and receiving its response
+ setupDMAForWriteCmd( FPGA_WRITE_CMD_HDR_LEN + jobSize + FPGA_CRC_LEN );
+ setupDMAForWriteResp( FPGA_WRITE_RSP_HDR_LEN + FPGA_CRC_LEN );
+
+ // Initiate bulk write command and its receipt - read will follow
+ startDMAReceiptOfWriteResp();
+ startDMAWriteCmd();
+
+ return state;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleFPGAReceiveWriteRespFromFPGAState function handles the FPGA
+ * receive write to FPGA response.
+ * @details \b Inputs: fpgaJobsQStatus, fpgaWriteResponseBuffer[]
+ * @details \b Outputs: fpgaWriteResponseBuffer[]
+ * @return next state of the FPGA state machine
+ *************************************************************************/
+static FPGA_STATE_T handleFPGAReceiveWriteRespFromFPGAState( void )
+{
+ FPGA_STATE_T state = FPGA_RCV_WRITE_RESP_FROM_FPGA_STATE;
+
+ if ( FPGA_COMM_WRITE_RESP_RECEIVED == fpgaJobsQStatus.fpgaCommWrite )
+ {
+ if ( FPGA_WRITE_CMD_ACK == fpgaWriteResponseBuffer[ 0 ] )
+ {
+ // Message is an ack - check CRC
+ U32 rspSize = FPGA_READ_RSP_HDR_LEN;
+ U32 crcPos = rspSize;
+ U16 crc = MAKE_WORD_OF_BYTES( fpgaWriteResponseBuffer[ crcPos ], fpgaWriteResponseBuffer[ crcPos + 1 ] );
+
+ // Does the FPGA response CRC checkout?
+ if ( crc == crc16( fpgaWriteResponseBuffer, rspSize ) )
+ {
+ if ( FPGA_FLASH_WRITE_DATA == fpgaJobsQStatus.fpgaCurrentJob )
+ {
+ sendFPGAAckNackStatus( ACK );
+ tempACkStatus = ACK; // TODO remove
+
+ TESTREMOVE += fpgaDataLenToWrite;// TODO REMOVE
+ countRemove += 1;// TODO REMOVE
+ }
+
+ // CRC passed
+ state = FPGA_IDLE_STATE;
+ }
+ else
+ {
+ // TODO error handling
+ }
+ }
+
+ memset( fpgaWriteCmdBuffer, 0x0, FPGA_WRITE_CMD_BUFFER_LEN ); // TODO a better place for this
+ }
+
+ requestFlashRegistersStatus();
+
+ return state;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleFPGAReadFromFPGAState function handles the FPGA read from FPGA.
+ * @details \b Inputs: none
+ * @details \b Outputs: fpgaReadCmdBuffer[], fpgaJobsQStatus, fpgaFlashStatus
+ * @return next state of the FPGA state machine
+ *************************************************************************/
+static FPGA_STATE_T handleFPGAReadFromFPGAState( void )
+{
+ FPGA_STATE_T state = FPGA_RCV_READ_RESP_FROM_FPGA_STATE;
+ U16 crc = 0;
+ U16 jobAddress = JOBS_SPECS[ fpgaJobsQStatus.fpgaCurrentJob ].fpgaJobAddress;
+ U08 jobSize = JOBS_SPECS[ fpgaJobsQStatus.fpgaCurrentJob ].fpgaJobSize;
+
+ // Construct read command to read 3 registers starting at address 0
+ fpgaReadCmdBuffer[ 0 ] = FPGA_READ_CMD_CODE;
+ fpgaReadCmdBuffer[ 1 ] = GET_LSB_OF_WORD( jobAddress );
+ fpgaReadCmdBuffer[ 2 ] = GET_MSB_OF_WORD( jobAddress );
+ fpgaReadCmdBuffer[ 3 ] = jobSize;
+ crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN );
+ fpgaReadCmdBuffer[ 4 ] = GET_MSB_OF_WORD( crc );
+ fpgaReadCmdBuffer[ 5 ] = GET_LSB_OF_WORD( crc );
+
+ // Prep DMA for sending the read cmd and receiving the response
+ fpgaJobsQStatus.fpgaCommRead = FPGA_COMM_READ_IN_PROGRESS;
+ fpgaFlashStatus.startTime = getMSTimerCount();
+
+ setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + jobSize + sizeof( U16 ) );
+ setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + sizeof( U16 ) );
+ startDMAReceiptOfReadResp();
+ startDMAReadCmd();
+
+ return state;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleFPGAReceiveReadRespFromFPGAState function handles the FPGA
+ * read response from FPGA.
+ * @details \b Inputs: fpgaJobsQStatus, fpgaReadResponseBuffer[]
+ * @details \b Outputs: fpgaReadResponseBuffer[], fpgaHeader,
+ * fpgaUpdateRegisterStatus
+ * @return next state of the FPGA state machine
+ *************************************************************************/
+static FPGA_STATE_T handleFPGAReceiveReadRespFromFPGAState( void )
+{
+ FPGA_STATE_T state = FPGA_RCV_READ_RESP_FROM_FPGA_STATE;
+
+ if ( FPGA_COMM_READ_RESP_RECEIVED == fpgaJobsQStatus.fpgaCommRead )
+ {
+ if ( FPGA_READ_CMD_ACK == fpgaReadResponseBuffer[ 0 ] )
+ {
+ U32 rspSize = FPGA_READ_RSP_HDR_LEN + JOBS_SPECS[ fpgaJobsQStatus.fpgaCurrentJob ].fpgaJobSize;
+ U32 crcPos = rspSize;
+ U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ crcPos ], fpgaReadResponseBuffer[ crcPos + 1 ] );
+
+ // Does the FPGA response CRC check out?
+ if ( crc == crc16( fpgaReadResponseBuffer, rspSize ) )
+ {
+ switch( fpgaJobsQStatus.fpgaCurrentJob )
+ {
+ case FPGA_READ_HEADER:
+ memcpy( &fpgaHeader, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], sizeof( FPGA_HEADER_T ) );
+ break;
+
+ case FPGA_READ_UPDATE_REG:
+ fpgaUpdateRegisterStatus = fpgaReadResponseBuffer[ FPGA_UPDATE_REQUEST_INDEX ];
+ break;
+
+ default:
+ // Do nothing
+ break;
+ }
+
+ memset( fpgaReadResponseBuffer, 0x0, FPGA_READ_RSP_BUFFER_LEN );
+
+ state = FPGA_IDLE_STATE;
+ }
+ }
+ }
+
+ if ( TRUE == didTimeout( fpgaFlashStatus.startTime, 100 ) )
+ {
+ state = FPGA_IDLE_STATE;
+ }
+
+ resetFPGACommFlags();
+
+ // Should not be any data received at this time
+ consumeUnexpectedData();
+
+ return state;
+}
+
+/**@}*/
+
Index: firmware/App/Services/FPGA.h
===================================================================
diff -u
--- firmware/App/Services/FPGA.h (revision 0)
+++ firmware/App/Services/FPGA.h (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -0,0 +1,41 @@
+
+#ifndef __FPGA_H__
+#define __FPGA_H__
+
+#include "BLCommon.h"
+
+/**
+ * @defgroup FPGA FPGA
+ * @brief FPGA service unit.
+ * The FPGA unit manages communication between the bootloader and the FPGA via UART.
+ * This unit is driven by the Priority Task via calls to two FPGA executive functions:
+ * 1) Writes update data to the FPGA flash
+ * 2) Reads header, update register, FIFO count as well as the flash status
+ * This unit first reads the header record that includes the FPGA ID and revision and
+ * verifies the FPGA ID to check FPGA communication.
+ *
+ * @addtogroup FPGA
+ * @{
+ */
+
+// ********** public definitions **********
+
+// ********** public function prototypes **********
+
+void initFPGA( void );
+
+void execFPGA( void );
+
+void signalFPGAReceiptCompleted( void );
+
+BOOL hasUpdateBeenRequested( void );
+BOOL isFPGAIDValid( void );
+BOOL isFPGAFlashComplete( void );
+
+void signalFPGAToPrepareForUpdate( void );
+void signalFPGAToWriteToFlash( U08* data, U32 len );
+void signalFPGAToSelfConfigure( void );
+
+/**@}*/
+
+#endif
Index: firmware/App/Services/FlashAPI/F021_API_CortexR4_LE_L2FMC_V3D16_NDS.lib
===================================================================
diff -u
Binary files differ
Index: firmware/App/Services/Interrupts.c
===================================================================
diff -u -r850f8042a02fd17ee53b8db24bc2e3d17bbb9c7f -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Services/Interrupts.c (.../Interrupts.c) (revision 850f8042a02fd17ee53b8db24bc2e3d17bbb9c7f)
+++ firmware/App/Services/Interrupts.c (.../Interrupts.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,28 +1,69 @@
-/*
- * Interrupts.c
- *
- * Created on: Aug 1, 2024
- * Author: fw
- */
#include "can.h"
#include "rti.h"
#include "sci.h"
#include "sys_dma.h"
#include "BLCommon.h"
-#include "CommBuffers.h"
+#include "Comm.h"
+#include "FPGA.h"
+#include "SystemComm.h"
#include "TaskGeneral.h"
#include "TaskPriority.h"
#include "TaskTimer.h"
+/**
+ * @addtogroup Interrupts
+ * @{
+ */
+// ********** private definitions **********
+
+// TODO do we need more error handling? (i.e. canErrorNotification)
+
+// ********** private data **********
+
+static BOOL sci2FEOEError; ///< FPGA serial frame or overrun flag;
+
+// ********** private function prototypes **********
+
+/*********************************************************************//**
+ * @brief
+ * The initInterrupts function initializes the Interrupts unit.
+ * @details \b Inputs: none
+ * @details \b Outputs: Interrupts unit initialized.
+ * @return none
+ *************************************************************************/
void initInterrupts( void )
{
- // TODO fill up
+ sci2FEOEError = FALSE;
}
+/*********************************************************************//**
+ * @brief
+ * The getSci2FEOEError function returns the sci2FEOEError (OE - Overrun,
+ * FE - Framing Error) status and resets the status if TRUE
+ * @details \b Inputs: sci2FEOEError
+ * @details \b Outputs: none
+ * @return sci2 FE / OE error
+ *************************************************************************/
+BOOL getSci2FEOEError( void )
+{
+ BOOL returnValue = sci2FEOEError;
+ sci2FEOEError = ( TRUE == returnValue ? FALSE : sci2FEOEError );
+
+ return returnValue;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The rtiNotification function handles real-time interrupt notifications.
+ * @details \b Inputs: none
+ * @details \b Outputs: Task associated with given notification is executed.
+ * @param notification ID of RTI timer that caused this interrupt
+ * @return none
+ *************************************************************************/
void rtiNotification( uint32 notification )
{
switch ( notification )
@@ -46,10 +87,86 @@
}
}
+/*********************************************************************//**
+ * @brief
+ * The canMessageNotification function handles CAN message notifications.
+ * @details \b Inputs: none
+ * @details \b Outputs: CAN message notification handled.
+ * @param node ID of CAN controller that given notification came from.
+ * @param messageBox ID of CAN mailbox that triggered the message notification
+ * @return none
+ *************************************************************************/
void canMessageNotification( canBASE_t *node, uint32 messageBox )
{
if ( node == canREG1 )
{
- handleCANMsgInterrupt( (SW_UPDATE_CAN_MAIL_BOXES_T)messageBox );
+ handleCANMsgInterrupt( (SW_UPDATE_CAN_MAIL_BOX_T)messageBox );
}
}
+
+/*********************************************************************//**
+ * @brief
+ * The sciNotification function handles UART communication error interrupts.
+ * Frame and Over-run errors are recorded and cleared.
+ * @details \b Inputs: none
+ * @details \b Outputs: sci2FEOEError, sci2FEOEError
+ * @param sci Pointer to the SCI peripheral that detected the error
+ * @param flags 32 bits of error flags
+ * @return none
+ *************************************************************************/
+void sciNotification( sciBASE_t *sci, uint32 flags )
+{
+#ifndef _VECTORCAST_
+ // Cannot set the pointers to be equal in VectorCAST. Can define pointers but the user does not have any control on the address of it
+ if ( sci == scilinREG )
+#endif
+ {
+ if ( ( flags & SCI_FE_INT ) != 0 )
+ {
+ sci2FEOEError = TRUE;
+ scilinREG->FLR |= SCI_FE_INT;
+ }
+
+ if ( ( flags & SCI_OE_INT ) != 0 )
+ {
+ sci2FEOEError = TRUE;
+ scilinREG->FLR |= SCI_OE_INT;
+ }
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The dmaGroupANotification function handles communication DMA interrupts.
+ * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given DMA channel is
+ * invalid/unexpected.
+ * @details \b Inputs: none
+ * @details \b Outputs: DMA interrupt is handled.
+ * @param inttype type of DMA interrupt
+ * @param channel DMA channel that caused the interrupt
+ * @return none
+ *************************************************************************/
+void dmaGroupANotification( dmaInterrupt_t inttype, uint32 channel )
+{
+ if ( inttype == BTC ) // Block transfer completed interrupt
+ {
+ switch ( channel )
+ {
+ case DMA_CH0: // FPGA receive channel
+ clearSCI2DMAReceiveInterrupt();
+ signalFPGAReceiptCompleted();
+ break;
+
+ case DMA_CH2: // FPGA transmit channel
+ clearSCI2DMATransmitInterrupt();
+ break;
+
+ default:
+ // Do nothing
+ break;
+ }
+ }
+}
+
+/**@}*/
+
Index: firmware/App/Services/Interrupts.h
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Services/Interrupts.h (.../Interrupts.h) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/App/Services/Interrupts.h (.../Interrupts.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,14 +1,23 @@
-/*
- * Interrupts.h
- *
- * Created on: Aug 1, 2024
- * Author: fw
- */
#ifndef __INTERRUPTS_H__
#define __INTERRUPTS_H__
+/**
+ * @defgroup Interrupts Interrupts
+ * @brief Interrupts unit handles various peripheral interrupts.
+ *
+ * @addtogroup Interrupts
+ * @{
+ */
+
+// ********** public definitions **********
+
+// ********** public function prototypes **********
+
void initInterrupts( void );
+BOOL getSci2FEOEError( void );
+/**@}*/
+
#endif
Index: firmware/App/Services/NVDataMgmt.c
===================================================================
diff -u
--- firmware/App/Services/NVDataMgmt.c (revision 0)
+++ firmware/App/Services/NVDataMgmt.c (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -0,0 +1,247 @@
+
+#include // For memcpy and memset
+
+#include "F021.h" // For fapi operations
+#include "system.h" // For fapi operations
+
+#include "NVDataMgmt.h"
+
+/**
+ * @addtogroup NVDataMgmt
+ * @{
+ */
+
+/*
+ * TODO
+ * 1. Clean up the flash with the bad data packets
+ */
+
+// ********** private definitions **********
+
+#define BANK0_NUM_OF_SECTORS 16 ///< Bank0 number of sectors.
+#define FLOAT_TO_INT_ROUNDUP_OFFSET 0.5F ///< Offset to add to a floating point value for rounding rounding when converting to integer.
+#define ROUNDED_HCLK_FREQ ((HCLK_FREQ) < 0.0F ? (S32)((HCLK_FREQ) - FLOAT_TO_INT_ROUNDUP_OFFSET) : \
+ (S32)((HCLK_FREQ) + FLOAT_TO_INT_ROUNDUP_OFFSET)) ///< Rounded HCLK for flash clock.
+
+/// EEPROM functions use the buffer length as the size of U32. So before send the length to any of FAPI functions, it should be divided by 4.
+#define EEPROM_OPS_SIZE_OF_CONVERTER 4
+#define NUM_OF_BYTES_WRITE_TO_FALSH 16 ///< Number of bytes to write.
+#define NUM_OF_FIRMWARE_CRC_TABLE_BYTES 1 ///< Number of firmware CRC table bytes.
+#define VALUE_OF_AN_ERASED_FLASH 0xFFFFFFFF ///< Value of an erased flash.
+
+/// Flash write status structure
+typedef struct Flash_Write_Status
+{
+ BOOL hasFlashBeenErased; ///< Boolean flag to indicate flash has been erased.
+ U32 currentWriteAddress; ///< Current write address in the flash memory.
+} SW_UPDATE_FALSH_STATUS_T;
+
+/// Bank 0 sectors status structure
+typedef struct Sectors
+{
+ U32 startAddress; ///< Start address.
+ U32 length; // number of 32-bit words ///< Length of data (word or 4 bytes).
+ U32 bankNumber; ///< Bank number.
+ U32 sectorNumber; ///< Sector number.
+} BANK0_SECTORS_T;
+
+/// Bank sectors array
+const BANK0_SECTORS_T bank0Sectors[ BANK0_NUM_OF_SECTORS ]=
+{
+ 0x00000000, 0x04000, 0, 0,
+ 0x00004000, 0x04000, 0, 1,
+ 0x00008000, 0x04000, 0, 2,
+ 0x0000C000, 0x04000, 0, 3,
+ 0x00010000, 0x04000, 0, 4,
+ 0x00014000, 0x04000, 0, 5,
+ 0x00018000, 0x08000, 0, 6,
+ 0x00020000, 0x20000, 0, 7,
+ 0x00040000, 0x20000, 0, 8,
+ 0x00060000, 0x20000, 0, 9,
+ 0x00080000, 0x20000, 0, 10,
+ 0x000A0000, 0x20000, 0, 11,
+ 0x000C0000, 0x20000, 0, 12,
+ 0x000E0000, 0x20000, 0, 13,
+ 0x00100000, 0x20000, 0, 14,
+ 0x00120000, 0x20000, 0, 15
+};
+
+// ********** private data **********
+
+static SW_UPDATE_FALSH_STATUS_T SWUpdateFlashStatus; ///< Software update flash status.
+
+// ********** private function prototypes **********
+
+static BOOL eraseFlashSectors( void );
+static BOOL writeFlashSectors( U08* data );
+
+/*********************************************************************//**
+ * @brief
+ * The initNVDataMgmt function initializes the module.
+ * @details \b Inputs: none
+ * @details \b Outputs: initializes flash bank 0.
+ * @return none
+ *************************************************************************/
+void initNVDataMgmt( void )
+{
+ // Setup the flash bank clock
+ Fapi_initializeFlashBanks( ROUNDED_HCLK_FREQ );
+ // Activate flash bank 0
+ Fapi_setActiveFlashBank( Fapi_FlashBank0 );
+ Fapi_enableMainBankSectors( 0xFFFF ); /* used for API 2.01*/
+ while( FAPI_CHECK_FSM_READY_BUSY != Fapi_Status_FsmReady );
+
+ clearSWUpdateNVStatus();
+}
+
+/*********************************************************************//**
+ * @brief
+ * The clearSWUpdateNVStatus function clears the variables that are used
+ * in software update.
+ * @details \b Inputs: none
+ * @details \b Outputs: SWUpdateFlashStatus
+ * @return none
+ *************************************************************************/
+void clearSWUpdateNVStatus( void )
+{
+ SWUpdateFlashStatus.hasFlashBeenErased = FALSE;
+ SWUpdateFlashStatus.currentWriteAddress = FIRMWARE_START_ADDRESS;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleUpdatingFlash function handles updating the flash. If the sectors
+ * have not been erased first, they are erased.
+ * @details \b Inputs: none
+ * @details \b Outputs: SWUpdateFlashStatus
+ * @param data to write pointer to the buffer that is going to be written
+ * to flash
+ * @return TRUE if the write and erase was successful otherwise, FALSE
+ *************************************************************************/
+BOOL handleUpdatingFlash( U08* dataToWrite )
+{
+ BOOL status = FALSE;
+
+ if ( FALSE == SWUpdateFlashStatus.hasFlashBeenErased )
+ {
+ // TODO what should we do if the erase failed? try again?
+ SWUpdateFlashStatus.hasFlashBeenErased = eraseFlashSectors();
+
+ if ( TRUE == SWUpdateFlashStatus.hasFlashBeenErased )
+ {
+ status = writeFlashSectors( dataToWrite );
+ }
+ }
+ else
+ {
+ status = writeFlashSectors( dataToWrite );
+ }
+
+ return status;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The isFWCRCTableValid function checks whether the firmware CRC table is
+ * valid or not. This function reads a word data starting from the firmware
+ * start address. Then it is verified to make sure it is not 0xFFFFFFFF.
+ * @details \b Inputs: none
+ * @details \b Outputs: none
+ * @return TRUE if the firmware CRC is valid otherwise, FALSE
+ *************************************************************************/
+BOOL isFWCRCTableValid( void )
+{
+ Fapi_FlashStatusWordType crcVerifyReason;
+ U32 erasedFlashedValue[ NUM_OF_FIRMWARE_CRC_TABLE_BYTES ];
+
+ BOOL crcVerifyStatus = FALSE;
+
+ // Create a buffer of 1 byte and write 0xFFFFFFFF to it
+ memset( erasedFlashedValue, VALUE_OF_AN_ERASED_FLASH, sizeof( erasedFlashedValue ) );
+
+ // Verify the value is not 0xFFFFFFFF reading from the firmware start address
+ crcVerifyStatus = Fapi_doVerify( (U32*)FIRMWARE_CRC_TABLE_ADDRESS, NUM_OF_FIRMWARE_CRC_TABLE_BYTES,
+ (U32*)&erasedFlashedValue, &crcVerifyReason );
+ // Wait for the FAPI respond
+ while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy ); // TODO timeout or count so we wont get stuck here for ever
+
+ // Check if the value of the provided buffer is the same as the what was found in the firmware start address
+ crcVerifyStatus = ( Fapi_Status_Success == crcVerifyStatus ? FALSE : TRUE );
+
+ return crcVerifyStatus;
+}
+
+// ********** private functions **********
+
+/*********************************************************************//**
+ * @brief
+ * The eraseFlashSectors function erases the flash sectors. It starts from
+ * the sectors of the firmware start address and erases until the end of bank 0.
+ * @details \b Inputs: none
+ * @details \b Outputs: none
+ * @return TRUE if the erase was successful otherwise, FALSE
+ *************************************************************************/
+static BOOL eraseFlashSectors( void )
+{
+ U08 i;
+
+ BOOL status = FALSE;
+
+ for ( i = 0; i < BANK0_NUM_OF_SECTORS; i++ )
+ {
+ if ( bank0Sectors[ i ].startAddress >= FIRMWARE_START_ADDRESS )
+ {
+ Fapi_issueAsyncCommandWithAddress( Fapi_EraseSector, (U32*)bank0Sectors[ i ].startAddress );
+ while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy );
+ while(FAPI_GET_FSM_STATUS != Fapi_Status_Success);
+ status |= TRUE;
+ }
+ }
+
+ // TODO check the erased sectors
+
+ return status;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The writeFlashSectors function writes to a sector of the flash.
+ * @details \b Inputs: SWUpdateFlashStatus
+ * @details \b Outputs: none
+ * @return TRUE if the write was successful otherwise, FALSE
+ *************************************************************************/
+static BOOL writeFlashSectors( U08* data )
+{
+ Fapi_FlashStatusWordType writeVerifyReason;
+ Fapi_StatusType writeVerifyStatus;
+ U08 dataRead2Verify[ SW_UPDATE_FLASH_BUFFER_SIZE ];
+
+ BOOL status = FALSE;
+ U08 bytesWritten = 0;
+ U32 startAddress = SWUpdateFlashStatus.currentWriteAddress;
+
+ memcpy( dataRead2Verify, data, SW_UPDATE_FLASH_BUFFER_SIZE );
+
+ // Keep writing until the buffer is finished
+ while ( bytesWritten < SW_UPDATE_FLASH_BUFFER_SIZE )
+ {
+ Fapi_issueProgrammingCommand( (U32*)SWUpdateFlashStatus.currentWriteAddress, data, NUM_OF_BYTES_WRITE_TO_FALSH, 0x00, 0, Fapi_DataOnly );
+ while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy );
+
+ // Update the write pointer. Update the current write address in the flash
+ data += NUM_OF_BYTES_WRITE_TO_FALSH;
+ SWUpdateFlashStatus.currentWriteAddress += NUM_OF_BYTES_WRITE_TO_FALSH;
+ bytesWritten += NUM_OF_BYTES_WRITE_TO_FALSH;
+ }
+
+ writeVerifyStatus = Fapi_doVerify( (U32*)startAddress, ( SW_UPDATE_FLASH_BUFFER_SIZE / SW_UPDATE_FLASH_BUFFER_SIZE ),
+ (U32*)&dataRead2Verify, &writeVerifyReason );
+ while( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy ); // TODO timeout or count so we wont get stuck here forever
+
+ status = ( Fapi_Status_Success == writeVerifyStatus ? TRUE : FALSE );
+
+ return status;
+}
+
+/**@}*/
+
Index: firmware/App/Services/NVDataMgmt.h
===================================================================
diff -u
--- firmware/App/Services/NVDataMgmt.h (revision 0)
+++ firmware/App/Services/NVDataMgmt.h (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -0,0 +1,30 @@
+
+#ifndef __NVDATAMGMT_H__
+#define __NVDATAMGMT_H__
+
+#include "BLCommon.h"
+
+/**
+ * @defgroup NVDataMgmt NVDataMgmt
+ * @brief Non-volatile data management module. Handles Bank 7 of the TI processor and the
+ * RAM of the RTC chip.
+ *
+ * @addtogroup NVDataMgmt
+ * @{
+ */
+
+// ********** public definitions **********
+
+// ********** public function prototypes **********
+
+void initNVDataMgmt( void );
+
+void clearSWUpdateNVStatus( void );
+
+BOOL handleUpdatingFlash( U08* dataToWrite );
+
+BOOL isFWCRCTableValid( void );
+
+/**@}*/
+
+#endif
Index: firmware/App/Services/SystemComm.c
===================================================================
diff -u
--- firmware/App/Services/SystemComm.c (revision 0)
+++ firmware/App/Services/SystemComm.c (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -0,0 +1,103 @@
+
+#include "can.h"
+
+#include "CommBuffers.h"
+#include "SystemComm.h"
+
+/**
+ * @addtogroup SystemComm
+ * @{
+ */
+
+// ********** private definitions **********
+
+/*********************************************************************//**
+ * @brief
+ * The initSystemComm function initializes the SystemComm unit.
+ * @details \b Inputs: none
+ * @details \b Outputs: SystemComm unit variables initialized.
+ * @return none
+ *************************************************************************/
+void initSystemComm( void )
+{
+
+}
+
+/*********************************************************************//**
+ * @brief
+ * The handleCANMsgInterrupt function handles a CAN frame interrupt from
+ * a given CAN mail box.
+ * This may have occurred because a CAN frame transmission has completed
+ * or because a CAN frame has been received. The appropriate handler is
+ * called.
+ * @details \b Inputs: none
+ * @details \b Outputs: message interrupt handled
+ * @param mailbox which CAN mail box triggered this interrupt
+ * @return none
+ *************************************************************************/
+void handleCANMsgInterrupt( SW_UPDATE_CAN_MAIL_BOX_T mailBox )
+{
+ // TODO do we need check the range of the messages?
+ // TODO retry?
+
+ U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ];
+
+ if ( SW_UPDATE_COMMAD == mailBox )
+ {
+ if ( FALSE != canIsRxMessageArrived( canREG1, mailBox ) )
+ {
+ U32 result = canGetData( canREG1, mailBox, data );
+
+ if ( result != 0 )
+ {
+ addToCommBuffer( mailBox, data, CAN_MESSAGE_PAYLOAD_SIZE );
+ }
+ }
+ }
+ else
+ {
+ if ( RECEIVE_MSG_ID[ BL_STACK_ID ] == mailBox )
+ {
+ if ( FALSE != canIsRxMessageArrived( canREG1, mailBox ) )
+ {
+ U32 result = canGetData( canREG1, mailBox, data );
+
+ if ( result != 0 )
+ {
+ addToCommBuffer( mailBox, data, CAN_MESSAGE_PAYLOAD_SIZE );
+ }
+ }
+ }
+ }
+}
+
+/*********************************************************************//**
+ * @brief
+ * The sendAckNackStatusFromFirmware function sends the ack or nack status
+ * of a received message.
+ * @details \b Inputs: none
+ * @details \b Outputs: none
+ * @param data pointer to the data to be sent
+ * @return TRUE if the CAN transmit was successful otherwise, FALSE
+ *************************************************************************/
+BOOL sendAckNackStatusFromFirmware( U08* data )
+{
+ BOOL status = FALSE;
+
+ if ( 0 != canTransmit( canREG1, (U32)SW_UPDATE_RESP, data ) )
+ {
+ status = TRUE;
+ }
+
+ return status;
+}
+
+BOOL broadcastDataTestRemove( U08* data ) // TODO remove
+{
+ canTransmit( canREG1, (U32)SW_TEST, data );
+
+ return TRUE;
+}
+
+/**@}*/
+
Index: firmware/App/Services/SystemComm.h
===================================================================
diff -u
--- firmware/App/Services/SystemComm.h (revision 0)
+++ firmware/App/Services/SystemComm.h (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -0,0 +1,29 @@
+
+#ifndef __SYSCOMM_H__
+#define __SYSCOMM_H__
+
+#include "BLCommon.h"
+
+/**
+ * @defgroup SystemComm SystemComm
+ * @brief System communication unit. Manages incoming and outgoing CAN frames.
+ *
+ * @addtogroup SystemComm
+ * @{
+ */
+
+// ********** public definitions **********
+
+// ********** public function prototypes **********
+
+void initSystemComm( void );
+
+void handleCANMsgInterrupt( SW_UPDATE_CAN_MAIL_BOX_T mailBox );
+
+BOOL sendAckNackStatusFromFirmware( U08* data );
+
+BOOL broadcastDataTestRemove( U08* data );
+
+/**@}*/
+
+#endif
Index: firmware/App/Services/Timers.c
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Services/Timers.c (.../Timers.c) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/App/Services/Timers.c (.../Timers.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,12 +1,10 @@
-/*
- * Timers.c
- *
- * Created on: Aug 1, 2024
- * Author: fw
- */
#include "Timers.h"
+/**
+ * @addtogroup Timers
+ * @{
+ */
// ********** private definitions **********
@@ -16,9 +14,9 @@
/*********************************************************************//**
* @brief
- * The initTimers function initializes the Timers module.
- * @details Inputs: msTimerCount
- * @details Outputs: msTimerCount
+ * The initTimers function initializes the Timers unit.
+ * @details \b Inputs: none
+ * @details \b Outputs: msTimerCount
* @return none
*************************************************************************/
void initTimers( void )
@@ -29,8 +27,8 @@
/*********************************************************************//**
* @brief
* The incMSTimerCount function increments the ms timer count.
- * @details Inputs: msTimerCount
- * @details Outputs: msTimerCount
+ * @details \b Inputs: msTimerCount
+ * @details \b Outputs: msTimerCount
* @return none
*************************************************************************/
void incMSTimerCount( void )
@@ -41,9 +39,9 @@
/*********************************************************************//**
* @brief
* The getMSTimerCount function returns the current ms timer count.
- * @details Inputs: msTimerCount
- * @details Outputs: none
- * @return msTimerCount as a U32
+ * @details \b Inputs: msTimerCount
+ * @details \b Outputs: none
+ * @return The current 32-bit millisecond timer count.
*************************************************************************/
U32 getMSTimerCount( void )
{
@@ -54,8 +52,8 @@
* @brief
* The didTimeout function determines whether a timeout has occurred between
* a given start count and a given timeout period (in ms).
- * @details Inputs: msTimerCount
- * @details Outputs: none
+ * @details \b Inputs: msTimerCount
+ * @details \b Outputs: none
* @param startMSCount the ms count at the start of the timeout period
* @param timeoutPeriod the period for the timeout (in ms)
* @return TRUE if a timeout has occurred, FALSE if not
@@ -87,6 +85,4 @@
return result;
}
-
-
-
+/**@}*/
Index: firmware/App/Services/Timers.h
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Services/Timers.h (.../Timers.h) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/App/Services/Timers.h (.../Timers.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,18 +1,25 @@
-/*
- * Timers.h
- *
- * Created on: Aug 1, 2024
- * Author: fw
- */
#ifndef __TIMERS_H__
#define __TIMERS_H__
#include "BLCommon.h"
+/**
+ * @defgroup Timers Timers
+ * @brief Timers service unit. Provides timer utility functions based on
+ * a 1ms timer counter incremented by TaskTimer.c.
+ *
+ * @addtogroup Timers
+ * @{
+ */
+
+// ********** public function prototypes **********
+
void initTimers( void );
void incMSTimerCount( void );
U32 getMSTimerCount( void );
BOOL didTimeout( U32 startMSCount, U32 timeoutPeriod );
+/**@}*/
+
#endif
Index: firmware/App/Services/Utilities.c
===================================================================
diff -u -rf2652e85c8676d0356fea2690cfd9cac716ca795 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Services/Utilities.c (.../Utilities.c) (revision f2652e85c8676d0356fea2690cfd9cac716ca795)
+++ firmware/App/Services/Utilities.c (.../Utilities.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,16 +1,23 @@
-/*
- * Utilities.c
- *
- * Created on: Aug 4, 2024
- * Author: fw
- */
+#ifndef _VECTORCAST_
+// This header file is disabled in VectorCAST because this is a TI library and VectorCAST uses GNU 7.4 compiler for testing
+#include
+#endif
+
#include "Utilities.h"
-#define SHIFT_8_BITS_FOR_BYTE_SHIFT 8 ///< Number of bits to shift in order to shift a byte
-#define SHIFT_24_BITS 24 ///< Number of bits to shift in order to shift 3 bytes
+/**
+ * @addtogroup Utilities
+ * @{
+ */
+// ********** private definitions **********
+#define INITIAL_CRC16_VAL 0xFFFF ///< Seed for 16-bit CRC function.
+#define SHIFT_24_BITS 24 ///< Number of bits to shift in order to shift 3 bytes.
+
+// ********** private data **********
+
/// CRC-32 look-up table.
const U32 CRC32_TABLE[] =
{
@@ -48,7 +55,103 @@
0xD2DFB272, 0xCC03DD33, 0xEF676CF0, 0xF1BB03B1, 0xA9AE0F76, 0xB7726037, 0x9416D1F4, 0x8ACABEB5,
};
+/// CRC-16 look-up table.
+const U16 CRC16_TABLE[] =
+{
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+};
+/*********************************************************************//**
+ * @brief
+ * The runFWIntegrityTest function runs the firmware integrity test on the
+ * firmware that is in the flash. It returns whether the integrity passed or
+ * failed.
+ * @details \b Inputs: none
+ * @details \b Outputs: none
+ * @return TRUE if integrity test passed otherwise, FALSE
+ *************************************************************************/
+BOOL runFWIntegrityTest( void )
+{
+ U32 remainingSize = 0;
+ U32 currentRecord = 0; ///< Current CRC table record to check.
+ U32 currentProcessedSize = 0; ///< Current data size processed for CRC calculation.
+ U32 crcCalculated = 0; ///< The calculated CRC value.
+
+ CRC_TABLE const * const crcTablePtr = (CRC_TABLE *)FIRMWARE_CRC_TABLE_ADDRESS;
+ CRC_RECORD const * currentRecordPtr = &crcTablePtr->recs[ currentRecord ];
+ BOOL integrityStatus = TRUE;
+
+ do
+ {
+ currentRecordPtr = &crcTablePtr->recs[ currentRecord ];
+
+ if ( currentRecord < crcTablePtr->num_recs )
+ {
+ remainingSize = currentRecordPtr->size - currentProcessedSize;
+
+ if ( remainingSize > MAX_CRC_CALC_DATA_SIZE )
+ {
+ crcCalculated = crc32( crcCalculated, (U08 *)( currentRecordPtr->addr + currentProcessedSize ), MAX_CRC_CALC_DATA_SIZE );
+ currentProcessedSize += MAX_CRC_CALC_DATA_SIZE;
+ }
+ else
+ {
+ crcCalculated = crc32( crcCalculated, (U08 *)( currentRecordPtr->addr + currentProcessedSize ), remainingSize );
+ integrityStatus &= ( ( (U32)currentRecordPtr->crc_value == crcCalculated ) ? TRUE : FALSE );
+ crcCalculated = 0;
+ currentProcessedSize = 0;
+ currentRecord++;
+ }
+ }
+ } while ( ( currentRecord < crcTablePtr->num_recs ) && ( integrityStatus == TRUE ) );
+
+ integrityStatus &= (currentRecord == crcTablePtr->num_recs);
+
+ return integrityStatus;
+}
+
+/*********************************************************************//**
+ * @brief
+ * The crc32 function calculates a 32-bit CRC for a given range of bytes
+ * in memory. Poly = 0x1EDC6F41. Not reflected. Initial value = 0x00000000.
+ * @details \b Inputs: CRC32_TABLE[]
+ * @details \b Outputs: none
+ * @param initialValue initial CRC seed value
+ * @param address pointer to start address of memory range to calculate CRC for
+ * @param len number of bytes in the memory range to calculate CRC for
+ * @return 32-bit CRC
+ *************************************************************************/
U32 crc32( U32 initialValue, U08 *address, U32 len )
{
U32 crc = initialValue;
@@ -62,9 +165,28 @@
return crc;
}
-BOOL isCRCValid( U32 msgCRC, U32 calcCRC )
+/*********************************************************************//**
+ * @brief
+ * The crc16 function calculates a 16-bit CRC for a given range of bytes
+ * in memory. Poly = 0x1021. Not reflected. Initial value = 0xFFFF.
+ * @details \b Inputs: CRC16_TABLE[]
+ * @details \b Outputs: none
+ * @param address pointer to start address of memory range to calculate CRC for
+ * @param len number of bytes in the memory range to calculate CRC for
+ * @return 16-bit CRC
+ *************************************************************************/
+U16 crc16( U08 *address, U32 len )
{
- return ( msgCRC == calcCRC ? TRUE : FALSE );
+ U16 crc = INITIAL_CRC16_VAL;
+
+ while ( len-- > 0 )
+ {
+ crc = ( crc << SHIFT_8_BITS_FOR_BYTE_SHIFT ) ^ CRC16_TABLE[ *address ^ ( ( crc >> SHIFT_8_BITS_FOR_BYTE_SHIFT ) & MASK_OFF_MSB ) ];
+ address++;
+ }
+
+ return crc;
}
+/**@}*/
Index: firmware/App/Services/Utilities.h
===================================================================
diff -u -rf2652e85c8676d0356fea2690cfd9cac716ca795 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Services/Utilities.h (.../Utilities.h) (revision f2652e85c8676d0356fea2690cfd9cac716ca795)
+++ firmware/App/Services/Utilities.h (.../Utilities.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,20 +1,29 @@
-/*
- * Utilities.h
- *
- * Created on: Aug 4, 2024
- * Author: fw
- */
#ifndef __UTILITIES_H__
#define __UTILITIES_H__
#include "BLCommon.h"
+/**
+ * @defgroup Utilities Utilities
+ * @brief Utilities unit contains various utility functions.
+ *
+ * @addtogroup Utilities
+ * @{
+ */
+
+// ********** public definitions **********
+
#define MAX_CRC_CALC_DATA_SIZE 0x8000 ///< The maximum size of data for each CRC calculation.
+// ********** public function prototypes **********
+BOOL runFWIntegrityTest( void );
+
U32 crc32( U32 initialValue, U08 *address, U32 len );
-BOOL isCRCValid( U32 msgCRC, U32 calcCRC ); // TODO remove
+U16 crc16( U08 *address, U32 len );
+/**@}*/
+
#endif
Index: firmware/App/Tasks/TaskBG.c
===================================================================
diff -u -rf2652e85c8676d0356fea2690cfd9cac716ca795 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Tasks/TaskBG.c (.../TaskBG.c) (revision f2652e85c8676d0356fea2690cfd9cac716ca795)
+++ firmware/App/Tasks/TaskBG.c (.../TaskBG.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,36 +1,33 @@
-/*
- * TaskBG.c
- *
- * Created on: Jul 31, 2024
- * Author: fw
+
+#include "Download.h"
+#include "TaskBG.h"
+
+/**
+ * @addtogroup TaskBackground
+ * @{
*/
-#include "CommBuffers.h"
+// ********** private definitions **********
-static SW_UPDATE_BUFFER_STATUS_T bufferStatus;
+// ********** private data **********
+/*********************************************************************//**
+ * @brief
+ * The taskBackground function handles the idle Background Task loop.
+ * @details \b Inputs: none
+ * @details \b Outputs: Background task functions are called.
+ * @return none
+ *************************************************************************/
void taskBackground( void )
{
#ifndef _VECTORCAST_ // Cannot have infinite loop in unit test tool
while ( 1 )
#endif
{
- getSWUpdateBufferStatus( &bufferStatus );
+ execDownload();
- if ( ( TRUE == bufferStatus.isSWUpdateBufferReady ) && ( UPDATE_FIRMWARE == bufferStatus.dest ) )
- {
- U08 dataToWriteToFlash[ SW_UPDATE_FLASH_BUFFER_SIZE ];
-
- getSWUpdateBuffer( dataToWriteToFlash );
-
- // TODO prepare for a write to NV
- // TODO Disable/enable irq and fiq
- // TODO get ack/nack from NV data
- sendAckNackStatusFromFirmware( ACK, FALSE );
- clearSWUpdateBuffer( FALSE );
- //_disable_FIQ();
- //_enable_FIQ();
- }
+ // TODo add watchdog
}
}
+/**@}*/
Index: firmware/App/Tasks/TaskBG.h
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Tasks/TaskBG.h (.../TaskBG.h) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/App/Tasks/TaskBG.h (.../TaskBG.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,13 +1,22 @@
-/*
- * TaskBG.h
- *
- * Created on: Jul 31, 2024
- * Author: fw
- */
#ifndef __TASKBG_H__
#define __TASKBG_H__
+/**
+ * @defgroup TaskBackground TaskBackground
+ * @brief The background task is an infinite loop running in the background
+ * called by main() after initialization. The background task executes
+ * functions that may take a long time to complete or are very low priority.
+ * This includes non-volatile memory operations and watchdog management.
+ *
+ * @addtogroup TaskBackground
+ * @{
+ */
+
+// Public function prototypes
+
void taskBackground( void );
+/**@}*/
+
#endif
Index: firmware/App/Tasks/TaskGeneral.c
===================================================================
diff -u -r850f8042a02fd17ee53b8db24bc2e3d17bbb9c7f -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 850f8042a02fd17ee53b8db24bc2e3d17bbb9c7f)
+++ firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,14 +1,29 @@
-/*
- * TaskGeneral.c
- *
- * Created on: Jul 31, 2024
- * Author: fw
- */
#include "BLCommon.h"
+#include "OperationModes.h"
#include "TaskGeneral.h"
+/**
+ * @addtogroup TaskGeneral
+ * @{
+ */
+
+// ********** private data **********
+
+/*********************************************************************//**
+ * @brief
+ * The taskGeneral function handles the scheduled General Task interrupt.
+ * Calls the executive functions for most monitors and controllers, the
+ * operation modes.
+ * @details \b Inputs: none
+ * @details \b Outputs: Executive functions running in general task are called.
+ * @return none
+ *************************************************************************/
void taskGeneral( void )
{
- BOOL test;
+ execOperationModes();
+
+ // TODo add watchdog
}
+
+/**@}*/
Index: firmware/App/Tasks/TaskGeneral.h
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Tasks/TaskGeneral.h (.../TaskGeneral.h) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/App/Tasks/TaskGeneral.h (.../TaskGeneral.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,16 +1,22 @@
-/*
- * TaskGeneral.h
- *
- * Created on: Jul 31, 2024
- * Author: fw
- */
#ifndef __TASKGENERAL_H__
#define __TASKGENERAL_H__
-#define TASK_GENERAL_INTERVAL 50
+/**
+ * @defgroup TaskGeneral TaskGeneral
+ * @brief The general task is called by RTI interrupt every 50 ms and performs
+ * the bulk of sensor, actuator, mode, alarm, and communication operations.
+ *
+ * @addtogroup TaskGeneral
+ * @{
+ */
+// Public definitions
+
+// Public function prototypes
+
void taskGeneral( void );
+/**@}*/
#endif
Index: firmware/App/Tasks/TaskPriority.c
===================================================================
diff -u -rf2652e85c8676d0356fea2690cfd9cac716ca795 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision f2652e85c8676d0356fea2690cfd9cac716ca795)
+++ firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,16 +1,29 @@
-/*
- * TaskPriority.c
- *
- * Created on: Jul 31, 2024
- * Author: fw
- */
#include "BLCommon.h"
#include "CommBuffers.h"
+#include "FPGA.h"
#include "TaskPriority.h"
+/**
+ * @addtogroup TaskPriority
+ * @{
+ */
+
+// ********** private data **********
+
+/*********************************************************************//**
+ * @brief
+ * The taskPriority function handles the scheduled Priority Task interrupt.
+ * Calls the executive functions for FPGA.
+ * @details \b Inputs: none
+ * @details \b Outputs: Executive functions running in priority task are called.
+ * @return none
+ *************************************************************************/
void taskPriority( void )
{
- BOOL test;
+ execFPGA();
+
+ // TODo add watchdog
}
+/**@}*/
Index: firmware/App/Tasks/TaskPriority.h
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Tasks/TaskPriority.h (.../TaskPriority.h) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/App/Tasks/TaskPriority.h (.../TaskPriority.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,15 +1,25 @@
-/*
- * TaskPriority.h
- *
- * Created on: Jul 31, 2024
- * Author: fw
- */
#ifndef __TASKPRIORITY_H__
#define __TASKPRIORITY_H__
-#define TASK_PRIORITY_INTERVAL 10
+/**
+ * @defgroup TaskPriority TaskPriority
+ * @brief The priority task is called by RTI interrupt every 10 ms and performs
+ * high priority and/or urgent sensor/actuator processing as well as the
+ * interface to the FPGA.
+ *
+ * @addtogroup TaskPriority
+ * @{
+ */
+// Public definitions
+
+#define TASK_PRIORITY_INTERVAL (10) ///< Priority task timer interrupt interval (in ms).
+
+// Public function prototypes
+
void taskPriority( void );
+/**@}*/
+
#endif
Index: firmware/App/Tasks/TaskTimer.c
===================================================================
diff -u -r850f8042a02fd17ee53b8db24bc2e3d17bbb9c7f -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Tasks/TaskTimer.c (.../TaskTimer.c) (revision 850f8042a02fd17ee53b8db24bc2e3d17bbb9c7f)
+++ firmware/App/Tasks/TaskTimer.c (.../TaskTimer.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,16 +1,29 @@
-/*
- * TaskTimer.c
- *
- * Created on: Jul 31, 2024
- * Author: fw
- */
#include "BLCommon.h"
#include "TaskTimer.h"
+#include "Timers.h"
+/**
+ * @addtogroup TaskTimer
+ * @{
+ */
+
+// ********** private data **********
+
+/*********************************************************************//**
+ * @brief
+ * The taskTimer function handles the scheduled Timer Task interrupt.
+ * Calls the Timers executive to maintain a 1ms timer counter to
+ * support timer and timeout functions.
+ * @details \b Inputs: none
+ * @details \b Outputs: Executive function for Timers is called.
+ * @return none
+ *************************************************************************/
void taskTimer( void )
{
- BOOL tst;
+ incMSTimerCount();
+
+ // TODo add watchdog
}
-
+/**@}*/
Index: firmware/App/Tasks/TaskTimer.h
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/App/Tasks/TaskTimer.h (.../TaskTimer.h) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/App/Tasks/TaskTimer.h (.../TaskTimer.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,15 +1,22 @@
-/*
- * TaskTimer.h
- *
- * Created on: Jul 31, 2024
- * Author: fw
- */
#ifndef __TASKTIMER_H__
#define __TASKTIMER_H__
-#define TASK_TIMER_INTERVAL 1
+/**
+ * @defgroup TaskTimer TaskTimer
+ * @brief Timer task is called by RTI interrupt every 1 ms to update the
+ * millisecond timer counter.
+ *
+ * @addtogroup TaskTimer
+ * @{
+ */
+// Public definitions
+
+// Public function prototypes
+
void taskTimer( void );
+/**@}*/
+
#endif
Index: firmware/BL.dil
===================================================================
diff -u -rf2652e85c8676d0356fea2690cfd9cac716ca795 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/BL.dil (.../BL.dil) (revision f2652e85c8676d0356fea2690cfd9cac716ca795)
+++ firmware/BL.dil (.../BL.dil) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -1,4 +1,4 @@
-# RM46L852PGE 08/05/24 16:54:30
+# RM46L852PGE 09/23/24 12:06:34
#
ARCH=RM46L852PGE
#
@@ -57,7 +57,7 @@
DRIVER.SYSTEM.VAR.VIM_CHANNEL_98_INT_ENABLE.VALUE=0
DRIVER.SYSTEM.VAR.VIM_CHANNEL_20_INT_PRAGMA_ENABLE.VALUE=0
DRIVER.SYSTEM.VAR.VIM_CHANNEL_12_INT_PRAGMA_ENABLE.VALUE=0
-DRIVER.SYSTEM.VAR.VIM_CHANNEL_2_INT_TYPE.VALUE=FIQ
+DRIVER.SYSTEM.VAR.VIM_CHANNEL_2_INT_TYPE.VALUE=IRQ
DRIVER.SYSTEM.VAR.SAFETY_INIT_MIBSPI2_RAMPARITYCHECK_ENA.VALUE=0
DRIVER.SYSTEM.VAR.CRC_ENABLE.VALUE=0
DRIVER.SYSTEM.VAR.MIBSPI1_ENABLE.VALUE=1
@@ -139,7 +139,7 @@
DRIVER.SYSTEM.VAR.ECAP6_ENABLE.VALUE=1
DRIVER.SYSTEM.VAR.SCI_ENABLE.VALUE=1
DRIVER.SYSTEM.VAR.FLASH_DATA_1_WAIT_STATE_FREQ.VALUE=110.0
-DRIVER.SYSTEM.VAR.RAM_STACK_IRQ_BASE.VALUE=0x08003000
+DRIVER.SYSTEM.VAR.RAM_STACK_IRQ_BASE.VALUE=0x08002800
DRIVER.SYSTEM.VAR.VIM_CHANNEL_125_MAPPING.VALUE=125
DRIVER.SYSTEM.VAR.VIM_CHANNEL_117_MAPPING.VALUE=117
DRIVER.SYSTEM.VAR.VIM_CHANNEL_109_MAPPING.VALUE=109
@@ -407,7 +407,7 @@
DRIVER.SYSTEM.VAR.CORE_HANDLER_TABLE_UNDEF_ENABLE.VALUE=0
DRIVER.SYSTEM.VAR.VIM_CHANNEL_8_INT_PRAGMA_ENABLE.VALUE=0
DRIVER.SYSTEM.VAR.SAFETY_INIT_PBIST_SP_SELECTED.VALUE=0
-DRIVER.SYSTEM.VAR.RAM_STACK_ABORT_BASE.VALUE=0x08005000
+DRIVER.SYSTEM.VAR.RAM_STACK_ABORT_BASE.VALUE=0x08002c00
DRIVER.SYSTEM.VAR.VIM_CHANNEL_92_NAME.VALUE=etpwm2Interrupt
DRIVER.SYSTEM.VAR.VIM_CHANNEL_84_NAME.VALUE=phantomInterrupt
DRIVER.SYSTEM.VAR.VIM_CHANNEL_76_NAME.VALUE=phantomInterrupt
@@ -435,7 +435,7 @@
DRIVER.SYSTEM.VAR.CORE_PMU_COUNTER1_EVENT.VALUE=0x11
DRIVER.SYSTEM.VAR.EFUSE_SELFTEST_ENA.VALUE=0
DRIVER.SYSTEM.VAR.CLKT_AVCLK4_DOMAIN_DISABLE.VALUE=0
-DRIVER.SYSTEM.VAR.RAM_LINK_BASE_ADDRESS.VALUE=0x08005800
+DRIVER.SYSTEM.VAR.RAM_LINK_BASE_ADDRESS.VALUE=0x08003400
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_12_SUB_4_DISABLE.VALUE=0
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_2_SUB_7_DISABLE.VALUE=0
DRIVER.SYSTEM.VAR.VIM_CHANNEL_120_INT_ENABLE.VALUE=0
@@ -502,7 +502,7 @@
DRIVER.SYSTEM.VAR.VIM_CHANNEL_10_NAME.VALUE=het1HighLevelInterrupt
DRIVER.SYSTEM.VAR.PMM_MEM_PD2_STATEVALUE.VALUE=0x5
DRIVER.SYSTEM.VAR.ERRATA_WORKAROUND_9.VALUE=1
-DRIVER.SYSTEM.VAR.RAM_STACK_USER_LENGTH.VALUE=0x00001000
+DRIVER.SYSTEM.VAR.RAM_STACK_USER_LENGTH.VALUE=0x00002000
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_8_PERMISSION.VALUE=PRIV_RW_USER_RW_NOEXEC
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_10_SUB_2_DISABLE.VALUE=0
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_7_SUB_7_DISABLE.VALUE=0
@@ -549,14 +549,14 @@
DRIVER.SYSTEM.VAR.VIM_CHANNEL_85_NAME.VALUE=phantomInterrupt
DRIVER.SYSTEM.VAR.VIM_CHANNEL_77_NAME.VALUE=EMACTxIntISR
DRIVER.SYSTEM.VAR.VIM_CHANNEL_69_NAME.VALUE=phantomInterrupt
-DRIVER.SYSTEM.VAR.RAM_STACK_IRQ_LENGTH.VALUE=0x00002000
+DRIVER.SYSTEM.VAR.RAM_STACK_IRQ_LENGTH.VALUE=0x00000400
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_11_SUB_6_DISABLE.VALUE=0
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_7_SUB_0_DISABLE.VALUE=0
-DRIVER.SYSTEM.VAR.VIM_CHANNEL_2_INT_PRAGMA_ENABLE.VALUE=1
+DRIVER.SYSTEM.VAR.VIM_CHANNEL_2_INT_PRAGMA_ENABLE.VALUE=0
DRIVER.SYSTEM.VAR.CLKT_RTI2_POST_SOURCE.VALUE=VCLK
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_9_PERMISSION_VALUE.VALUE=0x1300
DRIVER.SYSTEM.VAR.VIM_CHANNEL_5_NAME.VALUE=rtiCompare3Interrupt
-DRIVER.SYSTEM.VAR.RAM_STACK_LENGTH.VALUE=0x00005800
+DRIVER.SYSTEM.VAR.RAM_STACK_LENGTH.VALUE=0x00003400
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_2_PERMISSION.VALUE=PRIV_RO_USER_RO_EXEC
DRIVER.SYSTEM.VAR.CLKT_LPO_BIAS.VALUE=true
DRIVER.SYSTEM.VAR.CLKT_AVCLK3_DIVIDER1.VALUE=4
@@ -628,7 +628,7 @@
DRIVER.SYSTEM.VAR.VIM_CHANNEL_103_NAME.VALUE=etpwm7TripZoneInterrupt
DRIVER.SYSTEM.VAR.PBIST_ALGO_16.VALUE=0
DRIVER.SYSTEM.VAR.CLKT_VCLK2_DIVIDER.VALUE=1
-DRIVER.SYSTEM.VAR.RAM_LINK_LENGTH.VALUE=0x0002a800
+DRIVER.SYSTEM.VAR.RAM_LINK_LENGTH.VALUE=0x0002cc00
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_11_END_ADDRESS.VALUE=0x0802ffff
DRIVER.SYSTEM.VAR.VIM_CHANNEL_30_INT_ENABLE.VALUE=0
DRIVER.SYSTEM.VAR.VIM_CHANNEL_22_INT_ENABLE.VALUE=0
@@ -793,7 +793,7 @@
DRIVER.SYSTEM.VAR.VIM_CHANNEL_29_MAPPING.VALUE=29
DRIVER.SYSTEM.VAR.ECLK_PORT_BIT0_DIR.VALUE=1
DRIVER.SYSTEM.VAR.FLASH_LENGTH.VALUE=0x00140000
-DRIVER.SYSTEM.VAR.RAM_STACK_FIQ_LENGTH.VALUE=0x00001000
+DRIVER.SYSTEM.VAR.RAM_STACK_FIQ_LENGTH.VALUE=0x00000400
DRIVER.SYSTEM.VAR.CLKT_EXT1_ENABLE.VALUE=FALSE
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_12_SUB_2_DISABLE.VALUE=0
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_9_SUB_7_DISABLE.VALUE=0
@@ -925,8 +925,8 @@
DRIVER.SYSTEM.VAR.SAFETY_INIT_DMA_DP_PBISTCHECK_ENA.VALUE=0x00000800
DRIVER.SYSTEM.VAR.HET_ENABLE.VALUE=1
DRIVER.SYSTEM.VAR.PBIST_ALGO_13_14.VALUE=0
-DRIVER.SYSTEM.VAR.RAM_STACK_UNDEF_BASE.VALUE=0x08005400
-DRIVER.SYSTEM.VAR.RAM_STACK_SVC_BASE.VALUE=0x08001000
+DRIVER.SYSTEM.VAR.RAM_STACK_UNDEF_BASE.VALUE=0x08003000
+DRIVER.SYSTEM.VAR.RAM_STACK_SVC_BASE.VALUE=0x08002000
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_9_TYPE.VALUE=DEVICE_NONSHAREABLE
DRIVER.SYSTEM.VAR.VIM_CHANNEL_99_INT_PRAGMA_ENABLE.VALUE=0
DRIVER.SYSTEM.VAR.VIM_CHANNEL_3_INT_TYPE.VALUE=IRQ
@@ -1134,7 +1134,7 @@
DRIVER.SYSTEM.VAR.RTI_ENABLE.VALUE=1
DRIVER.SYSTEM.VAR.STC_MAX_TIMEOUT.VALUE=0xFFFFFFFF
DRIVER.SYSTEM.VAR.CLKT_LPO_LOW_TRIM.VALUE=100.00
-DRIVER.SYSTEM.VAR.RAM_STACK_FIQ_BASE.VALUE=0x08002000
+DRIVER.SYSTEM.VAR.RAM_STACK_FIQ_BASE.VALUE=0x08002400
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_4_PERMISSION_VALUE.VALUE=0x0300
DRIVER.SYSTEM.VAR.VIM_CHANNEL_0_NAME.VALUE=esmHighInterrupt
DRIVER.SYSTEM.VAR.FLASH_BANK_LINK_LENGTH_7.VALUE=0x000010000
@@ -1184,7 +1184,7 @@
DRIVER.SYSTEM.VAR.VIM_CHANNEL_15_NAME.VALUE=adc1Group1Interrupt
DRIVER.SYSTEM.VAR.ERRATA_WORKAROUND_15.VALUE=1
DRIVER.SYSTEM.VAR.RAM_STACK_UNDEF_LENGTH.VALUE=0x00000400
-DRIVER.SYSTEM.VAR.RAM_STACK_SVC_LENGTH.VALUE=0x00001000
+DRIVER.SYSTEM.VAR.RAM_STACK_SVC_LENGTH.VALUE=0x00000400
DRIVER.SYSTEM.VAR.CLKT_LPO_TRIM_OTP_LOC.VALUE=0xF00801B4
DRIVER.SYSTEM.VAR.CORE_MPU_REGION_6_SUB_6_DISABLE.VALUE=0
DRIVER.SYSTEM.VAR.CORE_HANDLER_TABLE_UNDEF_ENTRY.VALUE=_undef
@@ -1723,7 +1723,7 @@
DRIVER.SCI.VAR.SCI_FEINTLVL.VALUE=0
DRIVER.SCI.VAR.SCILIN_EVENPARITY.VALUE=0
DRIVER.SCI.VAR.SCI_TXINTLVL.VALUE=0
-DRIVER.SCI.VAR.SCILIN_OEINTENA.VALUE=0
+DRIVER.SCI.VAR.SCILIN_OEINTENA.VALUE=1
DRIVER.SCI.VAR.SCILIN_PORT_BIT2_DOUT.VALUE=0
DRIVER.SCI.VAR.SCI_PORT_BIT1_DOUT.VALUE=0
DRIVER.SCI.VAR.SCI_PEINTENA.VALUE=0
@@ -1733,7 +1733,7 @@
DRIVER.SCI.VAR.SCI_PORT_BIT2_DOUT.VALUE=0
DRIVER.SCI.VAR.SCILIN_BASE.VALUE=0xFFF7E400
DRIVER.SCI.VAR.SCI_RXINTLVL.VALUE=0
-DRIVER.SCI.VAR.SCILIN_FEINTENA.VALUE=0
+DRIVER.SCI.VAR.SCILIN_FEINTENA.VALUE=1
DRIVER.SCI.VAR.SCI_PRESCALE.VALUE=55
DRIVER.SCI.VAR.SCILIN_OEINTLVL.VALUE=0
DRIVER.SCI.VAR.SCILIN_TXINTENA.VALUE=0
@@ -3852,7 +3852,7 @@
DRIVER.CAN.VAR.CAN_2_MESSAGE_14_ENA.VALUE=0x00000000
DRIVER.CAN.VAR.CAN_2_MESSAGE_9_ENA.VALUE=0x00000000
DRIVER.CAN.VAR.CAN_2_TQ.VALUE=250.000
-DRIVER.CAN.VAR.CAN_1_MESSAGE_7_BOOL_ENA.VALUE=0
+DRIVER.CAN.VAR.CAN_1_MESSAGE_7_BOOL_ENA.VALUE=1
DRIVER.CAN.VAR.CAN_1_BRPE.VALUE=0
DRIVER.CAN.VAR.CAN_3_MESSAGE_7_ID.VALUE=7
DRIVER.CAN.VAR.CAN_2_MESSAGE_4_RTR.VALUE=0x00000000
@@ -4503,7 +4503,7 @@
DRIVER.CAN.VAR.CAN_2_MESSAGE_36_BOOL_ENA.VALUE=0
DRIVER.CAN.VAR.CAN_2_MESSAGE_28_BOOL_ENA.VALUE=0
DRIVER.CAN.VAR.CAN_2_MESSAGE_1_INT_ENA.VALUE=0x00000000
-DRIVER.CAN.VAR.CAN_1_MESSAGE_7_ENA.VALUE=0x00000000
+DRIVER.CAN.VAR.CAN_1_MESSAGE_7_ENA.VALUE=0x80000000
DRIVER.CAN.VAR.CAN_3_MESSAGE_51_INT_LEVEL.VALUE=0x00000000
DRIVER.CAN.VAR.CAN_3_MESSAGE_43_INT_LEVEL.VALUE=0x00000000
DRIVER.CAN.VAR.CAN_3_MESSAGE_35_INT_LEVEL.VALUE=0x00000000
@@ -4524,7 +4524,7 @@
DRIVER.CAN.VAR.CAN_3_MESSAGE_15_EOB.VALUE=0x00000000
DRIVER.CAN.VAR.CAN_3_MESSAGE_15_DIR.VALUE=0x20000000
DRIVER.CAN.VAR.CAN_1_MESSAGE_7_EOB.VALUE=0x00000080
-DRIVER.CAN.VAR.CAN_1_MESSAGE_7_DIR.VALUE=0x00000000
+DRIVER.CAN.VAR.CAN_1_MESSAGE_7_DIR.VALUE=0x20000000
DRIVER.CAN.VAR.CAN_3_MESSAGE_41_INT_ENA.VALUE=0x00000000
DRIVER.CAN.VAR.CAN_3_MESSAGE_33_INT_ENA.VALUE=0x00000000
DRIVER.CAN.VAR.CAN_3_MESSAGE_30_BOOL_ENA.VALUE=0
@@ -4946,7 +4946,7 @@
DRIVER.CAN.VAR.CAN_3_MESSAGE_18_EOB.VALUE=0x00000000
DRIVER.CAN.VAR.CAN_3_MESSAGE_18_DIR.VALUE=0x20000000
DRIVER.CAN.VAR.CAN_3_MESSAGE_17_INT_ENA_REF.VALUE=0x00000000
-DRIVER.CAN.VAR.CAN_1_MESSAGE_7_INT_ENA_REF.VALUE=0x00000000
+DRIVER.CAN.VAR.CAN_1_MESSAGE_7_INT_ENA_REF.VALUE=0x00000001
DRIVER.CAN.VAR.CAN_3_MESSAGE_41_MASK.VALUE=0x000007FF
DRIVER.CAN.VAR.CAN_3_MESSAGE_33_MASK.VALUE=0x000007FF
DRIVER.CAN.VAR.CAN_3_MESSAGE_25_MASK.VALUE=0x000007FF
@@ -5249,7 +5249,7 @@
DRIVER.CAN.VAR.CAN_3_MESSAGE_6_MASK.VALUE=0x000007FF
DRIVER.CAN.VAR.CAN_2_MESSAGE_57_ENA.VALUE=0x00000000
DRIVER.CAN.VAR.CAN_2_MESSAGE_49_ENA.VALUE=0x00000000
-DRIVER.CAN.VAR.CAN_1_MESSAGE_7_INT_ENA.VALUE=0x00000000
+DRIVER.CAN.VAR.CAN_1_MESSAGE_7_INT_ENA.VALUE=0x00000800
DRIVER.CAN.VAR.CAN_1_MESSAGE_5_BOOL_ENA.VALUE=1
DRIVER.CAN.VAR.CAN_3_MESSAGE_59_INT_LEVEL.VALUE=0x00000000
DRIVER.CAN.VAR.CAN_2_MESSAGE_60_RTR.VALUE=0x00000000
Index: firmware/include/sci.h
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/include/sci.h (.../sci.h) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/include/sci.h (.../sci.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -165,8 +165,8 @@
|(uint32)((uint32)0U << 1U) \
|(uint32)((uint32)0U))
-#define SCILIN_SETINT_CONFIGVALUE ((uint32)((uint32)0U << 26U) \
- |(uint32)((uint32)0U << 25U) \
+#define SCILIN_SETINT_CONFIGVALUE ((uint32)((uint32)1U << 26U) \
+ |(uint32)((uint32)1U << 25U) \
|(uint32)((uint32)0U << 24U) \
|(uint32)((uint32)0U << 9U) \
|(uint32)((uint32)0U << 1U) \
Index: firmware/include/sys_core.h
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/include/sys_core.h (.../sys_core.h) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/include/sys_core.h (.../sys_core.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -54,6 +54,7 @@
#endif
/* USER CODE BEGIN (0) */
+void _copyAPI2RAM_(void);
/* USER CODE END */
/** @def USER_STACK_LENGTH
@@ -63,7 +64,7 @@
*
* @note: Use this macro for USER Mode Stack length (in bytes)
*/
-#define USER_STACK_LENGTH 0x00001000U
+#define USER_STACK_LENGTH 0x00002000U
/** @def SVC_STACK_LENGTH
* @brief SVC Mode Stack length (in bytes)
@@ -72,7 +73,7 @@
*
* @note: Use this macro for SVC Mode Stack length (in bytes)
*/
-#define SVC_STACK_LENGTH 0x00001000U
+#define SVC_STACK_LENGTH 0x00000400U
/** @def FIQ_STACK_LENGTH
* @brief FIQ Mode Stack length (in bytes)
@@ -81,7 +82,7 @@
*
* @note: Use this macro for FIQ Mode Stack length (in bytes)
*/
-#define FIQ_STACK_LENGTH 0x00001000U
+#define FIQ_STACK_LENGTH 0x00000400U
/** @def IRQ_STACK_LENGTH
* @brief IRQ Mode Stack length (in bytes)
@@ -90,7 +91,7 @@
*
* @note: Use this macro for IRQ Mode Stack length (in bytes)
*/
-#define IRQ_STACK_LENGTH 0x00002000U
+#define IRQ_STACK_LENGTH 0x00000400U
/** @def ABORT_STACK_LENGTH
* @brief ABORT Mode Stack length (in bytes)
Index: firmware/include/sys_vim.h
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/include/sys_vim.h (.../sys_vim.h) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/include/sys_vim.h (.../sys_vim.h) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -132,7 +132,7 @@
/* Configuration registers initial value */
#define VIM_FIRQPR0_CONFIGVALUE ( (uint32)((uint32)SYS_FIQ << 0U)\
| (uint32)((uint32)SYS_FIQ << 1U)\
- | (uint32)((uint32)SYS_FIQ << 2U)\
+ | (uint32)((uint32)SYS_IRQ << 2U)\
| (uint32)((uint32)SYS_IRQ << 3U)\
| (uint32)((uint32)SYS_IRQ << 4U)\
| (uint32)((uint32)SYS_IRQ << 5U)\
Index: firmware/source/can.c
===================================================================
diff -u -rf2652e85c8676d0356fea2690cfd9cac716ca795 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/source/can.c (.../can.c) (revision f2652e85c8676d0356fea2690cfd9cac716ca795)
+++ firmware/source/can.c (.../can.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -297,6 +297,25 @@
canREG1->IF2CMD = (uint8) 0xF8U;
canREG1->IF2NO = 6U;
+ /** - Initialize message 7
+ * - Wait until IF1 is ready for use
+ * - Set message mask
+ * - Set message control word
+ * - Set message arbitration
+ * - Set IF1 control byte
+ * - Set IF1 message number
+ */
+ /*SAFETYMCUSW 28 D MR:NA "Potentially infinite loop found - Hardware Status check for execution sequence" */
+ while ((canREG1->IF1STAT & 0x80U) ==0x80U)
+ {
+ } /* Wait */
+
+ canREG1->IF1MSK = 0xC0000000U | (uint32)((uint32)((uint32)0x000007FFU & (uint32)0x000007FFU) << (uint32)18U);
+ canREG1->IF1ARB = (uint32)0x80000000U | (uint32)0x00000000U | (uint32)0x20000000U | (uint32)((uint32)((uint32)0x607U & (uint32)0x000007FFU) << (uint32)18U);
+ canREG1->IF1MCTL = 0x00001000U | (uint32)0x00000800U | (uint32)0x00000000U | (uint32)0x00000080U | (uint32)8U;
+ canREG1->IF1CMD = (uint8) 0xF8U;
+ canREG1->IF1NO = 7U;
+
/** - Setup IF1 for data transmission
* - Wait until IF1 is ready for use
* - Set IF1 control byte
Index: firmware/source/rti.c
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/source/rti.c (.../rti.c) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/source/rti.c (.../rti.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -853,8 +853,6 @@
* RTI1 Compare 0 interrupt handler
*
*/
-#pragma CODE_STATE(rtiCompare0Interrupt, 32)
-#pragma INTERRUPT(rtiCompare0Interrupt, FIQ)
/* SourceId : RTI_SourceId_022 */
/* DesignId : RTI_DesignId_022 */
Index: firmware/source/sci.c
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/source/sci.c (.../sci.c) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/source/sci.c (.../sci.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -217,8 +217,8 @@
| (uint32)((uint32)0U); /* Break detect */
/** - set interrupt enable */
- scilinREG->SETINT = (uint32)((uint32)0U << 26U) /* Framing error */
- | (uint32)((uint32)0U << 25U) /* Overrun error */
+ scilinREG->SETINT = (uint32)((uint32)1U << 26U) /* Framing error */
+ | (uint32)((uint32)1U << 25U) /* Overrun error */
| (uint32)((uint32)0U << 24U) /* Parity error */
| (uint32)((uint32)0U << 9U) /* Receive */
| (uint32)((uint32)0U << 1U) /* Wakeup */
Index: firmware/source/sys_core.asm
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/source/sys_core.asm (.../sys_core.asm) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/source/sys_core.asm (.../sys_core.asm) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -160,12 +160,12 @@
ldr sp, userSp
bx lr
-userSp .word 0x08000000+0x00001000
-svcSp .word 0x08000000+0x00001000+0x00001000
-fiqSp .word 0x08000000+0x00001000+0x00001000+0x00001000
-irqSp .word 0x08000000+0x00001000+0x00001000+0x00001000+0x00002000
-abortSp .word 0x08000000+0x00001000+0x00001000+0x00001000+0x00002000+0x00000400
-undefSp .word 0x08000000+0x00001000+0x00001000+0x00001000+0x00002000+0x00000400+0x00000400
+userSp .word 0x08000000+0x00002000
+svcSp .word 0x08000000+0x00002000+0x00000400
+fiqSp .word 0x08000000+0x00002000+0x00000400+0x00000400
+irqSp .word 0x08000000+0x00002000+0x00000400+0x00000400+0x00000400
+abortSp .word 0x08000000+0x00002000+0x00000400+0x00000400+0x00000400+0x00000400
+undefSp .word 0x08000000+0x00002000+0x00000400+0x00000400+0x00000400+0x00000400+0x00000400
.endasmfunc
Index: firmware/source/sys_link.cmd
===================================================================
diff -u -r850f8042a02fd17ee53b8db24bc2e3d17bbb9c7f -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/source/sys_link.cmd (.../sys_link.cmd) (revision 850f8042a02fd17ee53b8db24bc2e3d17bbb9c7f)
+++ firmware/source/sys_link.cmd (.../sys_link.cmd) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -56,8 +56,8 @@
{
VECTORS (X) : origin=0x00000000 length=0x00000020
FLASH0 (RX) : origin=0x00000020 length=0x0013FFE0
- STACKS (RW) : origin=0x08000000 length=0x00005800
- RAM (RW) : origin=0x08005800 length=0x0002a800
+ STACKS (RW) : origin=0x08000000 length=0x00003400
+ RAM (RW) : origin=0x08003400 length=0x0002cc00
/* USER CODE BEGIN (2) */
/* USER CODE END */
@@ -90,6 +90,11 @@
/* USER CODE BEGIN (4) */
+ flashAPI:
+ {
+ NVDataMgmt.obj (.text)
+ --library= F021_API_CortexR4_LE_L2FMC_V3D16_NDS.lib (.text)
+ } palign=8 load = FLASH0, run = RAM, LOAD_START(apiLoadStart), RUN_START(apiRunStart), SIZE(apiLoadSize)
/* USER CODE END */
}
Index: firmware/source/sys_main.c
===================================================================
diff -u -r850f8042a02fd17ee53b8db24bc2e3d17bbb9c7f -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/source/sys_main.c (.../sys_main.c) (revision 850f8042a02fd17ee53b8db24bc2e3d17bbb9c7f)
+++ firmware/source/sys_main.c (.../sys_main.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -43,10 +43,6 @@
/* USER CODE BEGIN (0) */
-
-static void initProcessor( void );
-static void initSoftware( void );
-static void initTasks( void );
/* USER CODE END */
/* Include Files */
@@ -62,7 +58,12 @@
#include "BLCommon.h"
#include "CommBuffers.h"
+#include "Download.h"
+#include "FPGA.h"
#include "Interrupts.h"
+#include "NVDataMgmt.h"
+#include "OperationModes.h"
+#include "SystemComm.h"
#include "TaskBG.h"
#include "Timers.h"
/* USER CODE END */
@@ -76,6 +77,14 @@
*/
/* USER CODE BEGIN (2) */
+/*
+ * For reference:
+ * https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/403240/change-load-address-when-debugging-with-tm4c129cnczad
+ * https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1218850/rm46l852-booting-main-application-from-can-bootloader-results-in-prefetchentry-system-interrupt
+ */
+static void initProcessor( void );
+static void initSoftware( void );
+static void initTasks( void );
/* USER CODE END */
int main(void)
@@ -93,28 +102,55 @@
/* USER CODE BEGIN (4) */
+
+/*************************************************************************
+ * @brief initProcessor
+ * The initProcessor function initializes and configures the processor \n
+ * peripherals.
+ * @details Inputs: none
+ * @details Outputs: Processor peripherals initialized and configured.
+ * @return none
+ *************************************************************************/
static void initProcessor( void )
{
canInit();
sciInit();
dmaEnable();
}
+/*************************************************************************
+ * @brief initSoftware
+ * The initSoftware function calls all software unit initialization functions
+ * to initialize and configure the TD application.
+ * @details Inputs: none
+ * @details Outputs: All software units initialized.
+ * @return none
+ *************************************************************************/
static void initSoftware( void )
{
initCommBuffers();
+ initDownload();
+ initFPGA();
initInterrupts();
+ initNVDataMgmt();
+ initOperationModes();
+ initSystemComm();
initTimers();
}
+/*************************************************************************
+ * @brief initTasks
+ * The initTasks function sets up and starts the scheduled tasks.
+ * @details Inputs: none
+ * @details Outputs: Scheduled tasks set up and started.
+ * @return none
+ *************************************************************************/
static void initTasks( void )
{
// Initialize RTI to setup the 3 tasks
rtiInit();
rtiEnableNotification( rtiNOTIFICATION_COMPARE0 | rtiNOTIFICATION_COMPARE1 | rtiNOTIFICATION_COMPARE3 );
rtiStartCounter( rtiCOUNTER_BLOCK0 );
- // The timer task requires FIQ enabled
- _enable_FIQ();
// The general and priority tasks require IRQ enabled
_enable_IRQ();
}
Index: firmware/source/sys_startup.c
===================================================================
diff -u -r850f8042a02fd17ee53b8db24bc2e3d17bbb9c7f -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/source/sys_startup.c (.../sys_startup.c) (revision 850f8042a02fd17ee53b8db24bc2e3d17bbb9c7f)
+++ firmware/source/sys_startup.c (.../sys_startup.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -617,10 +617,10 @@
vimChannelMap( 3, 40, &rtiCompare1Interrupt );
vimChannelMap( 5, 64, &rtiCompare3Interrupt );
vimChannelMap( 13, 3, &linHighLevelInterrupt );
- vimChannelMap( 16, 16, &can1HighLevelInterrupt );
+ vimChannelMap( 16, 15, &can1HighLevelInterrupt );
vimChannelMap( 29, 13, &can1LowLevelInterrupt );
vimChannelMap( 40, 5, &dmaBTCAInterrupt );
- vimChannelMap( 64, 29, &sciHighLevelInterrupt );
+ vimChannelMap( 64, 16, &sciHighLevelInterrupt );
/* USER CODE END */
/* Configure system response to error conditions signaled to the ESM group1 */
@@ -629,6 +629,7 @@
/* initialize copy table */
__TI_auto_init();
/* USER CODE BEGIN (75) */
+ _copyAPI2RAM_();
/* USER CODE END */
/* call the application */
Index: firmware/source/sys_vim.c
===================================================================
diff -u -rabb9687e52d9db5df1abe7626ba04a6d431ba823 -r0c085209bea23f66011059a7c19796c1e4b246fa
--- firmware/source/sys_vim.c (.../sys_vim.c) (revision abb9687e52d9db5df1abe7626ba04a6d431ba823)
+++ firmware/source/sys_vim.c (.../sys_vim.c) (revision 0c085209bea23f66011059a7c19796c1e4b246fa)
@@ -229,7 +229,7 @@
/* set IRQ/FIQ priorities */
vimREG->FIRQPR0 = (uint32)((uint32)SYS_FIQ << 0U)
| (uint32)((uint32)SYS_FIQ << 1U)
- | (uint32)((uint32)SYS_FIQ << 2U)
+ | (uint32)((uint32)SYS_IRQ << 2U)
| (uint32)((uint32)SYS_IRQ << 3U)
| (uint32)((uint32)SYS_IRQ << 4U)
| (uint32)((uint32)SYS_IRQ << 5U)