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)