MCUXpresso_LPC804/boards/lpcxpresso804/demo_apps/safety_iec60730b/main.c

439 lines
14 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
#include "safety_test_items.h"
#include "board.h"
/*******************************************************************************
* 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
/* Watchdog test */
SafetyWatchdogTest(&g_sSafetyCommon, &g_sSafetyWdTest);
#if WATCHDOG_ENABLED
Watchdog_refresh; /* refreshing the watchdog */
#endif
#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 */
g_sSafetyCommon.safetyErrors = 0; /* clear the variable that records safety error codes */
g_sSafetyCommon.fastIsrSafetySwitch = 0;
/* 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 < 9; i++) /* first 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 defined(_MKE15Z7_H_) | defined(_MKE17Z7_H_)
#if TSI_TEST_ENABLED
volatile uint32_t tsi_cnt_number = 0; /* Variables for runtime TSI test */
/* Enable TSI peripheral clock */
PCC->CLKCFG[PCC_TSI0_INDEX] = (PCC_CLKCFG_CGC(0));
PCC->CLKCFG[PCC_TSI0_INDEX] = (PCC_CLKCFG_CGC(TRUE) | PCC_CLKCFG_PCS(1)); /* System Oscillator Bus Clock */
tsi_port_clock_enable(); /* This function enable clock to correspond PORT */
/* Put ALL items to INIT state */
for (tsi_cnt_number = 0; tsi_safety_test_items[tsi_cnt_number] != NULL; tsi_cnt_number++)
{
FS_TSI_InputInit(tsi_safety_test_items[tsi_cnt_number]);
}
/* After-reset TSI test */
for (tsi_cnt_number = 0; tsi_safety_test_items[tsi_cnt_number] != NULL; tsi_cnt_number++)
{
while (FS_TSI_PASS_STIM != tsi_safety_test_items[tsi_cnt_number]->state)
{
SafetyTsiChanelTest(&g_sSafetyCommon, tsi_safety_test_items[tsi_cnt_number]);
}
FS_TSI_InputInit(tsi_safety_test_items[tsi_cnt_number]); /* SET back to INIT state for next runtime check */
#if WATCHDOG_ENABLED
Watchdog_refresh; /* refreshing the watchdog */
#endif
}
tsi_cnt_number = 0; /* Reset to 0 for RUNTIME test cnt */
#endif /* TSI_TEST_ENABLED */
#endif /* _MKE15Z7_H_ _MKE17Z7_H_ */
#if DIO_TEST_ENABLED
/* Digital I/O test */
SafetyDIOTestInit(&g_sSafetyCommon, g_dio_safety_test_items);
#ifdef _MKE02Z4_H_
SafetyDigitalOutputTest(&g_sSafetyCommon,g_dio_safety_test_items[0]);
SafetyDigitalInputTest(&g_sSafetyCommon,g_dio_safety_test_items[1]);
#else
for (int i = 0; g_dio_safety_test_items[i] != 0; i++)
{
SafetyDigitalOutputTest(&g_sSafetyCommon, g_dio_safety_test_items[i]);
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);
}
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);
#if defined(_MKE15Z7_H_) | defined(_MKE17Z7_H_)
SafetyDigitalInputOutput_ShortAdjTest(&g_sSafetyCommon, g_dio_safety_test_items[2], g_dio_safety_test_items[3],
LOGICAL_ZERO);
SafetyDigitalInputOutput_ShortAdjTest(&g_sSafetyCommon, g_dio_safety_test_items[6], g_dio_safety_test_items[7],
LOGICAL_ONE);
#endif
#endif /* _MKE02Z4_H_ */
#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 (TRUE)
{
/* 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");
g_sSafetyCommon.CPU_control_test_result = FS_CM0_CPU_Control();
__asm("CPSIE i");
if (g_sSafetyCommon.CPU_control_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_CM0_CPU_SPprocess();
__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 TSI_TEST_ENABLED
#if defined(_MKE15Z7_H_) | defined(_MKE17Z7_H_)
/* Runtime TSI test */
if (FS_TSI_PASS_STIM != tsi_safety_test_items[tsi_cnt_number]->state)
{
SafetyTsiChanelTest(&g_sSafetyCommon, tsi_safety_test_items[tsi_cnt_number]);
}
else if (tsi_safety_test_items[tsi_cnt_number + 1] != NULL)
{
FS_TSI_InputInit(tsi_safety_test_items[tsi_cnt_number]);
tsi_cnt_number++;
/* DIO TEST */
/* Because DIO can Use the SAME port as TSI, we must call this test only when TSI not RUN! */
safety_dio_runtime();
}
else
{
tsi_cnt_number = 0;
}
#endif /* _MKE15Z7_H_ _MKE17Z7_H_ */
#else /* TSI_TEST_ENABLED */
#if DIO_TEST_ENABLED
/* Digital I/O test */
safety_dio_runtime();
#endif /* DIO_TEST_ENABLED */
#endif /* TSI_TEST_ENABLED */
#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)
{
#ifdef _MKE02Z4_H_
SafetyDigitalOutputTest(&g_sSafetyCommon, g_dio_safety_test_items[0]);
SafetyDigitalInputTest(&g_sSafetyCommon, g_dio_safety_test_items[1]);
#else
/* Static variable for indexing in items array */
static uint8_t dio_cnt_number = 0;
if (g_dio_safety_test_items[dio_cnt_number] != NULL)
{
SafetyDigitalOutputTest(&g_sSafetyCommon, g_dio_safety_test_items[dio_cnt_number]);
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;
}
#endif
}
/*!
* @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);
}