diff --git a/drivers/rz/CMakeLists.txt b/drivers/rz/CMakeLists.txt index 4a8e0df5..062d48ff 100644 --- a/drivers/rz/CMakeLists.txt +++ b/drivers/rz/CMakeLists.txt @@ -94,5 +94,8 @@ endif() zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_MTU fsp/src/${SOC_SERIES_PREFIX}/r_mtu3/r_mtu3.c) +zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_WDT + fsp/src/${SOC_SERIES_PREFIX}/r_wdt/r_wdt.c) + zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_CMTW fsp/src/${SOC_SERIES_PREFIX}/r_cmtw/r_cmtw.c) diff --git a/drivers/rz/fsp/inc/api/r_wdt_api.h b/drivers/rz/fsp/inc/api/r_wdt_api.h new file mode 100644 index 00000000..b9999e5e --- /dev/null +++ b/drivers/rz/fsp/inc/api/r_wdt_api.h @@ -0,0 +1,222 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @ingroup RENESAS_MONITORING_INTERFACES + * @defgroup WDT_API WDT Interface + * @brief Interface for watch dog timer functions. + * + * @section WDT_API_Summary Summary + * The WDT interface for the Watchdog Timer (WDT) peripheral provides watchdog functionality including resetting the + * device or generating an interrupt. + * + * + * @{ + **********************************************************************************************************************/ + +#ifndef R_WDT_API_H +#define R_WDT_API_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +/* Register definitions, common services and error codes. */ +#include "bsp_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ +#ifndef BSP_OVERRIDE_WDT_TIMEOUT_T + +/** WDT time-out periods. */ +typedef enum e_wdt_timeout +{ + WDT_TIMEOUT_128 = 0, ///< 128 clock cycles + WDT_TIMEOUT_512, ///< 512 clock cycles + WDT_TIMEOUT_1024, ///< 1024 clock cycles + WDT_TIMEOUT_2048, ///< 2048 clock cycles + WDT_TIMEOUT_4096, ///< 4096 clock cycles + WDT_TIMEOUT_8192, ///< 8192 clock cycles + WDT_TIMEOUT_16384, ///< 16384 clock cycles +} wdt_timeout_t; +#endif + +#ifndef BSP_OVERRIDE_WDT_CLOCK_DIVISION_T + +/** WDT clock division ratio. */ +typedef enum e_wdt_clock_division +{ + WDT_CLOCK_DIVISION_1 = 0, ///< CLK/1 + WDT_CLOCK_DIVISION_4 = 1, ///< CLK/4 + WDT_CLOCK_DIVISION_16 = 2, ///< CLK/16 + WDT_CLOCK_DIVISION_32 = 3, ///< CLK/32 + WDT_CLOCK_DIVISION_64 = 4, ///< CLK/64 + WDT_CLOCK_DIVISION_128 = 15, ///< CLK/128 + WDT_CLOCK_DIVISION_256 = 5, ///< CLK/256 + WDT_CLOCK_DIVISION_512 = 6, ///< CLK/512 + WDT_CLOCK_DIVISION_2048 = 7, ///< CLK/2048 + WDT_CLOCK_DIVISION_8192 = 8, ///< CLK/8192 +} wdt_clock_division_t; +#endif + +#ifndef BSP_OVERRIDE_WDT_WINDOW_START_END_T +/** WDT refresh permitted period window start position. */ +typedef enum e_wdt_window_start +{ + WDT_WINDOW_START_25 = 0, ///< Start position = 25% + WDT_WINDOW_START_50 = 1, ///< Start position = 50% + WDT_WINDOW_START_75 = 2, ///< Start position = 75% + WDT_WINDOW_START_100 = 3, ///< Start position = 100% +} wdt_window_start_t; + +/** WDT refresh permitted period window end position. */ +typedef enum e_wdt_window_end +{ + WDT_WINDOW_END_75 = 0, ///< End position = 75% + WDT_WINDOW_END_50 = 1, ///< End position = 50% + WDT_WINDOW_END_25 = 2, ///< End position = 25% + WDT_WINDOW_END_0 = 3, ///< End position = 0% +} wdt_window_end_t; +#endif + +/** WDT Counter underflow and refresh error control. */ +typedef enum e_wdt_reset_control +{ + WDT_RESET_CONTROL_NMI = 0, ///< NMI/IRQ request when counter underflows. + WDT_RESET_CONTROL_RESET = 1, ///< Reset request when counter underflows. +} wdt_reset_control_t; + +/** WDT Counter operation in sleep mode. */ +typedef enum e_wdt_stop_control +{ + WDT_STOP_CONTROL_DISABLE = 0, ///< Count will not stop when device enters sleep mode. + WDT_STOP_CONTROL_ENABLE = 1, ///< Count will automatically stop when device enters sleep mode. +} wdt_stop_control_t; + +/** WDT status */ +typedef enum e_wdt_status +{ + WDT_STATUS_NO_ERROR = 0, ///< No status flags set. + WDT_STATUS_UNDERFLOW = 1, ///< Underflow flag set. + WDT_STATUS_REFRESH_ERROR = 2, ///< Refresh error flag set. Refresh outside of permitted window. + WDT_STATUS_UNDERFLOW_AND_REFRESH_ERROR = 3, ///< Underflow and refresh error flags set. + WDT_STATUS_OVERFLOW = 4, ///< Overflow flag set. +} wdt_status_t; + +/** Callback function parameter data */ +typedef struct st_wdt_callback_args +{ + void const * p_context; ///< Placeholder for user data. Set in @ref wdt_api_t::open function in @ref wdt_cfg_t. +} wdt_callback_args_t; + +/** WDT timeout data. Used to return frequency of WDT clock and timeout period */ +typedef struct st_wdt_timeout_values +{ + uint32_t clock_frequency_hz; ///< Frequency of watchdog clock after divider. + uint32_t timeout_clocks; ///< Timeout period in units of watchdog clock ticks. +} wdt_timeout_values_t; + +/** WDT control block. Allocate an instance specific control block to pass into the WDT API calls. + */ +typedef void wdt_ctrl_t; + +/** WDT configuration parameters. */ +typedef struct st_wdt_cfg +{ + wdt_timeout_t timeout; ///< Timeout period. + wdt_clock_division_t clock_division; ///< Clock divider. + wdt_window_start_t window_start; ///< Refresh permitted window start position. + wdt_window_end_t window_end; ///< Refresh permitted window end position. + wdt_reset_control_t reset_control; ///< Select NMI/IRQ or reset generated on underflow. + wdt_stop_control_t stop_control; ///< Select whether counter operates in sleep mode. + void (* p_callback)(wdt_callback_args_t * p_args); ///< Callback provided when a WDT ISR occurs. + + /** Placeholder for user data. Passed to the user callback in wdt_callback_args_t. */ + void const * p_context; + void const * p_extend; ///< Placeholder for user extension. +} wdt_cfg_t; + +/** WDT functions implemented at the HAL layer will follow this API. */ +typedef struct st_wdt_api +{ + /** Initialize the WDT in register start mode. In auto-start mode (Supported devices only) with NMI output it + * registers the NMI callback. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] p_cfg Pointer to pin configuration structure. + */ + fsp_err_t (* open)(wdt_ctrl_t * const p_ctrl, wdt_cfg_t const * const p_cfg); + + /** Refresh the watchdog timer. + * + * @param[in] p_ctrl Pointer to control structure. + */ + fsp_err_t (* refresh)(wdt_ctrl_t * const p_ctrl); + + /** Read the status of the WDT. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[out] p_status Pointer to variable to return status information through. + */ + fsp_err_t (* statusGet)(wdt_ctrl_t * const p_ctrl, wdt_status_t * const p_status); + + /** Clear the status flags of the WDT. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] status Status condition(s) to clear. + */ + fsp_err_t (* statusClear)(wdt_ctrl_t * const p_ctrl, const wdt_status_t status); + + /** Read the current WDT counter value. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[out] p_count Pointer to variable to return current WDT counter value. + */ + fsp_err_t (* counterGet)(wdt_ctrl_t * const p_ctrl, uint32_t * const p_count); + + /** Read the watchdog timeout values. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[out] p_timeout Pointer to structure to return timeout values. + */ + fsp_err_t (* timeoutGet)(wdt_ctrl_t * const p_ctrl, wdt_timeout_values_t * const p_timeout); + + /** Specify callback function and optional context pointer and working memory pointer. + * + * @param[in] p_ctrl Pointer to the WDT control block. + * @param[in] p_callback Callback function + * @param[in] p_context Pointer to send to callback function + * @param[in] p_callback_memory Pointer to volatile memory where callback structure can be allocated. + * Callback arguments allocated here are only valid during the callback. + */ + fsp_err_t (* callbackSet)(wdt_ctrl_t * const p_ctrl, void (* p_callback)(wdt_callback_args_t *), + void const * const p_context, wdt_callback_args_t * const p_callback_memory); +} wdt_api_t; + +/** This structure encompasses everything that is needed to use an instance of this interface. */ +typedef struct st_wdt_instance +{ + wdt_ctrl_t * p_ctrl; ///< Pointer to the control structure for this instance + wdt_cfg_t const * p_cfg; ///< Pointer to the configuration structure for this instance + wdt_api_t const * p_api; ///< Pointer to the API structure for this instance +} wdt_instance_t; + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif + +/*******************************************************************************************************************//** + * @} (end defgroup WDT_API) + **********************************************************************************************************************/ diff --git a/drivers/rz/fsp/inc/instances/rza/r_wdt.h b/drivers/rz/fsp/inc/instances/rza/r_wdt.h new file mode 100644 index 00000000..b0ecf173 --- /dev/null +++ b/drivers/rz/fsp/inc/instances/rza/r_wdt.h @@ -0,0 +1,88 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @addtogroup WDT WDT + * @{ + **********************************************************************************************************************/ + +#ifndef R_WDT_H +#define R_WDT_H + +#include "bsp_api.h" + +#include "r_wdt_cfg.h" +#include "r_wdt_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** WDT private control block. DO NOT MODIFY. Initialization occurs when R_WDT_Open() is called. */ +typedef struct st_wdt_instance_ctrl +{ + uint32_t wdt_open; // Indicates whether the open() API has been successfully + // called. + wdt_cfg_t const * p_cfg; // Pointer to the configuration block. + void const * p_context; // Placeholder for user data. Passed to the user callback in + // wdt_callback_args_t. + void (* p_callback)(wdt_callback_args_t * p_args); // Callback provided when a WDT NMI ISR occurs. + wdt_callback_args_t * p_callback_memory; // Pointer to non-secure memory that can be used to pass arguments to a callback in non-secure memory. +} wdt_instance_ctrl_t; + +/** WDT configuration extension. This extension is required. */ +typedef struct st_wdt_extended_cfg +{ + uint16_t wdt_timeout; // Timeout value until the counter overflows. + uint8_t overflow_ipl; // WDT Overflow interrupt priority. + IRQn_Type overflow_irq; // WDT Overflow interrupt ID. +} wdt_extended_cfg_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const wdt_api_t g_wdt_on_wdt; + +/** @endcond */ + +/********************************************************************************************************************** + * Public Function Prototypes + **********************************************************************************************************************/ +fsp_err_t R_WDT_Refresh(wdt_ctrl_t * const p_ctrl); + +fsp_err_t R_WDT_Open(wdt_ctrl_t * const p_ctrl, wdt_cfg_t const * const p_cfg); + +fsp_err_t R_WDT_StatusClear(wdt_ctrl_t * const p_ctrl, const wdt_status_t status); + +fsp_err_t R_WDT_StatusGet(wdt_ctrl_t * const p_ctrl, wdt_status_t * const p_status); + +fsp_err_t R_WDT_CounterGet(wdt_ctrl_t * const p_ctrl, uint32_t * const p_count); + +fsp_err_t R_WDT_TimeoutGet(wdt_ctrl_t * const p_ctrl, wdt_timeout_values_t * const p_timeout); + +fsp_err_t R_WDT_CallbackSet(wdt_ctrl_t * const p_ctrl, + void ( * p_callback)(wdt_callback_args_t *), + void const * const p_context, + wdt_callback_args_t * const p_callback_memory); + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif // R_WDT_H + +/*******************************************************************************************************************//** + * @} (end addtogroup WDT) + **********************************************************************************************************************/ diff --git a/drivers/rz/fsp/inc/instances/rzn/r_wdt.h b/drivers/rz/fsp/inc/instances/rzn/r_wdt.h new file mode 100644 index 00000000..8f26adfd --- /dev/null +++ b/drivers/rz/fsp/inc/instances/rzn/r_wdt.h @@ -0,0 +1,80 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @addtogroup WDT WDT + * @{ + **********************************************************************************************************************/ + +#ifndef R_WDT_H +#define R_WDT_H + +#include "bsp_api.h" + +#include "r_wdt_cfg.h" +#include "r_wdt_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** WDT private control block. DO NOT MODIFY. Initialization occurs when R_WDT_Open() is called. */ +typedef struct st_wdt_instance_ctrl +{ + uint32_t wdt_open; // Indicates whether the open() API has been successfully + // called. + R_WDT0_Type * p_reg; // Base register for this channel + void const * p_context; // Placeholder for user data. Passed to the user callback in + // wdt_callback_args_t. + void (* p_callback)(wdt_callback_args_t * p_args); // Callback provided when a WDT ISR occurs. + wdt_callback_args_t * p_callback_memory; // Pointer to non-secure memory that can be used to pass arguments to a callback in non-secure memory. +} wdt_instance_ctrl_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const wdt_api_t g_wdt_on_wdt; + +/** @endcond */ + +/********************************************************************************************************************** + * Public Function Prototypes + **********************************************************************************************************************/ +fsp_err_t R_WDT_Refresh(wdt_ctrl_t * const p_ctrl); + +fsp_err_t R_WDT_Open(wdt_ctrl_t * const p_ctrl, wdt_cfg_t const * const p_cfg); + +fsp_err_t R_WDT_StatusClear(wdt_ctrl_t * const p_ctrl, const wdt_status_t status); + +fsp_err_t R_WDT_StatusGet(wdt_ctrl_t * const p_ctrl, wdt_status_t * const p_status); + +fsp_err_t R_WDT_CounterGet(wdt_ctrl_t * const p_ctrl, uint32_t * const p_count); + +fsp_err_t R_WDT_TimeoutGet(wdt_ctrl_t * const p_ctrl, wdt_timeout_values_t * const p_timeout); + +fsp_err_t R_WDT_CallbackSet(wdt_ctrl_t * const p_ctrl, + void ( * p_callback)(wdt_callback_args_t *), + void const * const p_context, + wdt_callback_args_t * const p_callback_memory); + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif // R_WDT_H + +/*******************************************************************************************************************//** + * @} (end addtogroup WDT) + **********************************************************************************************************************/ diff --git a/drivers/rz/fsp/inc/instances/rzt/r_wdt.h b/drivers/rz/fsp/inc/instances/rzt/r_wdt.h new file mode 100644 index 00000000..8f26adfd --- /dev/null +++ b/drivers/rz/fsp/inc/instances/rzt/r_wdt.h @@ -0,0 +1,80 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @addtogroup WDT WDT + * @{ + **********************************************************************************************************************/ + +#ifndef R_WDT_H +#define R_WDT_H + +#include "bsp_api.h" + +#include "r_wdt_cfg.h" +#include "r_wdt_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** WDT private control block. DO NOT MODIFY. Initialization occurs when R_WDT_Open() is called. */ +typedef struct st_wdt_instance_ctrl +{ + uint32_t wdt_open; // Indicates whether the open() API has been successfully + // called. + R_WDT0_Type * p_reg; // Base register for this channel + void const * p_context; // Placeholder for user data. Passed to the user callback in + // wdt_callback_args_t. + void (* p_callback)(wdt_callback_args_t * p_args); // Callback provided when a WDT ISR occurs. + wdt_callback_args_t * p_callback_memory; // Pointer to non-secure memory that can be used to pass arguments to a callback in non-secure memory. +} wdt_instance_ctrl_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const wdt_api_t g_wdt_on_wdt; + +/** @endcond */ + +/********************************************************************************************************************** + * Public Function Prototypes + **********************************************************************************************************************/ +fsp_err_t R_WDT_Refresh(wdt_ctrl_t * const p_ctrl); + +fsp_err_t R_WDT_Open(wdt_ctrl_t * const p_ctrl, wdt_cfg_t const * const p_cfg); + +fsp_err_t R_WDT_StatusClear(wdt_ctrl_t * const p_ctrl, const wdt_status_t status); + +fsp_err_t R_WDT_StatusGet(wdt_ctrl_t * const p_ctrl, wdt_status_t * const p_status); + +fsp_err_t R_WDT_CounterGet(wdt_ctrl_t * const p_ctrl, uint32_t * const p_count); + +fsp_err_t R_WDT_TimeoutGet(wdt_ctrl_t * const p_ctrl, wdt_timeout_values_t * const p_timeout); + +fsp_err_t R_WDT_CallbackSet(wdt_ctrl_t * const p_ctrl, + void ( * p_callback)(wdt_callback_args_t *), + void const * const p_context, + wdt_callback_args_t * const p_callback_memory); + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif // R_WDT_H + +/*******************************************************************************************************************//** + * @} (end addtogroup WDT) + **********************************************************************************************************************/ diff --git a/drivers/rz/fsp/src/rza/r_wdt/r_wdt.c b/drivers/rz/fsp/src/rza/r_wdt/r_wdt.c new file mode 100644 index 00000000..31f6c6ee --- /dev/null +++ b/drivers/rz/fsp/src/rza/r_wdt/r_wdt.c @@ -0,0 +1,445 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_wdt.h" +#include "bsp_api.h" +#include "bsp_cfg.h" + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +#define WDT_OPEN (0x00574454ULL) + +/* WDT register settings. */ +#define WDT_PRV_STATUS_FLAG_SET_POS (2U) +#define WDT_PRV_WDTSET_TIMEOUT_CALCURATE_VALUE (1024 * 1024) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +#if defined(__ARMCC_VERSION) || defined(__ICCARM__) +typedef void (BSP_CMSE_NONSECURE_CALL * wdt_prv_ns_callback)(wdt_callback_args_t * p_args); +#elif defined(__GNUC__) +typedef BSP_CMSE_NONSECURE_CALL void (*volatile wdt_prv_ns_callback)(wdt_callback_args_t * p_args); +#endif + +/*********************************************************************************************************************** + * Private function prototypes + **********************************************************************************************************************/ + +void wdt_overflow_isr(IRQn_Type const irq); + +static fsp_err_t r_wdt_parameter_checking(wdt_instance_ctrl_t * const p_instance_ctrl, wdt_cfg_t const * const p_cfg); + +static void r_wdt_overflow_callback(wdt_instance_ctrl_t * p_ctrl); + +/*********************************************************************************************************************** + * Private global variables + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Global variables + **********************************************************************************************************************/ + +/** Watchdog implementation of WDT Driver */ +const wdt_api_t g_wdt_on_wdt = +{ + .open = R_WDT_Open, + .refresh = R_WDT_Refresh, + .statusGet = R_WDT_StatusGet, + .statusClear = R_WDT_StatusClear, + .counterGet = R_WDT_CounterGet, + .timeoutGet = R_WDT_TimeoutGet, + .callbackSet = R_WDT_CallbackSet, +}; + +/*******************************************************************************************************************//** + * @addtogroup WDT WDT + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Configures the WDT driver based on the input configurations. This function sets the callback function, + * the timeout count value, and enables the overflow interrupt.Implements + * @ref wdt_api_t::open. + * + * This function should only be called once as WDT configuration registers can only be written to once so subsequent + * calls will have no effect. + * + * Example: + * @snippet r_wdt_example.c R_WDT_Open + * + * @retval FSP_SUCCESS WDT successfully configured. + * @retval FSP_ERR_ASSERTION Null pointer, or one or more configuration options is invalid. + * @retval FSP_ERR_ALREADY_OPEN Module is already open. This module can only be opened once. + **********************************************************************************************************************/ +fsp_err_t R_WDT_Open (wdt_ctrl_t * const p_ctrl, wdt_cfg_t const * const p_cfg) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + fsp_err_t err; + + /* Check validity of the parameters */ + err = r_wdt_parameter_checking(p_instance_ctrl, p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Set the callback function. */ + p_instance_ctrl->p_callback = p_cfg->p_callback; + p_instance_ctrl->p_context = p_cfg->p_context; + p_instance_ctrl->p_callback_memory = NULL; + + p_instance_ctrl->p_cfg = p_cfg; + + /* Clock On and Reset Off. */ + R_BSP_MODULE_START(FSP_IP_WDT, 0); + + /* Set the configuration registers in register start mode. */ + wdt_extended_cfg_t * p_extend = (wdt_extended_cfg_t *) p_cfg->p_extend; + R_WDT0->WDTSET = p_extend->wdt_timeout << R_WDT0_WDTSET_WDTTIME_Pos; + + /* Enable WDT Overflow interrupt. */ + if (NULL != p_instance_ctrl->p_callback) + { + R_BSP_IrqCfgEnable(p_extend->overflow_irq, p_extend->overflow_ipl, p_instance_ctrl); + } + + p_instance_ctrl->wdt_open = WDT_OPEN; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Read timeout information for the watchdog timer. Implements @ref wdt_api_t::timeoutGet. + * + * @retval FSP_SUCCESS WDT timeout information retrieved successfully. + * @retval FSP_ERR_ASSERTION Null Pointer. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_WDT_TimeoutGet (wdt_ctrl_t * const p_ctrl, wdt_timeout_values_t * const p_timeout) +{ +#if WDT_CFG_PARAM_CHECKING_ENABLE + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + FSP_ASSERT(NULL != p_timeout); + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + FSP_PARAMETER_NOT_USED(p_ctrl); + + /* Get timeout value from WDTTIM register. + * (see section 'WDT Period Setting Register_n (WDTSET_n)' of the user's manual)*/ + p_timeout->timeout_clocks = WDT_PRV_WDTSET_TIMEOUT_CALCURATE_VALUE * + ((R_WDT0->WDTSET >> R_WDT0_WDTSET_WDTTIME_Pos) + 1); + + /* Get the frequency of the clock supplying the watchdog */ + p_timeout->clock_frequency_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_OSCCLK); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Refresh the watchdog timer. Implements @ref wdt_api_t::refresh. + * + * In addition to refreshing the watchdog counter this function can be used to start the counter. + * + * Example: + * @snippet r_wdt_example.c R_WDT_Refresh + * + * @retval FSP_SUCCESS WDT successfully refreshed. + * @retval FSP_ERR_ASSERTION p_ctrl is NULL. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_WDT_Refresh (wdt_ctrl_t * const p_ctrl) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + +#if WDT_CFG_PARAM_CHECKING_ENABLE + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + if (0 == R_WDT0->WDTCNT_b.WDTEN) + { + /* Start the WDT. */ + R_WDT0->WDTCNT = R_WDT0_WDTCNT_WDTEN_Msk; + } + + /* WDT overflow interrupt flag is cleared. */ + R_WDT0->WDTINT = R_WDT0_WDTINT_INTDISP_Msk; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Read the WDT status flags. Implements @ref wdt_api_t::statusGet. + * + * Indicates both status and error conditions. + * + * Example: + * @snippet r_wdt_example.c R_WDT_StatusGet + * + * @retval FSP_SUCCESS WDT status successfully read. + * @retval FSP_ERR_ASSERTION Null pointer as a parameter. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_WDT_StatusGet (wdt_ctrl_t * const p_ctrl, wdt_status_t * const p_status) +{ +#if WDT_CFG_PARAM_CHECKING_ENABLE + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + FSP_ASSERT(NULL != p_status); + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#else + FSP_PARAMETER_NOT_USED(p_ctrl); +#endif + + /* Check for refresh or underflow errors. */ + *p_status = (wdt_status_t) (R_WDT0->WDTINT << WDT_PRV_STATUS_FLAG_SET_POS); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Clear the WDT status and error flags. Implements @ref wdt_api_t::statusClear. + * + * Example: + * @snippet r_wdt_example.c R_WDT_StatusClear + * + * @retval FSP_SUCCESS WDT flag(s) successfully cleared. + * @retval FSP_ERR_ASSERTION Null pointer as a parameter. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_WDT_StatusClear (wdt_ctrl_t * const p_ctrl, const wdt_status_t status) +{ + uint16_t value; + uint16_t read_value; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#else + FSP_PARAMETER_NOT_USED(p_ctrl); +#endif + + /* Casts to uint16_t to ensure value is handled as unsigned. */ + value = (uint16_t) status; + + /* Write zero to clear flags. */ + value = (uint16_t) (value >> WDT_PRV_STATUS_FLAG_SET_POS); + + /* Read back status flags until required flag(s) cleared. */ + /* Flags cannot be cleared until the clock cycle after they are set. */ + do + { + R_WDT0->WDTINT = value & R_WDT0_WDTINT_INTDISP_Msk; + read_value = (uint16_t) R_WDT0->WDTINT; + + /* Isolate flags to clear. */ + read_value &= (uint16_t) ((uint16_t) status >> WDT_PRV_STATUS_FLAG_SET_POS); + } while (0U != read_value); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Read the current count value of the WDT. Implements @ref wdt_api_t::counterGet. + * + * Example: + * @snippet r_wdt_example.c R_WDT_CounterGet + * + * @retval FSP_SUCCESS WDT current count successfully read. + * @retval FSP_ERR_ASSERTION Null pointer passed as a parameter. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_WDT_CounterGet (wdt_ctrl_t * const p_ctrl, uint32_t * const p_count) +{ +#if WDT_CFG_PARAM_CHECKING_ENABLE + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + FSP_ASSERT(NULL != p_count); + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#else + FSP_PARAMETER_NOT_USED(p_ctrl); +#endif + + /* Get the WDT counter value. */ + *p_count = R_WDT0->WDTTIM; + *p_count &= R_WDT0_WDTTIM_CRTTIME_Msk; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Updates the user callback and has option of providing memory for callback structure. + * Implements wdt_api_t::callbackSet + * + * @retval FSP_SUCCESS Callback updated successfully. + * @retval FSP_ERR_ASSERTION A required pointer is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_NO_CALLBACK_MEMORY p_callback is non-secure and p_callback_memory is either secure or NULL. + **********************************************************************************************************************/ +fsp_err_t R_WDT_CallbackSet (wdt_ctrl_t * const p_ctrl, + void ( * p_callback)(wdt_callback_args_t *), + void const * const p_context, + wdt_callback_args_t * const p_callback_memory) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + wdt_extended_cfg_t * p_extend = (wdt_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + /* Store callback and context */ +#if BSP_TZ_SECURE_BUILD + + /* Get security state of p_callback */ + bool callback_is_secure = + (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE)); + + #if WDT_CFG_PARAM_CHECKING_ENABLE + + /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */ + wdt_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory, + CMSE_AU_NONSECURE); + FSP_ERROR_RETURN(callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY); + #endif +#endif + + /* Store callback and context */ +#if BSP_TZ_SECURE_BUILD + p_instance_ctrl->p_callback = callback_is_secure ? p_callback : + (void (*)(wdt_callback_args_t *))cmse_nsfptr_create(p_callback); +#else + p_instance_ctrl->p_callback = p_callback; +#endif + p_instance_ctrl->p_context = p_context; + p_instance_ctrl->p_callback_memory = p_callback_memory; + + /* Enable WDT Overflow interrupt. */ + R_BSP_IrqCfgEnable(p_extend->overflow_irq, p_extend->overflow_ipl, p_instance_ctrl); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup WDT) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Internal WDT ISR callback which calls the user provided callback passing the context provided by the user. + * + * @param[in] p_ctrl Pointer to instance control structure + **********************************************************************************************************************/ +static void r_wdt_overflow_callback (wdt_instance_ctrl_t * p_ctrl) +{ + wdt_callback_args_t args; + + /* Store callback arguments in memory provided by user if available. This allows callback arguments to be + * stored in non-secure memory so they can be accessed by a non-secure callback function. */ + wdt_callback_args_t * p_args = p_ctrl->p_callback_memory; + if (NULL == p_args) + { + /* Store on stack */ + p_args = &args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args; + } + + p_args->p_context = p_ctrl->p_context; + +#if BSP_TZ_SECURE_BUILD + + /* p_callback can point to a secure function or a non-secure function. */ + if (!cmse_is_nsfptr(p_ctrl->p_callback)) + { + /* If p_callback is secure, then the project does not need to change security state. */ + p_ctrl->p_callback(p_args); + } + else + { + /* If p_callback is Non-secure, then the project must change to Non-secure state in order to call the callback. */ + wdt_prv_ns_callback p_callback = (wdt_prv_ns_callback) (p_ctrl->p_callback); + p_callback(p_args); + } + +#else + + /* If the project is not Trustzone Secure, then it will never need to change security state in order to call the callback. */ + p_ctrl->p_callback(p_args); +#endif + if (NULL != p_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_ctrl->p_callback_memory = args; + } +} + +/*******************************************************************************************************************//** + * Parameter checking function for WDT Open + * + * @param[in] p_instance_ctrl Pointer to instance control structure + * @param[in] p_cfg Pointer to configuration structure + * + * @retval FSP_SUCCESS WDT successfully configured. + * @retval FSP_ERR_ASSERTION Null pointer, or one or more configuration options is invalid. + * @retval FSP_ERR_ALREADY_OPEN Module is already open. This module can only be opened once. + **********************************************************************************************************************/ +static fsp_err_t r_wdt_parameter_checking (wdt_instance_ctrl_t * const p_instance_ctrl, wdt_cfg_t const * const p_cfg) +{ +#if WDT_CFG_PARAM_CHECKING_ENABLE + + /* Check that control and config structure pointers are valid. */ + FSP_ASSERT(NULL != p_cfg); + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN != p_instance_ctrl->wdt_open, FSP_ERR_ALREADY_OPEN); + FSP_ASSERT(NULL != p_cfg->p_extend); +#else + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + FSP_PARAMETER_NOT_USED(p_cfg); +#endif + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * WDT Overflow ISR + **********************************************************************************************************************/ +void wdt_overflow_isr (IRQn_Type const irq) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + wdt_instance_ctrl_t * p_ctrl = (wdt_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + + if (NULL != p_ctrl->p_callback) + { + /* Call the callback function. */ + r_wdt_overflow_callback(p_ctrl); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} diff --git a/drivers/rz/fsp/src/rzn/r_wdt/r_wdt.c b/drivers/rz/fsp/src/rzn/r_wdt/r_wdt.c new file mode 100644 index 00000000..e9a6a460 --- /dev/null +++ b/drivers/rz/fsp/src/rzn/r_wdt/r_wdt.c @@ -0,0 +1,490 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_wdt.h" +#include "bsp_api.h" +#include "bsp_cfg.h" + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +#define WDT_OPEN (0X00574454ULL) + +/* Lookup functions for WDT settings. Using function like macro for stringification. */ +#define WDT_PRV_WDTCR_SETTING_GET(setting, \ + wdtcr) (((wdtcr >> WDT_PRV_WDTCR_ ## setting ## _BIT) & \ + WDT_PRV_WDTCR_ ## setting ## _MASK)); +#define WDT_PRV_WDTCR_SETTING_SET(setting, \ + value) ((value & WDT_PRV_WDTCR_ ## setting ## _MASK) << \ + WDT_PRV_WDTCR_ ## setting ## _BIT); + +/* WDT register settings. */ +#define WDT_PRV_WDTSR_COUNTER_MASK (0x3FFFU) +#define WDT_PRV_WDTSR_FLAGS_MASK (0xC000U) + +#define WDT_PRV_WDTCR_TIMEOUT_BIT (0) +#define WDT_PRV_WDTCR_CLOCK_DIVISION_BIT (4) +#define WDT_PRV_WDTCR_WINDOW_END_BIT (8) +#define WDT_PRV_WDTCR_WINDOW_START_BIT (12) + +#define WDT_PRV_WDTRCR_RESET_CONTROL_BIT (7) +#define WDT_PRV_WDTCSTPR_STOP_CONTROL_BIT (7) + +#define WDT_PRV_WDTCR_TIMEOUT_MASK (0x3U) // Bits 0-1 +#define WDT_PRV_WDTCR_CLOCK_DIVISION_MASK (0xFU) // Bits 4-7 +#define WDT_PRV_WDTCR_WINDOW_END_MASK (0x3U) // Bits 8-9 +#define WDT_PRV_WDTCR_WINDOW_START_MASK (0x3U) // Bits 12-13 + +/* Refresh register values */ +#define WDT_PRV_REFRESH_STEP_1 (0U) +#define WDT_PRV_REFRESH_STEP_2 (0xFFU) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private function prototypes + **********************************************************************************************************************/ +static uint32_t r_wdt_clock_divider_get(wdt_clock_division_t division); + +static fsp_err_t r_wdt_parameter_checking(wdt_instance_ctrl_t * const p_instance_ctrl, wdt_cfg_t const * const p_cfg); + +/*********************************************************************************************************************** + * ISR prototypes + **********************************************************************************************************************/ +void wdt_underflow_isr(uint32_t id); + +/*********************************************************************************************************************** + * Private global variables + **********************************************************************************************************************/ +static const uint8_t g_wdtcr_timeout[] = +{ + 0xFFU, // WDTCR value for WDT_TIMEOUT_128 (not supported by WDT). + 0xFFU, // WDTCR value for WDT_TIMEOUT_512 (not supported by WDT). + 0x00U, // WDTCR value for WDT_TIMEOUT_1024. + 0xFFU, // WDTCR value for WDT_TIMEOUT_2048 (not supported by WDT). + 0x01U, // WDTCR value for WDT_TIMEOUT_4096. + 0x02U, // WDTCR value for WDT_TIMEOUT_8192. + 0x03U, // WDTCR value for WDT_TIMEOUT_16384. +}; + +/* Convert WDT timeout value to an integer */ +static const uint32_t g_wdt_timeout[] = +{ + 128U, + 512U, + 1024U, + 2048U, + 4096U, + 8192U, + 16384U +}; + +/* Converts WDT division enum to log base 2 of the division value, used to shift the PCLKL frequency. */ +static const uint8_t g_wdt_division_lookup[] = +{ + 0U, // log base 2(1) = 0 + 2U, // log base 2(4) = 2 + 4U, // log base 2(16) = 4 + 5U, // log base 2(32) = 5 + 6U, // log base 2(64) = 6 + 8U, // log base 2(256) = 8 + 9U, // log base 2(512) = 9 + 11U, // log base 2(2048) = 11 + 13U, // log base 2(8192) = 13 +}; + +/** Global pointer to control structure for use by the callback. */ +static volatile wdt_instance_ctrl_t * gp_wdt_ctrl = NULL; + +/*********************************************************************************************************************** + * Global variables + **********************************************************************************************************************/ + +/** Watchdog implementation of WDT Driver */ +const wdt_api_t g_wdt_on_wdt = +{ + .open = R_WDT_Open, + .refresh = R_WDT_Refresh, + .statusGet = R_WDT_StatusGet, + .statusClear = R_WDT_StatusClear, + .counterGet = R_WDT_CounterGet, + .timeoutGet = R_WDT_TimeoutGet, + .callbackSet = R_WDT_CallbackSet, +}; + +/*******************************************************************************************************************//** + * @addtogroup WDT WDT + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Configure the WDT in register start mode. Implements + * @ref wdt_api_t::open. + * + * This function should only be called once as WDT configuration registers can only be written to once so subsequent + * calls will have no effect. + * + * @retval FSP_SUCCESS WDT successfully configured. + * @retval FSP_ERR_ASSERTION Null pointer, or one or more configuration options is invalid. + * @retval FSP_ERR_ALREADY_OPEN Module is already open. This module can only be opened once. + **********************************************************************************************************************/ +fsp_err_t R_WDT_Open (wdt_ctrl_t * const p_ctrl, wdt_cfg_t const * const p_cfg) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + fsp_err_t err; + + /* Check validity of the parameters */ + err = r_wdt_parameter_checking(p_instance_ctrl, p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Register callback. */ + p_instance_ctrl->p_callback = p_cfg->p_callback; + p_instance_ctrl->p_context = p_cfg->p_context; + +#ifdef BSP_CFG_CORE_CR52 + #if (0 == BSP_CFG_CORE_CR52) + p_instance_ctrl->p_reg = R_WDT0; + #elif (1 == BSP_CFG_CORE_CR52) + p_instance_ctrl->p_reg = R_WDT1; + #endif +#endif +#ifdef BSP_CFG_CORE_CA55 + #if (0 == BSP_CFG_CORE_CA55) + p_instance_ctrl->p_reg = R_WDT2; + #elif (1 == BSP_CFG_CORE_CA55) + p_instance_ctrl->p_reg = R_WDT3; + #elif (2 == BSP_CFG_CORE_CA55) + p_instance_ctrl->p_reg = R_WDT4; + #elif (3 == BSP_CFG_CORE_CA55) + p_instance_ctrl->p_reg = R_WDT5; + #endif +#endif + + /* Error notification to ICU is permitted. */ + p_instance_ctrl->p_reg->WDTRCR_b.RSTIRQS = 0; + + uint32_t wdtcr = WDT_PRV_WDTCR_SETTING_SET(TIMEOUT, (uint16_t) g_wdtcr_timeout[p_cfg->timeout]); + wdtcr |= WDT_PRV_WDTCR_SETTING_SET(CLOCK_DIVISION, (uint16_t) p_cfg->clock_division); + wdtcr |= WDT_PRV_WDTCR_SETTING_SET(WINDOW_START, (uint16_t) p_cfg->window_start); + wdtcr |= WDT_PRV_WDTCR_SETTING_SET(WINDOW_END, (uint16_t) p_cfg->window_end); + + p_instance_ctrl->p_reg->WDTCR = (uint16_t) wdtcr; + + gp_wdt_ctrl = p_ctrl; + + p_instance_ctrl->wdt_open = WDT_OPEN; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Read timeout information for the watchdog timer. Implements @ref wdt_api_t::timeoutGet. + * + * @retval FSP_SUCCESS WDT timeout information retrieved successfully. + * @retval FSP_ERR_ASSERTION Null Pointer. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_WDT_TimeoutGet (wdt_ctrl_t * const p_ctrl, wdt_timeout_values_t * const p_timeout) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_timeout); + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + uint32_t shift; + uint32_t index; + uint32_t timeout = 0; + wdt_clock_division_t clock_division; + + /* Read the configuration of the watchdog */ + uint32_t wdtcr = p_instance_ctrl->p_reg->WDTCR; + clock_division = (wdt_clock_division_t) WDT_PRV_WDTCR_SETTING_GET(CLOCK_DIVISION, wdtcr); + timeout = WDT_PRV_WDTCR_SETTING_GET(TIMEOUT, wdtcr); + + /* Get timeout value from WDTCR register. */ + for (index = 0U; index < (sizeof(g_wdtcr_timeout)); index++) + { + if (g_wdtcr_timeout[index] == timeout) + { + p_timeout->timeout_clocks = g_wdt_timeout[index]; + } + } + + /* Get the frequency of the clock supplying the watchdog */ + uint32_t pckl_frequency = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKL); + shift = r_wdt_clock_divider_get(clock_division); + + p_timeout->clock_frequency_hz = pckl_frequency >> shift; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Refresh the watchdog timer. Implements @ref wdt_api_t::refresh. + * + * In addition to refreshing the watchdog counter this function can be used to start the counter in register start mode. + * + * @retval FSP_SUCCESS WDT successfully refreshed. + * @retval FSP_ERR_ASSERTION p_ctrl is NULL. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + * + * @note This function only returns FSP_SUCCESS. If the refresh fails due to being performed outside of the + * permitted refresh period the device will trigger an ISR to run. + **********************************************************************************************************************/ +fsp_err_t R_WDT_Refresh (wdt_ctrl_t * const p_ctrl) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + p_instance_ctrl->p_reg->WDTRR = WDT_PRV_REFRESH_STEP_1; + p_instance_ctrl->p_reg->WDTRR = WDT_PRV_REFRESH_STEP_2; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Read the WDT status flags. Implements @ref wdt_api_t::statusGet. + * + * Indicates both status and error conditions. + * + * @retval FSP_SUCCESS WDT status successfully read. + * @retval FSP_ERR_ASSERTION Null pointer as a parameter. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_WDT_StatusGet (wdt_ctrl_t * const p_ctrl, wdt_status_t * const p_status) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_status); + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + /* Check for refresh or underflow errors. */ + *p_status = (wdt_status_t) (p_instance_ctrl->p_reg->WDTSR >> 14); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Clear the WDT status and error flags. Implements @ref wdt_api_t::statusClear. + * + * @retval FSP_SUCCESS WDT flag(s) successfully cleared. + * @retval FSP_ERR_ASSERTION Null pointer as a parameter. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_WDT_StatusClear (wdt_ctrl_t * const p_ctrl, const wdt_status_t status) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + + uint16_t value; + uint16_t read_value; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + /* Casts to uint16_t to ensure value is handled as unsigned. */ + value = (uint16_t) status; + + /* Write zero to clear flags. */ + value = (uint16_t) ~value; + value = (uint16_t) (value << 14); + + /* Read back status flags until required flag(s) cleared. */ + /* Flags cannot be cleared until the clock cycle after they are set. */ + do + { + p_instance_ctrl->p_reg->WDTSR = value; + read_value = p_instance_ctrl->p_reg->WDTSR; + + /* Isolate flags to clear. */ + read_value &= (uint16_t) ((uint16_t) status << 14); + } while (0U != read_value); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Read the current count value of the WDT. Implements @ref wdt_api_t::counterGet. + * + * @retval FSP_SUCCESS WDT current count successfully read. + * @retval FSP_ERR_ASSERTION Null pointer passed as a parameter. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_WDT_CounterGet (wdt_ctrl_t * const p_ctrl, uint32_t * const p_count) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_count); + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + *p_count = (uint32_t) p_instance_ctrl->p_reg->WDTSR; + *p_count &= WDT_PRV_WDTSR_COUNTER_MASK; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Updates the user callback and has option of providing memory for callback structure. + * Implements wdt_api_t::callbackSet + * + * @retval FSP_SUCCESS Callback updated successfully. + * @retval FSP_ERR_ASSERTION A required pointer is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + **********************************************************************************************************************/ +fsp_err_t R_WDT_CallbackSet (wdt_ctrl_t * const p_ctrl, + void ( * p_callback)(wdt_callback_args_t *), + void const * const p_context, + wdt_callback_args_t * const p_callback_memory) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + /* Store callback and context */ + p_instance_ctrl->p_callback = p_callback; + p_instance_ctrl->p_context = p_context; + p_instance_ctrl->p_callback_memory = p_callback_memory; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup WDT) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Gets clock division shift value. + * + * @param[in] division Right shift value used to divide clock frequency. + **********************************************************************************************************************/ +static uint32_t r_wdt_clock_divider_get (wdt_clock_division_t division) +{ + uint32_t shift; + + if (WDT_CLOCK_DIVISION_128 == division) + { + shift = 7U; /* log base 2(128) = 7 */ + } + else + { + shift = g_wdt_division_lookup[division]; + } + + return shift; +} + +/*******************************************************************************************************************//** + * Parameter checking function for WDT Open + * + * @param[in] p_instance_ctrl Pointer to instance control structure + * @param[in] p_cfg Pointer to configuration structure + * + * @retval FSP_SUCCESS WDT successfully configured. + * @retval FSP_ERR_ASSERTION Null pointer, or one or more configuration options is invalid. + * @retval FSP_ERR_ALREADY_OPEN Module is already open. This module can only be opened once. + **********************************************************************************************************************/ +static fsp_err_t r_wdt_parameter_checking (wdt_instance_ctrl_t * const p_instance_ctrl, wdt_cfg_t const * const p_cfg) +{ +#if WDT_CFG_PARAM_CHECKING_ENABLE + + /* Check that control and config structure pointers are valid. */ + FSP_ASSERT(NULL != p_cfg); + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN != p_instance_ctrl->wdt_open, FSP_ERR_ALREADY_OPEN); + + /* Check timeout parameter is supported by WDT. */ + + /* Enum checking is done here because some enums in wdt_timeout_t are not supported by the WDT peripheral (they are + * included for other implementations of the watchdog interface). */ + FSP_ASSERT((p_cfg->timeout == WDT_TIMEOUT_1024) || (p_cfg->timeout == WDT_TIMEOUT_4096) || \ + (p_cfg->timeout == WDT_TIMEOUT_8192) || (p_cfg->timeout == WDT_TIMEOUT_16384)); +#else + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + FSP_PARAMETER_NOT_USED(p_cfg); +#endif + + return FSP_SUCCESS; +} + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * WDT ISR. + **********************************************************************************************************************/ +void wdt_underflow_isr (uint32_t id) +{ + WDT_CFG_MULTIPLEX_INTERRUPT_ENABLE; + + FSP_PARAMETER_NOT_USED(id); + + /* Call user registered callback */ + if (NULL != gp_wdt_ctrl) + { + if (NULL != gp_wdt_ctrl->p_callback) + { + wdt_callback_args_t args; + + /* Store callback arguments in memory provided by user if available. */ + wdt_callback_args_t * p_args = gp_wdt_ctrl->p_callback_memory; + if (NULL == p_args) + { + /* Store on stack */ + p_args = &args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args; + } + + p_args->p_context = gp_wdt_ctrl->p_context; + + gp_wdt_ctrl->p_callback(p_args); + + if (NULL != gp_wdt_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *gp_wdt_ctrl->p_callback_memory = args; + } + } + } + + WDT_CFG_MULTIPLEX_INTERRUPT_DISABLE; +} diff --git a/drivers/rz/fsp/src/rzt/r_wdt/r_wdt.c b/drivers/rz/fsp/src/rzt/r_wdt/r_wdt.c new file mode 100644 index 00000000..e9a6a460 --- /dev/null +++ b/drivers/rz/fsp/src/rzt/r_wdt/r_wdt.c @@ -0,0 +1,490 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_wdt.h" +#include "bsp_api.h" +#include "bsp_cfg.h" + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +#define WDT_OPEN (0X00574454ULL) + +/* Lookup functions for WDT settings. Using function like macro for stringification. */ +#define WDT_PRV_WDTCR_SETTING_GET(setting, \ + wdtcr) (((wdtcr >> WDT_PRV_WDTCR_ ## setting ## _BIT) & \ + WDT_PRV_WDTCR_ ## setting ## _MASK)); +#define WDT_PRV_WDTCR_SETTING_SET(setting, \ + value) ((value & WDT_PRV_WDTCR_ ## setting ## _MASK) << \ + WDT_PRV_WDTCR_ ## setting ## _BIT); + +/* WDT register settings. */ +#define WDT_PRV_WDTSR_COUNTER_MASK (0x3FFFU) +#define WDT_PRV_WDTSR_FLAGS_MASK (0xC000U) + +#define WDT_PRV_WDTCR_TIMEOUT_BIT (0) +#define WDT_PRV_WDTCR_CLOCK_DIVISION_BIT (4) +#define WDT_PRV_WDTCR_WINDOW_END_BIT (8) +#define WDT_PRV_WDTCR_WINDOW_START_BIT (12) + +#define WDT_PRV_WDTRCR_RESET_CONTROL_BIT (7) +#define WDT_PRV_WDTCSTPR_STOP_CONTROL_BIT (7) + +#define WDT_PRV_WDTCR_TIMEOUT_MASK (0x3U) // Bits 0-1 +#define WDT_PRV_WDTCR_CLOCK_DIVISION_MASK (0xFU) // Bits 4-7 +#define WDT_PRV_WDTCR_WINDOW_END_MASK (0x3U) // Bits 8-9 +#define WDT_PRV_WDTCR_WINDOW_START_MASK (0x3U) // Bits 12-13 + +/* Refresh register values */ +#define WDT_PRV_REFRESH_STEP_1 (0U) +#define WDT_PRV_REFRESH_STEP_2 (0xFFU) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private function prototypes + **********************************************************************************************************************/ +static uint32_t r_wdt_clock_divider_get(wdt_clock_division_t division); + +static fsp_err_t r_wdt_parameter_checking(wdt_instance_ctrl_t * const p_instance_ctrl, wdt_cfg_t const * const p_cfg); + +/*********************************************************************************************************************** + * ISR prototypes + **********************************************************************************************************************/ +void wdt_underflow_isr(uint32_t id); + +/*********************************************************************************************************************** + * Private global variables + **********************************************************************************************************************/ +static const uint8_t g_wdtcr_timeout[] = +{ + 0xFFU, // WDTCR value for WDT_TIMEOUT_128 (not supported by WDT). + 0xFFU, // WDTCR value for WDT_TIMEOUT_512 (not supported by WDT). + 0x00U, // WDTCR value for WDT_TIMEOUT_1024. + 0xFFU, // WDTCR value for WDT_TIMEOUT_2048 (not supported by WDT). + 0x01U, // WDTCR value for WDT_TIMEOUT_4096. + 0x02U, // WDTCR value for WDT_TIMEOUT_8192. + 0x03U, // WDTCR value for WDT_TIMEOUT_16384. +}; + +/* Convert WDT timeout value to an integer */ +static const uint32_t g_wdt_timeout[] = +{ + 128U, + 512U, + 1024U, + 2048U, + 4096U, + 8192U, + 16384U +}; + +/* Converts WDT division enum to log base 2 of the division value, used to shift the PCLKL frequency. */ +static const uint8_t g_wdt_division_lookup[] = +{ + 0U, // log base 2(1) = 0 + 2U, // log base 2(4) = 2 + 4U, // log base 2(16) = 4 + 5U, // log base 2(32) = 5 + 6U, // log base 2(64) = 6 + 8U, // log base 2(256) = 8 + 9U, // log base 2(512) = 9 + 11U, // log base 2(2048) = 11 + 13U, // log base 2(8192) = 13 +}; + +/** Global pointer to control structure for use by the callback. */ +static volatile wdt_instance_ctrl_t * gp_wdt_ctrl = NULL; + +/*********************************************************************************************************************** + * Global variables + **********************************************************************************************************************/ + +/** Watchdog implementation of WDT Driver */ +const wdt_api_t g_wdt_on_wdt = +{ + .open = R_WDT_Open, + .refresh = R_WDT_Refresh, + .statusGet = R_WDT_StatusGet, + .statusClear = R_WDT_StatusClear, + .counterGet = R_WDT_CounterGet, + .timeoutGet = R_WDT_TimeoutGet, + .callbackSet = R_WDT_CallbackSet, +}; + +/*******************************************************************************************************************//** + * @addtogroup WDT WDT + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Configure the WDT in register start mode. Implements + * @ref wdt_api_t::open. + * + * This function should only be called once as WDT configuration registers can only be written to once so subsequent + * calls will have no effect. + * + * @retval FSP_SUCCESS WDT successfully configured. + * @retval FSP_ERR_ASSERTION Null pointer, or one or more configuration options is invalid. + * @retval FSP_ERR_ALREADY_OPEN Module is already open. This module can only be opened once. + **********************************************************************************************************************/ +fsp_err_t R_WDT_Open (wdt_ctrl_t * const p_ctrl, wdt_cfg_t const * const p_cfg) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + fsp_err_t err; + + /* Check validity of the parameters */ + err = r_wdt_parameter_checking(p_instance_ctrl, p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Register callback. */ + p_instance_ctrl->p_callback = p_cfg->p_callback; + p_instance_ctrl->p_context = p_cfg->p_context; + +#ifdef BSP_CFG_CORE_CR52 + #if (0 == BSP_CFG_CORE_CR52) + p_instance_ctrl->p_reg = R_WDT0; + #elif (1 == BSP_CFG_CORE_CR52) + p_instance_ctrl->p_reg = R_WDT1; + #endif +#endif +#ifdef BSP_CFG_CORE_CA55 + #if (0 == BSP_CFG_CORE_CA55) + p_instance_ctrl->p_reg = R_WDT2; + #elif (1 == BSP_CFG_CORE_CA55) + p_instance_ctrl->p_reg = R_WDT3; + #elif (2 == BSP_CFG_CORE_CA55) + p_instance_ctrl->p_reg = R_WDT4; + #elif (3 == BSP_CFG_CORE_CA55) + p_instance_ctrl->p_reg = R_WDT5; + #endif +#endif + + /* Error notification to ICU is permitted. */ + p_instance_ctrl->p_reg->WDTRCR_b.RSTIRQS = 0; + + uint32_t wdtcr = WDT_PRV_WDTCR_SETTING_SET(TIMEOUT, (uint16_t) g_wdtcr_timeout[p_cfg->timeout]); + wdtcr |= WDT_PRV_WDTCR_SETTING_SET(CLOCK_DIVISION, (uint16_t) p_cfg->clock_division); + wdtcr |= WDT_PRV_WDTCR_SETTING_SET(WINDOW_START, (uint16_t) p_cfg->window_start); + wdtcr |= WDT_PRV_WDTCR_SETTING_SET(WINDOW_END, (uint16_t) p_cfg->window_end); + + p_instance_ctrl->p_reg->WDTCR = (uint16_t) wdtcr; + + gp_wdt_ctrl = p_ctrl; + + p_instance_ctrl->wdt_open = WDT_OPEN; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Read timeout information for the watchdog timer. Implements @ref wdt_api_t::timeoutGet. + * + * @retval FSP_SUCCESS WDT timeout information retrieved successfully. + * @retval FSP_ERR_ASSERTION Null Pointer. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_WDT_TimeoutGet (wdt_ctrl_t * const p_ctrl, wdt_timeout_values_t * const p_timeout) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_timeout); + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + uint32_t shift; + uint32_t index; + uint32_t timeout = 0; + wdt_clock_division_t clock_division; + + /* Read the configuration of the watchdog */ + uint32_t wdtcr = p_instance_ctrl->p_reg->WDTCR; + clock_division = (wdt_clock_division_t) WDT_PRV_WDTCR_SETTING_GET(CLOCK_DIVISION, wdtcr); + timeout = WDT_PRV_WDTCR_SETTING_GET(TIMEOUT, wdtcr); + + /* Get timeout value from WDTCR register. */ + for (index = 0U; index < (sizeof(g_wdtcr_timeout)); index++) + { + if (g_wdtcr_timeout[index] == timeout) + { + p_timeout->timeout_clocks = g_wdt_timeout[index]; + } + } + + /* Get the frequency of the clock supplying the watchdog */ + uint32_t pckl_frequency = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKL); + shift = r_wdt_clock_divider_get(clock_division); + + p_timeout->clock_frequency_hz = pckl_frequency >> shift; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Refresh the watchdog timer. Implements @ref wdt_api_t::refresh. + * + * In addition to refreshing the watchdog counter this function can be used to start the counter in register start mode. + * + * @retval FSP_SUCCESS WDT successfully refreshed. + * @retval FSP_ERR_ASSERTION p_ctrl is NULL. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + * + * @note This function only returns FSP_SUCCESS. If the refresh fails due to being performed outside of the + * permitted refresh period the device will trigger an ISR to run. + **********************************************************************************************************************/ +fsp_err_t R_WDT_Refresh (wdt_ctrl_t * const p_ctrl) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + p_instance_ctrl->p_reg->WDTRR = WDT_PRV_REFRESH_STEP_1; + p_instance_ctrl->p_reg->WDTRR = WDT_PRV_REFRESH_STEP_2; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Read the WDT status flags. Implements @ref wdt_api_t::statusGet. + * + * Indicates both status and error conditions. + * + * @retval FSP_SUCCESS WDT status successfully read. + * @retval FSP_ERR_ASSERTION Null pointer as a parameter. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_WDT_StatusGet (wdt_ctrl_t * const p_ctrl, wdt_status_t * const p_status) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_status); + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + /* Check for refresh or underflow errors. */ + *p_status = (wdt_status_t) (p_instance_ctrl->p_reg->WDTSR >> 14); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Clear the WDT status and error flags. Implements @ref wdt_api_t::statusClear. + * + * @retval FSP_SUCCESS WDT flag(s) successfully cleared. + * @retval FSP_ERR_ASSERTION Null pointer as a parameter. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_WDT_StatusClear (wdt_ctrl_t * const p_ctrl, const wdt_status_t status) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + + uint16_t value; + uint16_t read_value; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + /* Casts to uint16_t to ensure value is handled as unsigned. */ + value = (uint16_t) status; + + /* Write zero to clear flags. */ + value = (uint16_t) ~value; + value = (uint16_t) (value << 14); + + /* Read back status flags until required flag(s) cleared. */ + /* Flags cannot be cleared until the clock cycle after they are set. */ + do + { + p_instance_ctrl->p_reg->WDTSR = value; + read_value = p_instance_ctrl->p_reg->WDTSR; + + /* Isolate flags to clear. */ + read_value &= (uint16_t) ((uint16_t) status << 14); + } while (0U != read_value); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Read the current count value of the WDT. Implements @ref wdt_api_t::counterGet. + * + * @retval FSP_SUCCESS WDT current count successfully read. + * @retval FSP_ERR_ASSERTION Null pointer passed as a parameter. + * @retval FSP_ERR_NOT_OPEN Instance control block is not initialized. + **********************************************************************************************************************/ +fsp_err_t R_WDT_CounterGet (wdt_ctrl_t * const p_ctrl, uint32_t * const p_count) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_count); + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + *p_count = (uint32_t) p_instance_ctrl->p_reg->WDTSR; + *p_count &= WDT_PRV_WDTSR_COUNTER_MASK; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Updates the user callback and has option of providing memory for callback structure. + * Implements wdt_api_t::callbackSet + * + * @retval FSP_SUCCESS Callback updated successfully. + * @retval FSP_ERR_ASSERTION A required pointer is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + **********************************************************************************************************************/ +fsp_err_t R_WDT_CallbackSet (wdt_ctrl_t * const p_ctrl, + void ( * p_callback)(wdt_callback_args_t *), + void const * const p_context, + wdt_callback_args_t * const p_callback_memory) +{ + wdt_instance_ctrl_t * p_instance_ctrl = (wdt_instance_ctrl_t *) p_ctrl; + +#if WDT_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(WDT_OPEN == p_instance_ctrl->wdt_open, FSP_ERR_NOT_OPEN); +#endif + + /* Store callback and context */ + p_instance_ctrl->p_callback = p_callback; + p_instance_ctrl->p_context = p_context; + p_instance_ctrl->p_callback_memory = p_callback_memory; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup WDT) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Gets clock division shift value. + * + * @param[in] division Right shift value used to divide clock frequency. + **********************************************************************************************************************/ +static uint32_t r_wdt_clock_divider_get (wdt_clock_division_t division) +{ + uint32_t shift; + + if (WDT_CLOCK_DIVISION_128 == division) + { + shift = 7U; /* log base 2(128) = 7 */ + } + else + { + shift = g_wdt_division_lookup[division]; + } + + return shift; +} + +/*******************************************************************************************************************//** + * Parameter checking function for WDT Open + * + * @param[in] p_instance_ctrl Pointer to instance control structure + * @param[in] p_cfg Pointer to configuration structure + * + * @retval FSP_SUCCESS WDT successfully configured. + * @retval FSP_ERR_ASSERTION Null pointer, or one or more configuration options is invalid. + * @retval FSP_ERR_ALREADY_OPEN Module is already open. This module can only be opened once. + **********************************************************************************************************************/ +static fsp_err_t r_wdt_parameter_checking (wdt_instance_ctrl_t * const p_instance_ctrl, wdt_cfg_t const * const p_cfg) +{ +#if WDT_CFG_PARAM_CHECKING_ENABLE + + /* Check that control and config structure pointers are valid. */ + FSP_ASSERT(NULL != p_cfg); + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(WDT_OPEN != p_instance_ctrl->wdt_open, FSP_ERR_ALREADY_OPEN); + + /* Check timeout parameter is supported by WDT. */ + + /* Enum checking is done here because some enums in wdt_timeout_t are not supported by the WDT peripheral (they are + * included for other implementations of the watchdog interface). */ + FSP_ASSERT((p_cfg->timeout == WDT_TIMEOUT_1024) || (p_cfg->timeout == WDT_TIMEOUT_4096) || \ + (p_cfg->timeout == WDT_TIMEOUT_8192) || (p_cfg->timeout == WDT_TIMEOUT_16384)); +#else + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + FSP_PARAMETER_NOT_USED(p_cfg); +#endif + + return FSP_SUCCESS; +} + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * WDT ISR. + **********************************************************************************************************************/ +void wdt_underflow_isr (uint32_t id) +{ + WDT_CFG_MULTIPLEX_INTERRUPT_ENABLE; + + FSP_PARAMETER_NOT_USED(id); + + /* Call user registered callback */ + if (NULL != gp_wdt_ctrl) + { + if (NULL != gp_wdt_ctrl->p_callback) + { + wdt_callback_args_t args; + + /* Store callback arguments in memory provided by user if available. */ + wdt_callback_args_t * p_args = gp_wdt_ctrl->p_callback_memory; + if (NULL == p_args) + { + /* Store on stack */ + p_args = &args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args; + } + + p_args->p_context = gp_wdt_ctrl->p_context; + + gp_wdt_ctrl->p_callback(p_args); + + if (NULL != gp_wdt_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *gp_wdt_ctrl->p_callback_memory = args; + } + } + } + + WDT_CFG_MULTIPLEX_INTERRUPT_DISABLE; +} diff --git a/zephyr/rz/rz_cfg/fsp_cfg/rza/r_wdt_cfg.h b/zephyr/rz/rz_cfg/fsp_cfg/rza/r_wdt_cfg.h new file mode 100644 index 00000000..9d0dc2e0 --- /dev/null +++ b/zephyr/rz/rz_cfg/fsp_cfg/rza/r_wdt_cfg.h @@ -0,0 +1,18 @@ +/* +* Copyright (c) 2020 - 2025 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_WDT_CFG_H_ +#define R_WDT_CFG_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#define WDT_CFG_PARAM_CHECKING_ENABLE BSP_CFG_PARAM_CHECKING_ENABLE + +#ifdef __cplusplus +} +#endif +#endif /* R_WDT_CFG_H_ */ diff --git a/zephyr/rz/rz_cfg/fsp_cfg/rzn/r_wdt_cfg.h b/zephyr/rz/rz_cfg/fsp_cfg/rzn/r_wdt_cfg.h new file mode 100644 index 00000000..d2569d12 --- /dev/null +++ b/zephyr/rz/rz_cfg/fsp_cfg/rzn/r_wdt_cfg.h @@ -0,0 +1,18 @@ +/* +* Copyright (c) 2020 - 2025 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_WDT_CFG_H_ +#define R_WDT_CFG_H_ +#define WDT_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#define WDT_CFG_MULTIPLEX_INTERRUPT_SUPPORTED (0) +#if WDT_CFG_MULTIPLEX_INTERRUPT_SUPPORTED +#define WDT_CFG_MULTIPLEX_INTERRUPT_ENABLE BSP_INTERRUPT_ENABLE +#define WDT_CFG_MULTIPLEX_INTERRUPT_DISABLE BSP_INTERRUPT_DISABLE +#else +#define WDT_CFG_MULTIPLEX_INTERRUPT_ENABLE +#define WDT_CFG_MULTIPLEX_INTERRUPT_DISABLE +#endif +#endif /* R_WDT_CFG_H_ */ diff --git a/zephyr/rz/rz_cfg/fsp_cfg/rzt/r_wdt_cfg.h b/zephyr/rz/rz_cfg/fsp_cfg/rzt/r_wdt_cfg.h new file mode 100644 index 00000000..d2569d12 --- /dev/null +++ b/zephyr/rz/rz_cfg/fsp_cfg/rzt/r_wdt_cfg.h @@ -0,0 +1,18 @@ +/* +* Copyright (c) 2020 - 2025 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_WDT_CFG_H_ +#define R_WDT_CFG_H_ +#define WDT_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#define WDT_CFG_MULTIPLEX_INTERRUPT_SUPPORTED (0) +#if WDT_CFG_MULTIPLEX_INTERRUPT_SUPPORTED +#define WDT_CFG_MULTIPLEX_INTERRUPT_ENABLE BSP_INTERRUPT_ENABLE +#define WDT_CFG_MULTIPLEX_INTERRUPT_DISABLE BSP_INTERRUPT_DISABLE +#else +#define WDT_CFG_MULTIPLEX_INTERRUPT_ENABLE +#define WDT_CFG_MULTIPLEX_INTERRUPT_DISABLE +#endif +#endif /* R_WDT_CFG_H_ */