/*
 * Copyright 2021 NXP.
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef _SAFETY_CM0_LPC_H_
#define _SAFETY_CM0_LPC_H_

#include "safety_config.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define CPU_TEST_ERROR       0x1    /* CPU test fault flag */
#define FLASH_TEST_ERROR     0x2    /* Flash test fault flag */
#define RAM_TEST_ERROR       0x4    /* RAM test fault flag */
#define STACK_TEST_ERROR     0x8    /* Stack test fault flag */
#define CLOCK_TEST_ERROR     0x10   /* Clock test fault flag */
#define PC_TEST_ERROR        0x20   /* Program counter test fault flag */
#define CPU_PRIMASK_ERROR    0x40   /* PRIMASK test fault flag */
#define CPU_REGISTERS_ERROR  0x80   /* CPU registers test fault flag */
#define CPU_NONSTACKED_ERROR 0x100  /* non-stacked CPU test fault flag */
#define CPU_CONTROL_ERROR    0x200  /* CONTROL register test fault flag */
#define DIO_TEST_ERROR       0x400  /* DIO test fault flag */
#define AIO_TEST_ERROR       0x800  /* AIO test fault flag */
#define TSI_TEST_ERROR       0x1000 /* TSI test fault flag */
#define WDOG_TEST_ERROR      0x2000 /* WDOG test fault flag */

#define FS_FLASH_PASS     0x0        /* Flash test pass return */
#define FS_FLASH_FAIL     0x00000301 /* Flash test fail return */
#define FS_FLASH_PROGRESS 0x00000302

#define SAFETY_CFG_PC_ADDR0 0x1FFFFFF8 /* #1 test address for Program counter test */
#define SAFETY_CFG_PC_ADDR1 0x20000006 /* #2 test address for Program counter test */

/*! @brief Safety tests */
typedef struct _safety_common
{
    uint32_t fastIsrSafetySwitch;
    uint32_t safetyErrors;
    uint32_t WDOG_test_result;
    uint32_t CLOCK_test_result;
    uint32_t FLASH_test_result;
    uint32_t RAM_test_result;
    uint32_t PC_test_result;
    uint32_t CPU_primask_test_result;
    uint32_t CPU_reg_test_result;
    uint32_t CPU_non_stacked_test_result;
    uint32_t CPU_control_test_result;
    uint32_t STACK_test_result;
    uint32_t DIO_input_test_result;
    uint32_t DIO_output_test_result;
    uint32_t DIO_short_test_result;
    uint32_t AIO_test_result;
    uint32_t TSI_test_result;
    uint32_t cpuClkFreq;
    uint32_t mcgirclkFreq;
    uint32_t lpoFreq;
} safety_common_t;

/*! @brief Safety Watchdog test */
typedef struct _wd_test
{
    uint64_t wdTestTemp1;
    uint32_t wdTestExpected;
    uint32_t wdTestTolerance;
    uint32_t wdTestLptmrCnt;
    uint32_t wdTestLimitHigh;
    uint32_t wdTestLimitLow;
    uint32_t watchdogResets;
    uint32_t watchdogTimeoutCheck;
    uint16_t watchdogRefreshRatio;
} wd_test_t;

/*! @brief Safety Clock test */
typedef struct _clock_test
{
    uint32_t clockTestContext;
    uint32_t clockTestTolerance;
    uint32_t clockTestExpected;
    uint32_t clockTestLimitHigh;
    uint32_t clockTestLimitLow;
    uint32_t systickReloadValue;
    uint16_t clockTestStart;
} fs_clock_test_t;

/*! @brief Safety RAM test */
typedef struct _ram_test
{
    uint32_t ramTestStartAddress;
    uint32_t ramTestEndAddress;
    uint32_t blockSize;
    uint32_t actualAddress;
    uint32_t defaultBlockSize;
    uint32_t backupAddress;
} fs_ram_test_t;

/*! @brief Safety Flash test runtime */
typedef struct _flash_runtime_test_parameters
{
    uint32_t blockSize;     /* size of tested block */
    uint32_t actualAddress; /* actual start address for crc module */
    uint32_t partCrc;       /* seed in begin, particular crc result in process, crc result in final*/
} fs_flash_runtime_test_parameters_t;

