fix: add watchdog support and MCU recovery logic for fault scenarios
- Added watchdog initialization and periodic refresh in application code. - Implemented software reset trigger when code enters Default_Handler (catch-all for unhandled interrupts). - Improved FOTA robustness: added logic to restore code execution and CAN communication when the IOT module resets unexpectedly during firmware update. - Verified recovery flow and communication reinitialization after system reset scenarios.stable
parent
6f5919c517
commit
6b74e25455
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef CORE_INCLUDE_IVEC_MCAL_WDT_H_
|
||||
#define CORE_INCLUDE_IVEC_MCAL_WDT_H_
|
||||
|
||||
#include "../utils/utils.h"
|
||||
|
||||
IVEC_McalStatus_e xMCAL_WatchdogInit(MCAL_WWDT_TIMER timer);
|
||||
|
||||
IVEC_McalStatus_e xMCAL_WatchdogDeInit(void);
|
||||
|
||||
IVEC_McalStatus_e xMCAL_WatchdogReset(void);
|
||||
|
||||
#endif /* CORE_INCLUDE_IVEC_MCAL_WDT_H_ */
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
#include "ivec_mcal_wdt.h"
|
||||
|
||||
static volatile bool b_WDInitFlag;
|
||||
|
||||
|
||||
IVEC_McalStatus_e xMCAL_WatchdogInit(MCAL_WWDT_TIMER timer)
|
||||
{
|
||||
DL_WWDT_CLOCK_DIVIDE Clk_Div;
|
||||
DL_WWDT_TIMER_PERIOD Tmr_Per;
|
||||
|
||||
assert(WATCHDOG_TIMER != NULL);
|
||||
|
||||
switch(timer)
|
||||
{
|
||||
case MCAL_WDT_1_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_1;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_15_BITS;
|
||||
break;
|
||||
case MCAL_WDT_2_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_2;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_15_BITS;
|
||||
break;
|
||||
case MCAL_WDT_3_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_3;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_15_BITS;
|
||||
break;
|
||||
case MCAL_WDT_4_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_4;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_15_BITS;
|
||||
break;
|
||||
case MCAL_WDT_5_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_5;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_15_BITS;
|
||||
break;
|
||||
case MCAL_WDT_6_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_6;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_15_BITS;
|
||||
break;
|
||||
case MCAL_WDT_7_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_7;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_15_BITS;
|
||||
break;
|
||||
case MCAL_WDT_8_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_8;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_15_BITS;
|
||||
break;
|
||||
case MCAL_WDT_16_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_2;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_18_BITS;
|
||||
break;
|
||||
case MCAL_WDT_24_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_3;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_18_BITS;
|
||||
break;
|
||||
case MCAL_WDT_32_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_4;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_18_BITS;
|
||||
break;
|
||||
case MCAL_WDT_40_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_5;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_18_BITS;
|
||||
break;
|
||||
case MCAL_WDT_48_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_6;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_18_BITS;
|
||||
break;
|
||||
case MCAL_WDT_56_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_7;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_18_BITS;
|
||||
break;
|
||||
case MCAL_WDT_64_SEC_TIMER:
|
||||
Clk_Div = DL_WWDT_CLOCK_DIVIDE_8;
|
||||
Tmr_Per = DL_WWDT_TIMER_PERIOD_18_BITS;
|
||||
break;
|
||||
default: return IVEC_MCAL_STATUS_INIT_FAIL;
|
||||
}
|
||||
DL_WWDT_disablePower(WATCHDOG_TIMER);
|
||||
if(b_WDInitFlag == false)
|
||||
{
|
||||
/* Set Window0 as active window */
|
||||
DL_WWDT_setActiveWindow(WATCHDOG_TIMER, DL_WWDT_WINDOW0);
|
||||
|
||||
DL_WWDT_initWatchdogMode(WATCHDOG_TIMER, Clk_Div,Tmr_Per, DL_WWDT_RUN_IN_SLEEP, DL_WWDT_WINDOW_PERIOD_0, DL_WWDT_WINDOW_PERIOD_0); // DL_WWDT_WINDOW_PERIOD_0 is for selecting the closed percentage of the watchdog
|
||||
if(DL_WWDT_isPowerEnabled(WATCHDOG_TIMER))
|
||||
{
|
||||
while ((DL_SYSCTL_getClockStatus() & (DL_SYSCTL_CLK_STATUS_LFOSC_GOOD))!= (DL_SYSCTL_CLK_STATUS_LFOSC_GOOD));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return IVEC_MCAL_STATUS_TIMEOUT;
|
||||
}
|
||||
b_WDInitFlag = true;
|
||||
|
||||
return IVEC_MCAL_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{;
|
||||
return IVEC_MCAL_STATUS_INIT_FAIL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
IVEC_McalStatus_e xMCAL_WatchdogDeInit(void)
|
||||
{
|
||||
assert(WATCHDOG_TIMER != NULL);
|
||||
|
||||
if(b_WDInitFlag == true)
|
||||
{
|
||||
DL_WWDT_disablePower(WATCHDOG_TIMER);
|
||||
|
||||
b_WDInitFlag = false;
|
||||
|
||||
return IVEC_MCAL_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return IVEC_MCAL_STATUS_INIT_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IVEC_McalStatus_e xMCAL_WatchdogReset(void)
|
||||
{
|
||||
if(DL_WWDT_isRunning(WATCHDOG_TIMER) == true)
|
||||
{
|
||||
DL_WWDT_restart(WATCHDOG_TIMER);
|
||||
|
||||
return IVEC_MCAL_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return IVEC_MCAL_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
@ -498,6 +498,8 @@ void vCcUartRxToCanTx(IVEC_EcuCommonCanFrame_s* pxCanMsg)
|
|||
int l_i32Status = -1;
|
||||
l_i32RetSize = u16CMPLX_vFrameEncode((uint32_t)l_u32Id, (uint8_t*)&pu8Data[1], u8Len, l_u8UartBuffer, 30);
|
||||
l_i32Status = IVEC_ECUUartWrite(&__gprv_UartCcHandle, l_u8UartBuffer, l_i32RetSize);
|
||||
vMCAL_WDG_Refresh();
|
||||
DL_WWDT_disablePower(WATCHDOG_TIMER);
|
||||
vMCAL_softReset();
|
||||
}
|
||||
|
||||
|
|
@ -767,7 +769,10 @@ void vRTE_ProcessUartData(void)
|
|||
uint8_t u8Len = sizeof(pu8Data); // Length of data array
|
||||
iECU_UartInitiateTransmit(&g_xUartHandle, u32Id, pu8Data, u8Len);
|
||||
iECU_UartInitiateTransmit(&g_xUartHandle, 0x8, NULL, 0);
|
||||
vMCAL_WDG_Refresh();
|
||||
DL_WWDT_disablePower(WATCHDOG_TIMER);
|
||||
vMCAL_softReset();
|
||||
|
||||
}
|
||||
|
||||
if(l_eRetCode > 0 && l_u32Id == 0x00)
|
||||
|
|
@ -840,9 +845,10 @@ void vRTE_ProcessUartData(void)
|
|||
l_i32Status = IVEC_ECUUartWrite(&__gprv_UartCcHandle, l_u8UartBuffer, l_i32RetSize);
|
||||
}
|
||||
xECU_WriteDataOverCAN(&g_xCanHandle, &g_pu8UartBuffer[ecuUART_PKT_HEADER_u8], l_u32Id, l_eRetCode, 0);
|
||||
}
|
||||
}
|
||||
vMCAL_WDG_Refresh();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Processes CAN data and handles CAN communication.
|
||||
|
|
@ -868,6 +874,7 @@ void vRTE_ProcessCanData(void)
|
|||
(l_xCanBuff.u8Data[3] == 'I') && (l_xCanBuff.u8Data[4] == 'O') && \
|
||||
(l_xCanBuff.u8Data[5] == 'T'))
|
||||
{
|
||||
DL_WWDT_disablePower(WATCHDOG_TIMER);
|
||||
vMCAL_softReset();
|
||||
}
|
||||
|
||||
|
|
@ -880,7 +887,6 @@ void vRTE_ProcessCanData(void)
|
|||
{
|
||||
|
||||
l_i32RetSize = u16CMPLX_vFrameEncode((uint32_t)0xabcdef, (uint8_t*)&l_xCanBuff.u8Data[0], (int32_t)l_xCanBuff.u8Length, l_u8UartBuffer, 30);
|
||||
|
||||
}
|
||||
|
||||
l_i32Status = IVEC_ECUUartWrite(&__gprv_UartCcHandle, l_u8UartBuffer, l_i32RetSize);
|
||||
|
|
@ -898,5 +904,5 @@ void vRTE_ProcessCanData(void)
|
|||
break;
|
||||
}
|
||||
xECU_CANGetStatus(&g_xCanHandle);
|
||||
|
||||
vMCAL_WDG_Refresh();
|
||||
}
|
||||
|
|
|
|||
2
main.c
2
main.c
|
|
@ -31,6 +31,7 @@ int main(void)
|
|||
{
|
||||
__enable_irq();
|
||||
volatile DL_SYSCTL_RESET_CAUSE l_xResetCause = DL_SYSCTL_getResetCause();
|
||||
vMCAL_WDG_Refresh();
|
||||
vMCAL_mcuInit();
|
||||
xMCAL_sysctlInit(IVEC_HFXT,IVEC_STANDBY0);
|
||||
xMCAL_systickInit(IVEC_SYSTICK_PERIOD_1MS);
|
||||
|
|
@ -43,6 +44,7 @@ int main(void)
|
|||
while(1)
|
||||
{
|
||||
vRTE_AppRun();
|
||||
vMCAL_WDG_Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -231,6 +231,7 @@ void Default_Handler(void)
|
|||
// // You can use this to trace the fault location in your code
|
||||
|
||||
/* Enter an infinite loop. */
|
||||
DL_SYSCTL_resetDevice(DL_SYSCTL_RESET_CPU);
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,11 +158,13 @@ void vMCAL_delayTicks(int32_t i32DelayMs)
|
|||
*
|
||||
* Calls the necessary functions to initialize power and GPIO configurations for the MCU.
|
||||
*/
|
||||
|
||||
void vMCAL_mcuInit(void)
|
||||
{
|
||||
SYSCFG_DL_initPower();
|
||||
DL_WWDT_enablePower(WATCHDOG_TIMER);
|
||||
xMCAL_WatchdogInit(MCAL_WDT_4_SEC_TIMER); // Timer Inputs can be : 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 16 , 24 , 32 , 40 , 48 , 56 , 64 in seconds
|
||||
SYSCFG_DL_GPIO_init();
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Delays execution for a specified number of microseconds.
|
||||
|
|
@ -211,3 +213,8 @@ void vMCAL_softReset(void)
|
|||
{
|
||||
DL_SYSCTL_resetDevice(DL_SYSCTL_RESET_CPU);
|
||||
}
|
||||
|
||||
void vMCAL_WDG_Refresh(void)
|
||||
{
|
||||
xMCAL_WatchdogReset();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,26 @@
|
|||
#include <assert.h>
|
||||
#include "ti_msp_dl_config.h"
|
||||
|
||||
#define WATCHDOG_TIMER WWDT1
|
||||
typedef enum
|
||||
{
|
||||
MCAL_WDT_1_SEC_TIMER = 1,
|
||||
MCAL_WDT_2_SEC_TIMER,
|
||||
MCAL_WDT_3_SEC_TIMER,
|
||||
MCAL_WDT_4_SEC_TIMER,
|
||||
MCAL_WDT_5_SEC_TIMER,
|
||||
MCAL_WDT_6_SEC_TIMER,
|
||||
MCAL_WDT_7_SEC_TIMER,
|
||||
MCAL_WDT_8_SEC_TIMER,
|
||||
MCAL_WDT_16_SEC_TIMER = 16,
|
||||
MCAL_WDT_24_SEC_TIMER = 24,
|
||||
MCAL_WDT_32_SEC_TIMER = 32,
|
||||
MCAL_WDT_40_SEC_TIMER = 40,
|
||||
MCAL_WDT_48_SEC_TIMER = 48,
|
||||
MCAL_WDT_56_SEC_TIMER = 56,
|
||||
MCAL_WDT_64_SEC_TIMER = 64
|
||||
}MCAL_WWDT_TIMER;
|
||||
|
||||
/* Generic Status Codes */
|
||||
typedef enum
|
||||
{
|
||||
|
|
@ -86,5 +106,6 @@ void vMCAL_delayTicks(int32_t i32DelayMs);
|
|||
void vMCAL_softReset(void);
|
||||
void vMCAL_delayUs(uint32_t u32Us);
|
||||
IVEC_McalStatus_e xMCAL_vrefInit(void);
|
||||
void vMCAL_WDG_Refresh(void);
|
||||
|
||||
#endif /* UTILS_IVEC_UTILS_H_ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue