//*****************************************************************************
// (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 Bmg.c
///
/// \brief Functions for AL- specific initialization:
/// - mounting side LEFT /RIGHT
/// - EFT entry condition --> Normal Mode or "WaitForRAMAppl"
///
/// \descr
///
/// Additional information can be found in the design description (Link:
/// MDDD)
///
/// \author Cosmin Cojocaru (f11501c)
/// mailTo:constantin-cosmin.cojocaru(at)marelli.com
//-----------------------------------------------------------------------------
#include "Bmg.h"
#include "ShaData.h"
#include
#include
#ifdef BMG_DETECT_MOUNTING_SIDE
static uint8 Bmg_MountingSideLeftCounter = 0U;
static uint8 Bmg_MountingSideRightCounter = 0U;
static uint8 Bmg_MountingSideUnknown = 0U;
#endif //BMG_DETECT_MOUNTING_SIDE
#ifdef BMG_DETECT_ENTRY_CONDITION
static uint8 Bmg_WaitForRAMApplCounter = 0U;
#endif //BMG_DETECT_ENTRY_CONDITION
static TIMER Bmg_SampeRateTimer;
//function prototypes
#ifdef BMG_DETECT_ENTRY_CONDITION
static void Bmg_CheckWaitForRAMAppl(uint16 adcRawVal1, uint16 adcRawVal2, uint16 adcRawVal3);
#ifndef BMG_IS_ENTRY_COND_VAL1
#error BMG_IS_ENTRY_COND_VAL1 must be set in BmgCgf.h
#endif //BMG_IS_ENTRY_COND_VAL1
#ifndef BMG_IS_ENTRY_COND_VAL2
#define BMG_IS_ENTRY_COND_VAL2(x) (1U)
#endif //BMG_IS_ENTRY_COND_VAL2
#ifndef BMG_IS_ENTRY_COND_VAL3
#define BMG_IS_ENTRY_COND_VAL3(x) (1U)
#endif //BMG_IS_ENTRY_COND_VAL3
#endif //BMG_DETECT_ENTRY_CONDITION
#ifdef BMG_DETECT_MOUNTING_SIDE
static void Bmg_CheckMountingSide(uint16 adcRawVal, uint16 adcRawValKl30);
#endif //BMG_DETECT_MOUNTING_SIDE
//-----------------------------------------------------------------------------
/// \brief Bmg_BootStatus_detection
///
/// \descr Function which is performing the reading of ADC channels for mounting side and EFT entry condition
/// and increments it's specific counter according to the voltage tresholds
///
/// \param void
///
/// \return void
//-----------------------------------------------------------------------------
static void Bmg_BootStatus_detection(void)
{
uint8 u8_Index;
#ifdef BMG_DETECT_MOUNTING_SIDE
uint16 u16_RawMoutingSide = 0U;
#endif //BMG_DETECT_MOUNTING_SIDE
#ifdef BMG_DETECT_ENTRY_CONDITION
uint16 u16_RawEntryCondVal1 = 0U;
uint16 u16_RawEntryCondVal2 = 0U;
uint16 u16_RawEntryCondVal3 = 0U;
#endif //BMG_DETECT_ENTRY_CONDITION
#ifdef BMG_DETECT_MOUNTING_SIDE
Bmg_MountingSideLeftCounter = 0U;
Bmg_MountingSideRightCounter = 0U;
Bmg_MountingSideUnknown = 0U;
#endif //BMG_DETECT_MOUNTING_SIDE
#ifdef BMG_DETECT_ENTRY_CONDITION
Bmg_WaitForRAMApplCounter = 0U;
#endif //BMG_DETECT_ENTRY_CONDITION
for( u8_Index = (uint8)0; u8_Index < BMG_NR_SAMPES; u8_Index++ )
{
//set sample rate time
Bmg_SampeRateTimer = TimerStart( BMG_SAMPLE_RATE );
#ifdef BMG_DETECT_MOUNTING_SIDE
(void)Adc_ReadGroup(BMG_MOUNTING_SIDE_ADC_INDEX, &u16_RawMoutingSide);
#endif //BMG_DETECT_MOUNTING_SIDE
#ifdef BMG_DETECT_ENTRY_CONDITION
#ifdef BMG_ENTRY_COND_PIN_VAL1_INDEX
(void)Adc_ReadGroup(BMG_ENTRY_COND_PIN_VAL1_INDEX, &u16_RawEntryCondVal1);
#else
#error BMG_ENTRY_COND_PIN_VAL1_INDEX must be set in BmgCgf.h
#endif //BMG_ENTRY_COND_PIN_VAL1_INDEX
#ifdef BMG_ENTRY_COND_PIN_VAL2_INDEX
(void)Adc_ReadGroup(BMG_ENTRY_COND_PIN_VAL2_INDEX, &u16_RawEntryCondVal2);
#endif //BMG_ENTRY_COND_PIN_VAL2_INDEX
#ifdef BMG_ENTRY_COND_PIN_VAL3_INDEX
(void)Adc_ReadGroup(BMG_ENTRY_COND_PIN_VAL3_INDEX, &u16_RawEntryCondVal3);
#endif //BMG_ENTRY_COND_PIN_VAL3_INDEX
#endif //BMG_DETECT_ENTRY_CONDITION
//check results
#ifdef BMG_DETECT_MOUNTING_SIDE
Bmg_CheckMountingSide(u16_RawMoutingSide, u16_RawMoutingSide);
#endif //BMG_DETECT_MOUNTING_SIDE
#ifdef BMG_DETECT_ENTRY_CONDITION
Bmg_CheckWaitForRAMAppl(u16_RawEntryCondVal1, u16_RawEntryCondVal2, u16_RawEntryCondVal3);
#endif //BMG_DETECT_ENTRY_CONDITION
//wait for sample rate timing
while ( TimerTimeout( Bmg_SampeRateTimer ) == 0u ) {;}
}
}
#ifdef BMG_DETECT_MOUNTING_SIDE
//-----------------------------------------------------------------------------
/// \brief Bmg_CheckMountingSide
///
/// \descr Function used to perform the increment of mounting side specific counters based on voltage tresholds
///
/// \param adcRawVal: RAW ADC conversion value for LR detection assigned channel
/// \param adcRawValKl30: RAW ADC conversion value for KL30 assigned channel(parameter not used)
///
/// \return void
//-----------------------------------------------------------------------------
static void Bmg_CheckMountingSide(uint16 adcRawVal, uint16 adcRawValKl30)
{
// if value under the detection threshold left side is detected
if( BMG_IS_MOUNTING_SIDE_LEFT(adcRawVal))
{
Bmg_MountingSideLeftCounter++;
}
else if(BMG_IS_MOUNTING_SIDE_RIGHT(adcRawVal))
{
Bmg_MountingSideRightCounter++;
}
else
{
Bmg_MountingSideUnknown++;
}
(void)adcRawValKl30; // parameter is unused, avoid any warnings
}
//-----------------------------------------------------------------------------
/// \brief Bmg_BootStatus_isMountingSideLeft
///
/// \descr Function which detects Left mounting side based on it's counter value
///
/// \param void
///
/// \return boolean: TRUE - indicates that mounting side is on Left
/// FALSE - indicates that mounting side is on different side than Left(Righ or Unknown)
///
//-----------------------------------------------------------------------------
static boolean Bmg_BootStatus_isMountingSideLeft(void)
{
//if most of the samples match the condition returns true
return ( (Bmg_MountingSideLeftCounter > BMG_MAJORITY_OF_COUNTS_CHECKS) ? TRUE : FALSE );
}
//-----------------------------------------------------------------------------
/// \brief Bmg_BootStatus_isMountingSideRight
///
/// \descr Function which detects Right mounting side based on it's counter value
///
/// \param void
///
/// \return boolean: TRUE - indicates that mounting side is on Right
/// FALSE - indicates that mounting side is on different side than Right(Left or Unknown)
///
//-----------------------------------------------------------------------------
static boolean Bmg_BootStatus_isMountingSideRight(void)
{
//if most of the samples match the condition returns true
return ( (Bmg_MountingSideRightCounter > BMG_MAJORITY_OF_COUNTS_CHECKS) ? TRUE : FALSE );
}
#endif //BMG_DETECT_MOUNTING_SIDE
#ifdef BMG_DETECT_ENTRY_CONDITION
//-----------------------------------------------------------------------------
/// \brief Bmg_CheckWaitForRAMAppl
///
/// \descr Function used to perform the increment of EFT entry condition specific counter based on voltage tresholds
///
/// \param adcRawVal1: RAW ADC conversion value for NTC0 assigned channel
/// \param adcRawVal2: RAW ADC conversion value for NTC1 assigned channel
/// \param adcRawVal3: RAW ADC conversion value for NTC2 assigned channel
///
/// \return void
//-----------------------------------------------------------------------------
static void Bmg_CheckWaitForRAMAppl(uint16 adcRawVal1, uint16 adcRawVal2, uint16 adcRawVal3)
{
// all three defined condition must match to detect the entry condititon
if ( ( BMG_IS_ENTRY_COND_VAL1( adcRawVal1 ) )
&& ( BMG_IS_ENTRY_COND_VAL2( adcRawVal2 ) )
&& ( BMG_IS_ENTRY_COND_VAL3( adcRawVal3 ) ) )
{
Bmg_WaitForRAMApplCounter++;
}
else
{
// no valid voltage value to met the EFT entry condition, skip incrementing the counter
}
}
//-----------------------------------------------------------------------------
/// \brief Bmg_BootStatus_waitForRAMAppl
///
/// \descr Function which detects EFT operating mode based on it's counter value
///
/// \param void
///
/// \return boolean: TRUE - indicates that PBL is running in EFT operating mode
/// FALSE - indicates that PBL is running in normal operating mode
//-----------------------------------------------------------------------------
static boolean Bmg_BootStatus_waitForRAMAppl(void)
{
//if most of the samples match the condition returns true
return ( (Bmg_WaitForRAMApplCounter > BMG_MAJORITY_OF_COUNTS_CHECKS) ? TRUE : FALSE );
}
//-----------------------------------------------------------------------------
/// \brief start_app
///
/// \descr Function used to modify the CPU program counter to start executing instructions from a designated address
///
/// \param void
///
/// \return void
//-----------------------------------------------------------------------------
static void __attribute__((naked)) start_app(uint32 pc, uint32 sp) // PRQA S 3206 1 // pc and sp params are actually used through assembly instructions
{
__asm(" \n\
msr msp, r1 /* load r1 into MSP */\n\
bx r0 /* branch to the address at r0 */\n\
");
}// PRQA S 5334 3 // function not empty, assembly section code is used inside it
//-----------------------------------------------------------------------------
/// \brief Bmg_JumpToApplication
///
/// \descr Function used to jump to FBL start vector. This function will be called after execution of PBL SW, passing the handle to other SW applications
///
/// \param void
///
/// \return void
//-----------------------------------------------------------------------------
static void Bmg_JumpToApplication(void)
{
//Chage value of CM0P_SCS_VTOR
//PRQA S 306 1 //used as an adress
uint32* CM4_SCS_VTOR = (uint32*)((uint32)0xE000ED08UL);
const volatile uint32* FBL_VALID_PTR = (const volatile uint32*)((uint32)BMG_FBL_VALID_FLAG_ADDR);
/* Check if FBL flag is valid */
if (*FBL_VALID_PTR == BMG_FBL_VALID_FLAG_VALUE)
{
*CM4_SCS_VTOR = BMG_FBL_START_ADDR;
}
else /* No valid FBL flag detected, jump in FBL updater */
{
*CM4_SCS_VTOR = BMG_FBL_UPDATER_START_ADDR;
}
// PRQA S 306 1 //correct cast
const uint32* pc = (uint32*)(*CM4_SCS_VTOR + 4U);
// PRQA S 306 1 //correct cast
const uint32* sp = (uint32*)(*CM4_SCS_VTOR);
start_app(*pc, *sp);
}
//-----------------------------------------------------------------------------
/// \brief Bmg_Run
///
/// \descr Function which sets the mounting side pattern values in the shared data memory and detects the operating mode of PBL SW
///
/// \param void
///
/// \return void
//-----------------------------------------------------------------------------
void Bmg_Run(void)
{
//Initialize Mounting side with UNKNOWN
ShaData.MountingSide = EcuMountingSide_UNKNOWN.Code;
//perform the reading of ADC channels and increment the mounting side and enty condition counters according to voltage tresholds
Bmg_BootStatus_detection();
//check if mounting side is Left and write to shared data
if (Bmg_BootStatus_isMountingSideLeft() != 0u)
{
ShaData.MountingSide = EcuMountingSide_LEFT.Code;
}
//check if mounting side is Right and write to shared data
else if (Bmg_BootStatus_isMountingSideRight() != 0u)
{
ShaData.MountingSide = EcuMountingSide_RIGHT.Code;
}
//no Left or Right side detected, write unknown to shared data
else
{
ShaData.MountingSide = EcuMountingSide_UNKNOWN.Code;
}
//check for EFT entry condition
if (Bmg_BootStatus_waitForRAMAppl() != 0u)
{
//start OS and wait for can messages to load AL flash software into memory
OsSchedulerStartOs();
}
else
{
//jump in APP if EFT entry condition is not satisfied
Bmg_JumpToApplication();
}
//this code should not be reached
while (1) { ; }
}
#endif //BMG_DETECT_ENTRY_CONDITION
// EOF