//*****************************************************************************
// (C) Automotive Lighting Reutlingen GmbH
// Tuebinger Strasse 123, 72762 Reutlingen, Germany
//
// Automotive Lighting Reutlingen GmbH owns all the rights to this work.
// This work shall not be copied, reproduced, used, modified, transferred
// or its information shall not be disclosed without the prior written
// authorization of Automotive Lighting Reutlingen GmbH.
//*****************************************************************************
//-----------------------------------------------------------------------------
/// \file ApplCmd.c
///
/// \brief
///
/// \descr
///
/// Additional information can be found in the design description (Link:
/// MDDD)
///
/// \author Heusel Johannes ALDE-RT/EEG-PM2 (F89037A)
/// mailTo:johannes.heusel(at)al-lighting.com
//-----------------------------------------------------------------------------
//=============================================================================
// Includes
//=============================================================================
// PRQA S 306 EOF // Direct memory access required
#include /* memcpy, memcmp, ... */
#include
#include
#include
#include
#include "ApplCmd_AlFlasher.h"
//=============================================================================
//typedefs
//=============================================================================
typedef void(*function_type)(void);
//=============================================================================
//setting section for EcuInformation
//=============================================================================
//#pragma segment DATA=USER_DATA ????no section at the moment. Usage of this feature unclear.
static uint32 EftEcuInformation;
// #pragma segment DATA=DATA ??????
//=============================================================================
// Variable declaration extern
//=============================================================================
//extern char __ghsbegin_SBL_AREA[], __ghsend_SBL_AREA[];
//=============================================================================
// Variable declaration intern
//=============================================================================
static boolean boCrcOk = FALSE;
//=============================================================================
// function prototypes internal
//=============================================================================
static uint32 ApplCmd_ByteArrayToUint32(const uint8* data, boolean LSBfirst);
static uint8 ApplCmd_Uint32ToByteArray(uint8* dest, const uint32 src, boolean LSBfirst);
//=============================================================================
// Public functions definition
//=============================================================================
//-----------------------------------------------------------------------------
/// \brief
///
/// \descr
///
/// \param pMsgContext
///
/// \return uint8
//-----------------------------------------------------------------------------
// PRQA S 1503 2 // not used at the moment
// PRQA S 3408 1 // It is actually being declared using macros
uint8 ApplCmd_AlFlasher_CheckKey(MsgContextType *const pMsgContext)
{
uint8 ret = 0x31u; /*DCM_E_REQUESTOUTOFRANGE*/
static const uint8 Key[5] = { 0xF8, 0x3F, 0x82, 0xF5, 0x1E };
if (memcmp(pMsgContext->reqData, Key, (uint8)sizeof(Key)) == (int)0)
{
boLoginActivated = TRUE;
SBC_disable_watchdog();
ret = 0x00u;
}
return ret;
}
//-----------------------------------------------------------------------------
/// \brief
///
/// \descr
///
/// \param pMsgContext
///
/// \return uint8
//-----------------------------------------------------------------------------
// PRQA S 1503 2 // not used at the moment
// PRQA S 3408 1 // It is actually being declared using macros
uint8 ApplCmd_AlFlasher_GetECUinfo(MsgContextType *const pMsgContext)
{
uint8 ret;
// BB FE VV(MSB) VV VV VV(LSB)
if (pMsgContext->reqDataLen != 0u)
{
ret = 0x13u;/*DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT*/
}
else
{
// BB FF
pMsgContext->resDataLen = ApplCmd_Uint32ToByteArray(&pMsgContext->resData[0], EftEcuInformation, FALSE);
ret = 0;
}
return ret;
}
//-----------------------------------------------------------------------------
/// \brief
///
/// \descr
///
/// \param pMsgContext
///
/// \return uint8
//-----------------------------------------------------------------------------
// PRQA S 1503 2 // not used at the moment
// PRQA S 3408 1 // It is actually being declared using macros
uint8 ApplCmd_AlFlasher_SetECUinfo(MsgContextType *const pMsgContext)
{
uint8 ret;
// BB FE VV(MSB) VV VV VV(LSB)
if (pMsgContext->reqDataLen != 4u)
{
ret = 0x13u;/*DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT*/
}
else
{
EftEcuInformation = ApplCmd_ByteArrayToUint32(&pMsgContext->reqData[0], FALSE);
ret = 0;
}
return ret;
}
//-----------------------------------------------------------------------------
/// \brief
///
/// \descr
///
/// \param pMsgContext
///
/// \return uint8
//-----------------------------------------------------------------------------
// PRQA S 1503 2 // not used at the moment
// PRQA S 3408 1 // It is actually being declared using macros
uint8 ApplCmd_AlFlasher_GetSetECUinfo(MsgContextType *const pMsgContext)
{
uint8 ret = 0x31u; /*DCM_E_REQUESTOUTOFRANGE*/
switch (pMsgContext->reqData[0])
{
case 0xFEU: // Set EcuInfo
{
// BB FE VV(MSB) VV VV VV(LSB)
if (pMsgContext->reqDataLen != 5u)
{
ret = 0x13u;/*DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT*/
}
else
{
EftEcuInformation = ApplCmd_ByteArrayToUint32(&pMsgContext->reqData[1], FALSE);
ret = 0;
}
}
break;
case 0xFFU: // Get EcuInfo
{
// BB FF
pMsgContext->resDataLen = ApplCmd_Uint32ToByteArray(&pMsgContext->resData[0], EftEcuInformation, FALSE);
ret = 0;
}
break;
default:
break;
}
return ret;
}
//-----------------------------------------------------------------------------
/// \brief
///
/// \descr
///
/// \param pMsgContext
///
/// \return uint8
//-----------------------------------------------------------------------------
// PRQA S 1503 2 // not used at the moment
// PRQA S 3408 1 // It is actually being declared using macros
uint8 ApplCmd_AlFlasher_DownloadToRam(MsgContextType *const pMsgContext)
{
#define APPLCMD_0xBD_DATA_OFFSET (4U)
uint8 ret = 0x31u;/*DCM_E_REQUESTOUTOFRANGE*/
const uint32 Dest = ApplCmd_ByteArrayToUint32(&pMsgContext->reqData[0], FALSE);
const uint32 Source = (uint32)&pMsgContext->reqData[APPLCMD_0xBD_DATA_OFFSET];
const uint16 unNumOfBytes = pMsgContext->reqDataLen - APPLCMD_0xBD_DATA_OFFSET;
#undef APPLCMD_0xBD_DATA_OFFSET
//set response to defined state
pMsgContext->resData[0] = 0u;
pMsgContext->resDataLen = 0u;
#ifndef UNIT_TEST
//check for correct download area
if (((uint32)(Dest + unNumOfBytes) <= (uint32)(APPLCMD_ALFLASHER_DOWNLOAD2RAM_END))
&& (Dest >= (uint32)(APPLCMD_ALFLASHER_DOWNLOAD2RAM_BEGIN)))
{
(void)memcpy((void*)Dest, (const void*)Source, (size_t)unNumOfBytes);
ret = 0x0;
}
#endif // !UNIT_TEST
return ret;
}
//-----------------------------------------------------------------------------
/// \brief
///
/// \descr
///
/// \param pMsgContext
///
/// \return uint8
//-----------------------------------------------------------------------------
// PRQA S 1503 2 // not used at the moment
// PRQA S 3408 1 // It is actually being declared using macros
uint8 ApplCmd_AlFlasher_CalcChecksum(MsgContextType *const pMsgContext)
{
uint8 ret = 0x31u;/*DCM_E_REQUESTOUTOFRANGE*/
if (pMsgContext->reqDataLen == 8u)
{
const uint32 unStartAddr = ApplCmd_ByteArrayToUint32(&pMsgContext->reqData[0], FALSE);
const uint32 Length = ApplCmd_ByteArrayToUint32(&pMsgContext->reqData[4], FALSE);
uint32 crc32 = Crc_CalculateCRC32_Vector_AUTOSAR((uint8 *)unStartAddr, Length, 0xFFFFFFFFuL, TRUE);
pMsgContext->resDataLen = ApplCmd_Uint32ToByteArray(&pMsgContext->resData[0], crc32, TRUE);
crc32 = ApplCmd_ByteArrayToUint32(&pMsgContext->resData[0], FALSE);
#ifndef UNIT_TEST
if (crc32 == (*(uint32*)(unStartAddr + Length)))
{
boCrcOk = TRUE;
}
ret = 0x00u;
Can_Cycle_SetDownloadIsInProgress(FALSE);
#endif // !UNIT_TEST
}
return ret;
}
//-----------------------------------------------------------------------------
/// \brief
///
/// \descr
///
/// \param pMsgContext
///
/// \return uint8
//-----------------------------------------------------------------------------
// PRQA S 1503 2 // not used at the moment
// PRQA S 3408 1 // It is actually being declared using macros
uint8 ApplCmd_AlFlasher_Jump2RamAppl(MsgContextType *const pMsgContext)
{
uint8 ret = 0x31u;/*DCM_E_REQUESTOUTOFRANGE*/
if (boCrcOk == FALSE)
{
ret = 0x10u;/*DCM_E_GENERALREJECT*/
}
else if (pMsgContext->reqData[0] == 0x1U) // PAV mode
{
//Get the location of the startup code starting address in "emulated" ROM (RAM used as ROM for the RAM applications).
uint32 * u32StartupCodeStartingAddress = (uint32 *)(4U + ApplCmd_ByteArrayToUint32(&pMsgContext->reqData[1], FALSE));
//Use the location to read the startup code starting address.
const uint32 u32JumpAddr = (uint32)*u32StartupCodeStartingAddress;
//Chage value of CM0P_SCS_VTOR
uint32 * CM0P_SCS_VTOR = (uint32 *)0xE000ED08U;
#ifndef UNIT_TEST
*CM0P_SCS_VTOR = ApplCmd_ByteArrayToUint32(&pMsgContext->reqData[1], FALSE);
//lint -e611 Suspicious cast...
//lint -e740 Unusual pointer cast (incompatible indirect types)...
//Jump to startup code starting address. LSB must be set to b1 to signal the ARM CortexM0+ core we are using the thumb instruction set.
((function_type)(u32JumpAddr | 0x1U))(); // PRQA S 305 1 // Cast from uint32 to function pointer type is required.
//lint +e611
//lint +e740
#endif // !UNIT_TEST
ret = 0x0;
}
else
{
// do nothing
}
return ret;
}
//-----------------------------------------------------------------------------
/// \brief
///
/// \descr
///
/// \param dest
/// \param src
/// \param LSBfirst
///
/// \return uint8
//-----------------------------------------------------------------------------
//=============================================================================
// Private functions declaration
//=============================================================================
static uint8 ApplCmd_Uint32ToByteArray(uint8* dest, const uint32 src, boolean LSBfirst)
{
if (LSBfirst == TRUE)
{
dest[3] = (uint8)(src >> 24u);
dest[2] = (uint8)(src >> 16u);
dest[1] = (uint8)(src >> 8u);
dest[0] = (uint8)(src);
}
else
{
dest[0] = (uint8)(src >> 24u);
dest[1] = (uint8)(src >> 16u);
dest[2] = (uint8)(src >> 8u);
dest[3] = (uint8)(src);
}
return 4u;
}
//-----------------------------------------------------------------------------
/// \brief
///
/// \descr
///
/// \param data
/// \param LSBfirst
///
/// \return uint32
//-----------------------------------------------------------------------------
static uint32 ApplCmd_ByteArrayToUint32(const uint8* data, boolean LSBfirst)
{
uint32 ulValue32;
if (LSBfirst == TRUE)
{
ulValue32 = (((uint32)data[3] << 24u)
| ((uint32)data[2] << 16u)
| ((uint32)data[1] << 8u)
| ((uint32)data[0]));
}
else
{
ulValue32 = (((uint32)data[0] << 24u)
| ((uint32)data[1] << 16u)
| ((uint32)data[2] << 8u)
| ((uint32)data[3]));
}
return ulValue32;
}