/*! @brief Safety Flash test parameters */
typedef struct _flash_configuration_parameters
{
    uint32_t startConditionSeed;
    uint32_t startAddress;
    uint32_t endAddress;
    uint32_t size;
    uint32_t blockSize;
    uint16_t checksum16;
} fs_flash_configuration_parameters_t;

/* CRC structure containing information for the offline CRC calculation. */
typedef struct _fs_crc
{
    uint16_t ui16Start;
    uint32_t ui32FlashStart __attribute__((packed));
    uint32_t ui32FlashEnd __attribute__((packed));
    uint32_t ui32CRC __attribute__((packed));
    uint16_t ui16End __attribute__((packed));
} fs_crc_t;

#ifdef __cplusplus
extern "C" {
#endif

/*!
 * @name Safety Class B tests handling functions
 * @{
 */

/*******************************************************************************
 * API
 ******************************************************************************/
void SafetyWatchdogTest(safety_common_t *psSafetyCommon, wd_test_t *psSafetyWdTest);
void SafetyWatchdogRuntimeRefresh(wd_test_t *psSafetyWdTest);
void SafetyClockTestInit(safety_common_t *psSafetyCommon, fs_clock_test_t *psSafetyClockTest);
void SafetyClockTestIsr(fs_clock_test_t *psSafetyClockTest);
void SafetyClockTestCheck(safety_common_t *psSafetyCommon, fs_clock_test_t *psSafetyClockTest);
void SafetyFlashTestInit(fs_flash_runtime_test_parameters_t *psFlashCrc,
                         fs_flash_configuration_parameters_t *psFlashConfig);
void SafetyFlashAfterResetTest(safety_common_t *psSafetyCommon, fs_flash_configuration_parameters_t *psFlashConfig);
void SafetyFlashRuntimeTest(safety_common_t *psSafetyCommon,
                            fs_flash_runtime_test_parameters_t *psFlashCrc,
                            fs_flash_configuration_parameters_t *psFlashConfig);
uint32_t SafetyFlashTestHandling(fs_flash_runtime_test_parameters_t *psFlashCrc,
                                 fs_flash_configuration_parameters_t *psFlashConfig);
void SafetyRamTestInit(fs_ram_test_t *psSafetyRamTest, uint32_t *pSafetyRamStart, uint32_t *pSafetyRamEnd);
void SafetyRamAfterResetTest(safety_common_t *psSafetyCommon, fs_ram_test_t *psSafetyRamTest);
void SafetyRamRuntimeTest(safety_common_t *psSafetyCommon, fs_ram_test_t *psSafetyRamTest);
void SafetyPcTest(safety_common_t *psSafetyCommon, uint32_t pattern);
void SafetyCpuAfterResetTest(safety_common_t *psSafetyCommon);
void SafetyCpuIsrTest(safety_common_t *psSafetyCommon);
void SafetyCpuBackgroundTest(safety_common_t *psSafetyCommon);
void SafetyStackTestInit(void);
void SafetyStackTest(safety_common_t *psSafetyCommon);

void SafetyDIOTestInit(safety_common_t *psSafetyCommon, fs_dio_test_lpc_t *pTestItems[]);
void SafetyDigitalOutputTest(safety_common_t *psSafetyCommon, fs_dio_test_lpc_t *pTestedPin);
void SafetyDigitalInputOutput_ShortSupplyTest(safety_common_t *psSafetyCommon,
                                              fs_dio_test_lpc_t *pTestedPin,
                                              uint8_t polarity);
void SafetyDigitalInputOutput_ShortAdjTest(safety_common_t *psSafetyCommon,
                                           fs_dio_test_lpc_t *pTestedPin,
                                           fs_dio_test_lpc_t *pAdjPin,
                                           uint32_t PinValue);

void SafetyAnalogTest(safety_common_t *psSafetyCommon);

void SafetyIsrFunction(safety_common_t *psSafetyCommon,
                       fs_ram_test_t *psSafetyRamTest,
                       fs_ram_test_t *psSafetyRamStackTest);

void development_test_terminate(void);
void SafetyErrorHandling(safety_common_t *psSafetyCommon);

#ifdef __cplusplus
}
#endif

#endif /* _SAFETY_CM0_LPC_H_ */
