397 lines
12 KiB
C
397 lines
12 KiB
C
/*
|
|
* Copyright 2020-2022 NXP
|
|
* All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "fsl_cdog.h"
|
|
|
|
/*******************************************************************************
|
|
* Definitions
|
|
*******************************************************************************/
|
|
|
|
/* Component ID definition, used by tools. */
|
|
#ifndef FSL_COMPONENT_ID
|
|
#define FSL_COMPONENT_ID "platform.drivers.cdog"
|
|
#endif
|
|
|
|
/* Reset CONTROL mask */
|
|
#define RESERVED_CTRL_MASK 0x800u
|
|
|
|
#if defined(CDOG_IRQS)
|
|
/* Array of IRQs */
|
|
static const IRQn_Type s_CdogIrqs[] = CDOG_IRQS;
|
|
#endif /* CDOG_IRQS */
|
|
|
|
/*******************************************************************************
|
|
* Prototypes
|
|
******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
#if defined(CDOG)
|
|
/*!
|
|
* Weak implementation of CDOG IRQ, should be re-defined by user when using CDOG IRQ
|
|
*/
|
|
__WEAK void CDOG_DriverIRQHandler(void)
|
|
{
|
|
/* NVIC_DisableIRQ(CDOG_IRQn);
|
|
* CDOG_Stop(CDOG, s_start);
|
|
* CDOG->FLAGS = 0x0U;
|
|
* CDOG_Start(CDOG, 0xFFFFFFU, s_start);
|
|
* NVIC_EnableIRQ(CDOG_IRQn);
|
|
*/
|
|
}
|
|
#endif
|
|
|
|
#if defined(CDOG0)
|
|
/*!
|
|
* Weak implementation of CDOG0 IRQ, should be re-defined by user when using CDOG IRQ
|
|
*/
|
|
__WEAK void CDOG0_DriverIRQHandler(void)
|
|
{
|
|
/* NVIC_DisableIRQ(CDOG0_IRQn);
|
|
* CDOG_Stop(CDOG0, s_start);
|
|
* CDOG0->FLAGS = 0x0U;
|
|
* CDOG_Start(CDOG0, 0xFFFFFFU, s_start);
|
|
* NVIC_EnableIRQ(CDOG0_IRQn);
|
|
*/
|
|
}
|
|
#endif
|
|
|
|
#if defined(CDOG1)
|
|
/*!
|
|
* Weak implementation of CDOG1 IRQ, should be re-defined by user when using CDOG IRQ
|
|
*/
|
|
__WEAK void CDOG1_DriverIRQHandler(void)
|
|
{
|
|
/* NVIC_DisableIRQ(CDOG1_IRQn);
|
|
* CDOG_Stop(CDOG1, s_start);
|
|
* CDOG1->FLAGS = 0x0U;
|
|
* CDOG_Start(CDOG1, 0xFFFFFFU, s_start);
|
|
* NVIC_EnableIRQ(CDOG1_IRQn);
|
|
*/
|
|
}
|
|
#endif
|
|
|
|
/*!
|
|
* brief Sets the default configuration of CDOG
|
|
*
|
|
* This function initialize CDOG config structure to default values.
|
|
*
|
|
* param conf CDOG configuration structure
|
|
*/
|
|
void CDOG_GetDefaultConfig(cdog_config_t *conf)
|
|
{
|
|
/* Default configuration after reset */
|
|
conf->lock = (uint8_t)kCDOG_LockCtrl_Unlock; /* Lock control */
|
|
conf->timeout = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Timeout control */
|
|
conf->miscompare = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Miscompare control */
|
|
conf->sequence = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Sequence control */
|
|
conf->state = (uint8_t)kCDOG_FaultCtrl_NoAction; /* State control */
|
|
conf->address = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Address control */
|
|
conf->irq_pause = (uint8_t)kCDOG_IrqPauseCtrl_Run; /* IRQ pause control */
|
|
conf->debug_halt = (uint8_t)kCDOG_DebugHaltCtrl_Run; /* Debug halt control */
|
|
return;
|
|
}
|
|
|
|
/*!
|
|
* brief Sets secure counter and instruction timer values
|
|
*
|
|
* This function sets value in RELOAD and START registers for instruction timer.
|
|
*
|
|
* param base CDOG peripheral base address
|
|
* param reload reload value
|
|
* param start start value
|
|
*/
|
|
void CDOG_Start(CDOG_Type *base, uint32_t reload, uint32_t start)
|
|
{
|
|
base->RELOAD = reload;
|
|
base->START = start;
|
|
}
|
|
|
|
/*!
|
|
* brief Stops secure counter and instruction timer
|
|
*
|
|
* This function stops instruction timer and secure counter.
|
|
* This also change state of CDOG to IDLE.
|
|
*
|
|
* param base CDOG peripheral base address
|
|
* param stop expected value which will be compared with value of secure counter
|
|
*/
|
|
void CDOG_Stop(CDOG_Type *base, uint32_t stop)
|
|
{
|
|
base->STOP = stop;
|
|
}
|
|
|
|
/*!
|
|
* brief Sets secure counter and instruction timer values
|
|
*
|
|
* This function sets value in STOP, RELOAD and START registers
|
|
* for instruction timer and secure counter.
|
|
*
|
|
* param base CDOG peripheral base address
|
|
* param stop expected value which will be compared with value of secure counter
|
|
* param reload reload value for instruction timer
|
|
* param start start value for secure timer
|
|
*/
|
|
void CDOG_Set(CDOG_Type *base, uint32_t stop, uint32_t reload, uint32_t start)
|
|
{
|
|
base->STOP = stop;
|
|
base->RELOAD = reload;
|
|
base->START = start;
|
|
}
|
|
|
|
/*!
|
|
* brief Add value to secure counter
|
|
*
|
|
* This function add specified value to secure counter.
|
|
*
|
|
* param base CDOG peripheral base address.
|
|
* param add Value to be added.
|
|
*/
|
|
void CDOG_Add(CDOG_Type *base, uint32_t add)
|
|
{
|
|
base->ADD = (secure_counter_t)add;
|
|
}
|
|
|
|
/*!
|
|
* brief Add 1 to secure counter
|
|
*
|
|
* This function add 1 to secure counter.
|
|
*
|
|
* param base CDOG peripheral base address.
|
|
* param add Value to be added.
|
|
*/
|
|
void CDOG_Add1(CDOG_Type *base)
|
|
{
|
|
base->ADD1 = (secure_counter_t)0x1U;
|
|
}
|
|
|
|
/*!
|
|
* brief Add 16 to secure counter
|
|
*
|
|
* This function add 16 to secure counter.
|
|
*
|
|
* param base CDOG peripheral base address.
|
|
* param add Value to be added.
|
|
*/
|
|
void CDOG_Add16(CDOG_Type *base)
|
|
{
|
|
base->ADD16 = (secure_counter_t)0x1U;
|
|
}
|
|
|
|
/*!
|
|
* brief Add 256 to secure counter
|
|
*
|
|
* This function add 256 to secure counter.
|
|
*
|
|
* param base CDOG peripheral base address.
|
|
* param add Value to be added.
|
|
*/
|
|
void CDOG_Add256(CDOG_Type *base)
|
|
{
|
|
base->ADD256 = (secure_counter_t)0x1U;
|
|
}
|
|
|
|
/*!
|
|
* brief Substract value to secure counter
|
|
*
|
|
* This function substract specified value to secure counter.
|
|
*
|
|
* param base CDOG peripheral base address.
|
|
* param sub Value to be substracted.
|
|
*/
|
|
void CDOG_Sub(CDOG_Type *base, uint32_t sub)
|
|
{
|
|
base->SUB = (secure_counter_t)sub;
|
|
}
|
|
|
|
/*!
|
|
* brief Substract 1 from secure counter
|
|
*
|
|
* This function substract specified 1 from secure counter.
|
|
*
|
|
* param base CDOG peripheral base address.
|
|
*/
|
|
void CDOG_Sub1(CDOG_Type *base)
|
|
{
|
|
base->SUB1 = (secure_counter_t)0x1U;
|
|
}
|
|
|
|
/*!
|
|
* brief Substract 16 from secure counter
|
|
*
|
|
* This function substract specified 16 from secure counter.
|
|
*
|
|
* param base CDOG peripheral base address.
|
|
*/
|
|
void CDOG_Sub16(CDOG_Type *base)
|
|
{
|
|
base->SUB16 = (secure_counter_t)0x1U;
|
|
}
|
|
|
|
/*!
|
|
* brief Substract 256 from secure counter
|
|
*
|
|
* This function substract specified 256 from secure counter.
|
|
*
|
|
* param base CDOG peripheral base address.
|
|
*/
|
|
void CDOG_Sub256(CDOG_Type *base)
|
|
{
|
|
base->SUB256 = (secure_counter_t)0x1U;
|
|
}
|
|
|
|
/*!
|
|
* brief Checks secure counter.
|
|
*
|
|
* This function compares stop value with secure counter value
|
|
* by writting to RELOAD refister.
|
|
*
|
|
* param base CDOG peripheral base address
|
|
* param check expected (stop) value.
|
|
*/
|
|
void CDOG_Check(CDOG_Type *base, uint32_t check)
|
|
{
|
|
base->RESTART = check;
|
|
}
|
|
|
|
/*!
|
|
* brief Set the CDOG persistent word.
|
|
*
|
|
* param base CDOG peripheral base address.
|
|
* param value The value to be written.
|
|
*/
|
|
void CDOG_WritePersistent(CDOG_Type *base, uint32_t value)
|
|
{
|
|
base->PERSISTENT = value;
|
|
}
|
|
|
|
/*!
|
|
* brief Get the CDOG persistent word.
|
|
*
|
|
* param base CDOG peripheral base address.
|
|
* return The persistent word.
|
|
*/
|
|
uint32_t CDOG_ReadPersistent(CDOG_Type *base)
|
|
{
|
|
return base->PERSISTENT;
|
|
}
|
|
|
|
/*!
|
|
* brief Initialize CDOG
|
|
*
|
|
* This function initializes CDOG setting and enable all interrupts.
|
|
*
|
|
* param base CDOG peripheral base address
|
|
* param conf CDOG configuration structure
|
|
* return Status of the init operation
|
|
*/
|
|
status_t CDOG_Init(CDOG_Type *base, cdog_config_t *conf)
|
|
{
|
|
/* Ungate clock to CDOG engine and reset it */
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
#ifdef CDOG_CLOCKS
|
|
CLOCK_EnableClock(kCLOCK_Cdog);
|
|
#endif /* CDOG_CLOCKS */
|
|
#endif /* !FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
|
|
#if !(defined(FSL_FEATURE_CDOG_HAS_NO_RESET) && FSL_FEATURE_CDOG_HAS_NO_RESET)
|
|
RESET_PeripheralReset(kCDOG_RST_SHIFT_RSTn);
|
|
#endif /* !FSL_FEATURE_CDOG_HAS_NO_RESET */
|
|
|
|
if (base->CONTROL == 0x0U)
|
|
{
|
|
/* CDOG is not in IDLE mode, which may be cause after SW reset. */
|
|
/* Writing to CONTROL register will trigger fault. */
|
|
return kStatus_Fail;
|
|
}
|
|
|
|
/* Clear pending errors, otherwise the device will reset */
|
|
/* itself immediately after enable Code Watchdog */
|
|
if ((uint32_t)kCDOG_LockCtrl_Lock ==
|
|
((base->CONTROL & CDOG_CONTROL_LOCK_CTRL_MASK) >> CDOG_CONTROL_LOCK_CTRL_SHIFT))
|
|
|
|
{
|
|
base->FLAGS = CDOG_FLAGS_TO_FLAG(1U) | CDOG_FLAGS_MISCOM_FLAG(1U) | CDOG_FLAGS_SEQ_FLAG(1U) |
|
|
CDOG_FLAGS_CNT_FLAG(1U) | CDOG_FLAGS_STATE_FLAG(1U) | CDOG_FLAGS_ADDR_FLAG(1U) |
|
|
CDOG_FLAGS_POR_FLAG(1U);
|
|
}
|
|
else
|
|
{
|
|
/* load default values for CDOG->CONTROL before flags clear */
|
|
#if defined(FSL_FEATURE_CDOG_NEED_LOAD_DEFAULT_CONF) && (FSL_FEATURE_CDOG_NEED_LOAD_DEFAULT_CONF > 0)
|
|
cdog_config_t default_conf;
|
|
|
|
/* Initialize CDOG */
|
|
CDOG_GetDefaultConfig(&default_conf);
|
|
|
|
/* Write default value to CDOG->CONTROL*/
|
|
base->CONTROL =
|
|
CDOG_CONTROL_TIMEOUT_CTRL(default_conf.timeout) | /* Action if the timeout event is triggered */
|
|
CDOG_CONTROL_MISCOMPARE_CTRL(default_conf.miscompare) | /* Action if the miscompare error event is triggered */
|
|
CDOG_CONTROL_SEQUENCE_CTRL(default_conf.sequence) | /* Action if the sequence error event is triggered */
|
|
CDOG_CONTROL_STATE_CTRL(default_conf.state) | /* Action if the state error event is triggered */
|
|
CDOG_CONTROL_ADDRESS_CTRL(default_conf.address) | /* Action if the address error event is triggered */
|
|
CDOG_CONTROL_IRQ_PAUSE(default_conf.irq_pause) | /* Pause running during interrupts setup */
|
|
CDOG_CONTROL_DEBUG_HALT_CTRL(default_conf.debug_halt) | /* Halt CDOG timer during debug */
|
|
CDOG_CONTROL_LOCK_CTRL(default_conf.lock) | RESERVED_CTRL_MASK; /* Lock control register, RESERVED */
|
|
#endif /* FSL_FEATURE_CDOG_NEED_LOAD_DEFAULT_CONF */
|
|
|
|
base->FLAGS = CDOG_FLAGS_TO_FLAG(0U) | CDOG_FLAGS_MISCOM_FLAG(0U) | CDOG_FLAGS_SEQ_FLAG(0U) |
|
|
CDOG_FLAGS_CNT_FLAG(0U) | CDOG_FLAGS_STATE_FLAG(0U) | CDOG_FLAGS_ADDR_FLAG(0U) |
|
|
CDOG_FLAGS_POR_FLAG(0U);
|
|
}
|
|
|
|
base->CONTROL =
|
|
CDOG_CONTROL_TIMEOUT_CTRL(conf->timeout) | /* Action if the timeout event is triggered */
|
|
CDOG_CONTROL_MISCOMPARE_CTRL(conf->miscompare) | /* Action if the miscompare error event is triggered */
|
|
CDOG_CONTROL_SEQUENCE_CTRL(conf->sequence) | /* Action if the sequence error event is triggered */
|
|
CDOG_CONTROL_STATE_CTRL(conf->state) | /* Action if the state error event is triggered */
|
|
CDOG_CONTROL_ADDRESS_CTRL(conf->address) | /* Action if the address error event is triggered */
|
|
CDOG_CONTROL_IRQ_PAUSE(conf->irq_pause) | /* Pause running during interrupts setup */
|
|
CDOG_CONTROL_DEBUG_HALT_CTRL(conf->debug_halt) | /* Halt CDOG timer during debug */
|
|
CDOG_CONTROL_LOCK_CTRL(conf->lock) | RESERVED_CTRL_MASK; /* Lock control register, RESERVED */
|
|
|
|
#if defined(CDOG_IRQS)
|
|
/* Enable peripheral IRQs, if defined in array */
|
|
for (uint32_t i = 0; i < ARRAY_SIZE(s_CdogIrqs); i++)
|
|
{
|
|
NVIC_EnableIRQ(s_CdogIrqs[i]);
|
|
}
|
|
#endif /* CDOG_IRQS */
|
|
|
|
return kStatus_Success;
|
|
}
|
|
|
|
/*!
|
|
* brief Deinitialize CDOG
|
|
*
|
|
* This function stops CDOG secure counter.
|
|
*
|
|
* param base CDOG peripheral base address
|
|
*/
|
|
void CDOG_Deinit(CDOG_Type *base)
|
|
{
|
|
#if defined(CDOG_IRQS)
|
|
/* Enable peripheral IRQs, if defined in array */
|
|
for (uint32_t i = 0; i < ARRAY_SIZE(s_CdogIrqs); i++)
|
|
{
|
|
NVIC_DisableIRQ(s_CdogIrqs[i]);
|
|
}
|
|
#endif /* CDOG_IRQS */
|
|
|
|
#if !(defined(FSL_FEATURE_CDOG_HAS_NO_RESET) && FSL_FEATURE_CDOG_HAS_NO_RESET)
|
|
RESET_SetPeripheralReset(kCDOG_RST_SHIFT_RSTn);
|
|
#endif /* !FSL_FEATURE_CDOG_HAS_NO_RESET */
|
|
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
#ifdef CDOG_CLOCKS
|
|
CLOCK_DisableClock(kCLOCK_Cdog);
|
|
#endif /* CDOG_CLOCKS */
|
|
#endif /* !FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
|
}
|