369 lines
12 KiB
C
369 lines
12 KiB
C
/*
|
|
* Copyright 2021 NXP.
|
|
* All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "safety_config.h"
|
|
#if FMSTR_SERIAL_ENABLE
|
|
#include "freemaster.h"
|
|
#endif
|
|
|
|
|
|
/*******************************************************************************
|
|
* Prototypes
|
|
******************************************************************************/
|
|
void SYSTICK_Isr(void);
|
|
void safety_dio_runtime(void);
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
/* Start and end addresses for March test applied to Stack area */
|
|
extern const uint32_t c_stackTestFirstAddress; /* defined in safety_*.c */
|
|
extern const uint32_t c_stackTestSecondAddress; /* defined in safety_*.c */
|
|
|
|
/* Test variable */
|
|
volatile uint32_t counter = 0;
|
|
|
|
#if defined(__IAR_SYSTEMS_ICC__) /* IAR */
|
|
#pragma section = ".safety_ram"
|
|
#pragma section = ".pctest"
|
|
|
|
wd_test_t g_sSafetyWdTest @ ".safety_ram";
|
|
safety_common_t g_sSafetyCommon @ ".safety_ram";
|
|
fs_flash_runtime_test_parameters_t g_sFlashCrc @ ".safety_ram";
|
|
fs_flash_configuration_parameters_t g_sFlashConfig @ ".safety_ram";
|
|
fs_ram_test_t g_sSafetyRamTest @ ".safety_ram";
|
|
fs_ram_test_t g_sSafetyRamStackTest @ ".safety_ram";
|
|
fs_clock_test_t g_sSafetyClockTest @ ".safety_ram";
|
|
|
|
#elif (defined(__GNUC__) && ( __ARMCC_VERSION >= 6010050)) /* KEIL */
|
|
#include "linker_config.h"
|
|
|
|
/* The safety-related RAM border marker. */
|
|
extern uint32_t Image$$SafetyRam_region$$Limit;
|
|
|
|
uint32_t stack_pointer_addr = (uint32_t)__BOOT_STACK_ADDRESS;
|
|
|
|
uint16_t crcPostbuild; /* Checksum result calculated by srec_cat.exe in post-build phase */
|
|
|
|
wd_test_t g_sSafetyWdTest __attribute__((section(".safety_ram")));
|
|
safety_common_t g_sSafetyCommon __attribute__((section(".safety_ram")));
|
|
fs_clock_test_t g_sSafetyClockTest __attribute__((section(".safety_ram")));
|
|
fs_ram_test_t g_sSafetyRamTest __attribute__((section(".safety_ram")));
|
|
fs_ram_test_t g_sSafetyRamStackTest __attribute__((section(".safety_ram")));
|
|
fs_flash_runtime_test_parameters_t g_sFlashCrc __attribute__((section(".safety_ram")));
|
|
fs_flash_configuration_parameters_t g_sFlashConfig __attribute__((section(".safety_ram")));
|
|
|
|
#else /* MCUXpresso */
|
|
|
|
uint16_t crcPostbuild; /* Checksum result calculated by srec_cat.exe in post-build phase */
|
|
|
|
extern uint32_t __BOOT_STACK_ADDRESS; /* from Linker command file */
|
|
uint32_t stack_pointer_addr = (uint32_t)&__BOOT_STACK_ADDRESS;
|
|
|
|
extern uint32_t m_sec_fs_ram_start; /* from Linker command file */
|
|
uint32_t pui32SafetyRamSectionStart = (uint32_t)&m_sec_fs_ram_start;
|
|
|
|
extern uint32_t m_sec_fs_ram_end; /* from Linker command file */
|
|
uint32_t pui32SafetyRamSectionEnd = (uint32_t)&m_sec_fs_ram_end;
|
|
|
|
wd_test_t g_sSafetyWdTest __attribute__((section(".safety_ram")));
|
|
safety_common_t g_sSafetyCommon __attribute__((section(".safety_ram")));
|
|
fs_clock_test_t g_sSafetyClockTest __attribute__((section(".safety_ram")));
|
|
fs_ram_test_t g_sSafetyRamTest __attribute__((section(".safety_ram")));
|
|
fs_ram_test_t g_sSafetyRamStackTest __attribute__((section(".safety_ram")));
|
|
fs_flash_runtime_test_parameters_t g_sFlashCrc __attribute__((section(".safety_ram")));
|
|
fs_flash_configuration_parameters_t g_sFlashConfig __attribute__((section(".safety_ram")));
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
/*!
|
|
* @brief main function
|
|
*
|
|
* @param void
|
|
*
|
|
* @return None
|
|
*/
|
|
int32_t main(void)
|
|
{
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
|
|
/* Clock initialization */
|
|
ClockInit();
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
|
|
/* Pin initialization */
|
|
BOARD_InitBootPins();
|
|
|
|
/* Watchdog test */
|
|
SafetyWatchdogTest(&g_sSafetyCommon, &g_sSafetyWdTest);
|
|
|
|
g_sSafetyCommon.safetyErrors = 0; /* clear the variable that records safety error codes */
|
|
g_sSafetyCommon.fastIsrSafetySwitch = 0;
|
|
|
|
#if defined(__IAR_SYSTEMS_ICC__) /* IAR */
|
|
uint32_t *safetyRamStart = __section_begin(".safety_ram");
|
|
uint32_t *safetyRamEnd = __section_end(".safety_ram");
|
|
|
|
#elif (defined(__GNUC__) && (__ARMCC_VERSION >= 6010050)) /* KEIL */
|
|
uint32_t *safetyRamStart = (uint32_t *)m_safety_ram_start;
|
|
uint32_t *safetyRamEnd = (uint32_t *)&Image$$SafetyRam_region$$Limit;
|
|
|
|
#else /* MCUXpresso */
|
|
uint32_t *safetyRamStart = (uint32_t *)pui32SafetyRamSectionStart;
|
|
uint32_t *safetyRamEnd = (uint32_t *)pui32SafetyRamSectionEnd;
|
|
#endif
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
|
|
#if FMSTR_SERIAL_ENABLE
|
|
SerialInit();
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
|
|
FMSTR_Init();/* initialize freemaster */
|
|
#endif /* FMSTR_SERIAL_ENABLE */
|
|
|
|
/* Flash test init */
|
|
SafetyFlashTestInit(&g_sFlashCrc, &g_sFlashConfig);
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
|
|
#if FLASH_TEST_ENABLED
|
|
/* After-reset flash test */
|
|
SafetyFlashAfterResetTest(&g_sSafetyCommon, &g_sFlashConfig);
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
#endif /* FLASH_TEST_ENABLED */
|
|
|
|
/* Ram test init for Safety related RAM space */
|
|
SafetyRamTestInit(&g_sSafetyRamTest, safetyRamStart, safetyRamEnd);
|
|
|
|
/* Ram test init for Stack memory */
|
|
SafetyRamTestInit(&g_sSafetyRamStackTest, (uint32_t *)c_stackTestFirstAddress,
|
|
(uint32_t *)c_stackTestSecondAddress);
|
|
|
|
/* Ram after-reset test for safety related memory*/
|
|
SafetyRamAfterResetTest(&g_sSafetyCommon, &g_sSafetyRamTest);
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
|
|
/* Ram after-reset test for Stack area */
|
|
SafetyRamAfterResetTest(&g_sSafetyCommon, &g_sSafetyRamStackTest);
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
|
|
#if PC_TEST_ENABLED
|
|
/* Program Counter test */
|
|
SafetyPcTest(&g_sSafetyCommon, PC_TEST_PATTERN);
|
|
#endif
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
|
|
/* CPU test after */
|
|
SafetyCpuAfterResetTest(&g_sSafetyCommon);
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
|
|
/* initialize Stack test */
|
|
SafetyStackTestInit();
|
|
|
|
/* Stack overflow and underflow test */
|
|
SafetyStackTest(&g_sSafetyCommon);
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
|
|
#if ADC_TEST_ENABLED
|
|
AdcInit();
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
|
|
/* After-reset ADC test */
|
|
for (uint8_t i = 0; i < 6; i++) /* each odd iteration is init phase */
|
|
{
|
|
for (uint8_t y = 0; y < 40; y++)
|
|
__asm("nop"); /* delay because of conversion time */
|
|
SafetyAnalogTest(&g_sSafetyCommon);
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
}
|
|
#endif /* ADC_TEST_ENABLED */
|
|
|
|
#if DIO_TEST_ENABLED
|
|
/* Digital I/O test */
|
|
|
|
for (int i = 0; g_dio_safety_test_items[i] != 0; i++)
|
|
{
|
|
|
|
#ifndef _MIMXRT1189_CM33_H_
|
|
SafetyDigitalOutputTest(&g_sSafetyCommon, g_dio_safety_test_items[i]);
|
|
#endif
|
|
|
|
SafetyDigitalInputOutput_ShortSupplyTest(&g_sSafetyCommon, g_dio_safety_test_items[i], DIO_SHORT_TO_GND_TEST);
|
|
SafetyDigitalInputOutput_ShortSupplyTest(&g_sSafetyCommon, g_dio_safety_test_items[i], DIO_SHORT_TO_VDD_TEST);
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
}
|
|
|
|
SafetyDigitalInputOutput_ShortAdjTest(&g_sSafetyCommon, g_dio_safety_test_items[0], g_dio_safety_test_items[1],
|
|
LOGICAL_ONE);
|
|
SafetyDigitalInputOutput_ShortAdjTest(&g_sSafetyCommon, g_dio_safety_test_items[0], g_dio_safety_test_items[1],
|
|
LOGICAL_ZERO);
|
|
#endif /* DIO_TEST_ENABLED */
|
|
|
|
#if WATCHDOG_ENABLED
|
|
Watchdog_refresh; /* refreshing the watchdog */
|
|
#endif
|
|
|
|
#if CLOCK_TEST_ENABLED
|
|
/* Initialize Clock test */
|
|
SafetyClockTestInit(&g_sSafetyCommon, &g_sSafetyClockTest);
|
|
#endif
|
|
|
|
/* Initialize SysTick */
|
|
SystickInit(SYSTICK_RELOAD_VALUE);
|
|
|
|
/* Enable interrupts */
|
|
__asm("CPSIE i");
|
|
|
|
while (1)
|
|
{
|
|
/* Interruptable CPU registers test */
|
|
SafetyCpuBackgroundTest(&g_sSafetyCommon);
|
|
|
|
/* safety test of CPU CONTROL register, it cannot be placed in interrupt, thus interrupts must be disabled for a
|
|
* while */
|
|
/* - see IEC60730 library documentation for CPU errors handling ! */
|
|
__asm("CPSID i");
|
|
#if (defined(_LPC55S69_CM33_CORE0_H_) || defined(_LPC55S06_H_) || defined(_MIMXRT1189_CM33_H_)) /* If device supports TrustZone */
|
|
g_sSafetyCommon.CPU_control_s_test_result = FS_CM33_CPU_Control_S();
|
|
#else
|
|
g_sSafetyCommon.CPU_control_s_test_result = FS_CM33_CPU_Control();
|
|
#endif /* If device supports TrustZone */
|
|
__asm("CPSIE i");
|
|
if (g_sSafetyCommon.CPU_control_s_test_result == FS_FAIL_CPU_CONTROL)
|
|
{
|
|
g_sSafetyCommon.safetyErrors |= CPU_CONTROL_ERROR;
|
|
SafetyErrorHandling(&g_sSafetyCommon);
|
|
}
|
|
|
|
/* safety test of CPU SP_PROCESS register, it cannot be placed in interrupt, thus interrupts must be disabled
|
|
* for a while */
|
|
/* - see IEC60730 library documentation for CPU errors handling ! */
|
|
__asm("CPSID i");
|
|
FS_CM33_CPU_SPprocess_S();
|
|
__asm("CPSIE i");
|
|
|
|
#if FLASH_TEST_ENABLED
|
|
/* Runtime Flash test */
|
|
SafetyFlashRuntimeTest(&g_sSafetyCommon, &g_sFlashCrc, &g_sFlashConfig);
|
|
#endif
|
|
|
|
#if CLOCK_TEST_ENABLED
|
|
/* Runtime Clock test */
|
|
SafetyClockTestCheck(&g_sSafetyCommon, &g_sSafetyClockTest);
|
|
#endif
|
|
|
|
/* Stack overflow and underflow test */
|
|
SafetyStackTest(&g_sSafetyCommon);
|
|
|
|
#if ADC_TEST_ENABLED
|
|
/* Runtime ADC test */
|
|
SafetyAnalogTest(&g_sSafetyCommon);
|
|
#endif
|
|
|
|
#if DIO_TEST_ENABLED
|
|
/* Digital I/O test */
|
|
safety_dio_runtime();
|
|
#endif
|
|
|
|
#if FMSTR_SERIAL_ENABLE
|
|
|
|
FMSTR_Poll(); /* Freemaster cummunication */
|
|
#endif /* FMSTR_SERIAL_ENABLE */
|
|
|
|
development_test_terminate(); /* For example validation during development */
|
|
}
|
|
}
|
|
|
|
void safety_dio_runtime(void)
|
|
{
|
|
/* Static variable for indexing in items array */
|
|
static uint8_t dio_cnt_number = 0;
|
|
|
|
if (g_dio_safety_test_items[dio_cnt_number] != NULL)
|
|
{
|
|
#ifndef _MIMXRT1189_CM33_H_
|
|
SafetyDigitalOutputTest(&g_sSafetyCommon, g_dio_safety_test_items[dio_cnt_number]);
|
|
#endif
|
|
SafetyDigitalInputOutput_ShortSupplyTest(&g_sSafetyCommon, g_dio_safety_test_items[dio_cnt_number],
|
|
DIO_SHORT_TO_GND_TEST);
|
|
SafetyDigitalInputOutput_ShortSupplyTest(&g_sSafetyCommon, g_dio_safety_test_items[dio_cnt_number],
|
|
DIO_SHORT_TO_VDD_TEST);
|
|
|
|
/* In next call, test next DIO channel */
|
|
dio_cnt_number++;
|
|
}
|
|
else
|
|
{
|
|
dio_cnt_number = 0;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* @brief Systick interrupt function
|
|
*
|
|
* @param void
|
|
*
|
|
* @return None
|
|
*/
|
|
void SYSTICK_Isr(void)
|
|
{
|
|
counter++;
|
|
|
|
#if CLOCK_TEST_ENABLED
|
|
/* Clock test function */
|
|
SafetyClockTestIsr(&g_sSafetyClockTest);
|
|
#endif
|
|
|
|
/* Safety tests which cannot be interrupted */
|
|
SafetyIsrFunction(&g_sSafetyCommon, &g_sSafetyRamTest, &g_sSafetyRamStackTest);
|
|
|
|
/* Refreshing the watchdog. For short period of interrupts, choose higher refresh ratio parameter */
|
|
SafetyWatchdogRuntimeRefresh(&g_sSafetyWdTest);
|
|
}
|