mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
408 lines
11 KiB
C
408 lines
11 KiB
C
/* Copyright (C) 2022 Alif Semiconductor - All Rights Reserved.
|
|
* Use, distribution and modification of this code is permitted under the
|
|
* terms stated in the Alif Semiconductor Software License Agreement
|
|
*
|
|
* You should have received a copy of the Alif Semiconductor Software
|
|
* License Agreement with this file. If not, please write to:
|
|
* contact@alifsemi.com, or visit: https://alifsemi.com/license
|
|
*
|
|
*/
|
|
|
|
/**************************************************************************//**
|
|
* @file Driver_WDT.c
|
|
* @author Tanay Rami
|
|
* @email tanay@alifsemi.com
|
|
* @version V1.0.0
|
|
* @date 27-April-2021
|
|
* @brief CMSIS-Driver for Watchdog
|
|
* @bug None.
|
|
* @Note None.
|
|
******************************************************************************/
|
|
|
|
/* Includes --------------------------------------------------------------------------- */
|
|
/* Project Includes */
|
|
#include "Driver_WDT.h"
|
|
#include "Driver_WDT_Private.h"
|
|
|
|
#if !(RTE_WDT0)
|
|
#error "Watchdog Timer WDT is not enabled in the RTE_Device.h"
|
|
#endif
|
|
|
|
#if (defined(RTE_Drivers_WDT0) && !RTE_WDT0)
|
|
#error "Watchdog Timer WDT0 not configured in RTE_Device.h!"
|
|
#endif
|
|
|
|
#define ARM_WDT_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1, 0) /* driver version */
|
|
|
|
/* Watchdog peripherals Clock (same as SystemCoreClock) */
|
|
extern uint32_t SystemCoreClock;
|
|
#define WDT_PERIPHERAL_CLOCK (SystemCoreClock)
|
|
|
|
/* Generic macro calculations for msecs ticks for the watchdog timeout. */
|
|
#define FREQ ( (uint32_t) WDT_PERIPHERAL_CLOCK )
|
|
#define MILLI_SEC (1000UL)
|
|
#define WDT_TICKS_FOR_MILLI_SECS(x) ( ( (uint64_t) x * FREQ ) / MILLI_SEC )
|
|
#define WDT_MILLI_SECS_FOR_TICKS(x) ( ( (uint64_t) x * MILLI_SEC) / FREQ )
|
|
#define WDT_MAX_TIMEOUT_MILLI_SEC ( ( (uint64_t) WATCHDOG_MAX_VALUE * MILLI_SEC ) / (FREQ) )
|
|
|
|
/* Driver Version */
|
|
static const ARM_DRIVER_VERSION DriverVersion = {
|
|
ARM_WDT_API_VERSION,
|
|
ARM_WDT_DRV_VERSION
|
|
};
|
|
|
|
/* Driver Capabilities */
|
|
static const ARM_WDT_CAPABILITIES DriverCapabilities = {
|
|
1, /* supports watchdog Lock */
|
|
0 /* Reserved (must be zero) */
|
|
};
|
|
|
|
/**
|
|
\fn ARM_DRIVER_VERSION WDT_GetVersion(void)
|
|
\brief get watchdog version
|
|
\return driver version
|
|
*/
|
|
static ARM_DRIVER_VERSION WDT_GetVersion(void)
|
|
{
|
|
return DriverVersion;
|
|
}
|
|
|
|
/**
|
|
\fn ARM_WDT_CAPABILITIES WDT_GetCapabilities(void)
|
|
\brief get watchdog capabilites
|
|
\return driver capabilites
|
|
*/
|
|
static ARM_WDT_CAPABILITIES WDT_GetCapabilities(void)
|
|
{
|
|
return DriverCapabilities;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t WDT_Start(WDT_RESOURCES *wdt)
|
|
\brief Start the watchdog timer.
|
|
\param[in] wdt : Pointer to watchdog device resources
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t WDT_Start(WDT_RESOURCES *wdt)
|
|
{
|
|
if (!wdt)
|
|
return ARM_DRIVER_ERROR_PARAMETER;
|
|
|
|
if (!(wdt->flags & WATCHDOG_POWERED) )
|
|
return ARM_DRIVER_ERROR;
|
|
|
|
if (wdt_locked(wdt->regs))
|
|
return ARM_DRIVER_ERROR_BUSY;
|
|
|
|
wdt_start(wdt->regs, wdt->timeout);
|
|
|
|
wdt->flags |= WATCHDOG_STARTED;
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t WDT_Feed(WDT_RESOURCES *wdt)
|
|
\brief Feeds the watchdog to not cause a reset.
|
|
\param[in] wdt : Pointer to watchdog device resources
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t WDT_Feed(WDT_RESOURCES *wdt)
|
|
{
|
|
if (!wdt)
|
|
return ARM_DRIVER_ERROR_PARAMETER;
|
|
|
|
if ( !(wdt->flags & WATCHDOG_STARTED) )
|
|
return ARM_DRIVER_ERROR;
|
|
|
|
if (wdt_locked(wdt->regs))
|
|
return ARM_DRIVER_ERROR_BUSY;
|
|
|
|
wdt_feed(wdt->regs, wdt->timeout);
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t WDT_GetRemainingTime(uint32_t *val, WDT_RESOURCES *wdt)
|
|
\brief Get watchdog remaining time before reset.
|
|
\param[out] val : Pointer to the address where watchdog remaining time in milliseconds.
|
|
\param[in] wdt : Pointer to watchdog device resources
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t WDT_GetRemainingTime(uint32_t *val, WDT_RESOURCES *wdt)
|
|
{
|
|
if (!wdt)
|
|
return ARM_DRIVER_ERROR_PARAMETER;
|
|
|
|
if ( !(wdt->flags & WATCHDOG_STARTED) )
|
|
return ARM_DRIVER_ERROR;
|
|
|
|
if (wdt_locked(wdt->regs))
|
|
return ARM_DRIVER_ERROR_BUSY;
|
|
|
|
*val = WDT_MILLI_SECS_FOR_TICKS(wdt_get_remaining_ticks(wdt->regs));
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t WDT_Stop(WDT_RESOURCES *wdt)
|
|
\brief Stop the watchdog timer.
|
|
\param[in] wdt : Pointer to watchdog device resources
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t WDT_Stop(WDT_RESOURCES *wdt)
|
|
{
|
|
if (!wdt)
|
|
return ARM_DRIVER_ERROR_PARAMETER;
|
|
|
|
if ( !(wdt->flags & WATCHDOG_STARTED) )
|
|
return ARM_DRIVER_ERROR;
|
|
|
|
if (wdt_locked(wdt->regs))
|
|
return ARM_DRIVER_ERROR_BUSY;
|
|
|
|
wdt_stop(wdt->regs);
|
|
|
|
wdt->flags &= ~WATCHDOG_STARTED;
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t WDT_PowerControl(ARM_POWER_STATE state,
|
|
WDT_RESOURCES *wdt)
|
|
\brief watchdog power control
|
|
\param[in] state : Power state
|
|
\param[in] wdt : Pointer to watchdog device resources
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t WDT_PowerControl(ARM_POWER_STATE state,
|
|
WDT_RESOURCES *wdt)
|
|
{
|
|
int ret = ARM_DRIVER_OK;
|
|
|
|
switch (state)
|
|
{
|
|
case ARM_POWER_OFF:
|
|
|
|
if ( (wdt->flags & WATCHDOG_STARTED) )
|
|
{
|
|
/* watchdog is still running,
|
|
* Stop the watchdog before Power-off.
|
|
*/
|
|
return ARM_DRIVER_ERROR_BUSY;
|
|
}
|
|
|
|
/* Reset watchdog power flag. */
|
|
wdt->flags &= (~WATCHDOG_POWERED);
|
|
break;
|
|
|
|
case ARM_POWER_FULL:
|
|
|
|
if ( !(wdt->flags & WATCHDOG_INITIALIZED) )
|
|
return ARM_DRIVER_ERROR;
|
|
|
|
/* Set the power flag enabled */
|
|
wdt->flags |= WATCHDOG_POWERED;
|
|
break;
|
|
|
|
case ARM_POWER_LOW:
|
|
default:
|
|
return ARM_DRIVER_ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t WDT_Initialize(uint32_t timeout,
|
|
WDT_RESOURCES *wdt)
|
|
\brief Initialize the watchdog device.
|
|
The init function leaves the watchdog in a clean state:
|
|
- initialized;
|
|
- stop;
|
|
- locked.
|
|
\param[in] timeout : Timeout in msec, must be > 0.
|
|
\param[in] wdt : Pointer to watchdog device resources
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t WDT_Initialize(uint32_t timeout_msec,
|
|
WDT_RESOURCES *wdt)
|
|
{
|
|
if (!wdt)
|
|
return ARM_DRIVER_ERROR_PARAMETER;
|
|
|
|
if ( (wdt->flags & WATCHDOG_STARTED) )
|
|
{
|
|
wdt_unlock(wdt->regs);
|
|
|
|
/* Stop the watchdog */
|
|
wdt_stop(wdt->regs);
|
|
wdt->flags &= ~WATCHDOG_STARTED;
|
|
}
|
|
|
|
if (!timeout_msec)
|
|
return ARM_DRIVER_ERROR_PARAMETER;
|
|
|
|
if( timeout_msec > WDT_MAX_TIMEOUT_MILLI_SEC )
|
|
return ARM_DRIVER_ERROR_PARAMETER;
|
|
|
|
wdt_lock(wdt->regs);
|
|
|
|
/* Update watchdog timeout. */
|
|
wdt->timeout = WDT_TICKS_FOR_MILLI_SECS(timeout_msec);
|
|
|
|
/* Set flag to initialized. */
|
|
wdt->flags = WATCHDOG_INITIALIZED;
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t WDT_Uninitialize(WDT_RESOURCES *wdt)
|
|
\brief Uninitialize the watchdog device.
|
|
\param[in] wdt : Pointer to watchdog device resources
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t WDT_Uninitialize(WDT_RESOURCES *wdt)
|
|
{
|
|
if ( (wdt->flags & WATCHDOG_STARTED) )
|
|
{
|
|
/* watchdog is still running,
|
|
* Stop the watchdog before Uninitialize.
|
|
*/
|
|
return ARM_DRIVER_ERROR_BUSY;
|
|
}
|
|
|
|
/* reset watchdog flags and timeout. */
|
|
wdt->flags = 0;
|
|
wdt->timeout = 0;
|
|
|
|
return ARM_DRIVER_OK;
|
|
}
|
|
|
|
/**
|
|
\fn int32_t WDT_Control(uint32_t control,
|
|
uint32_t arg,
|
|
WDT_RESOURCES *wdt)
|
|
\brief CMSIS-Driver watchdog control.
|
|
Control watchdog Interface.
|
|
\param[in] control : Operation
|
|
\param[in] arg : Argument of operation (optional)
|
|
\param[in] wdt : Pointer to watchdog device resources
|
|
\return \ref execution_status
|
|
*/
|
|
static int32_t WDT_Control(uint32_t control,
|
|
uint32_t arg,
|
|
WDT_RESOURCES *wdt)
|
|
{
|
|
ARG_UNUSED(arg);
|
|
int ret = ARM_DRIVER_OK;
|
|
|
|
if( !(wdt->flags & WATCHDOG_POWERED ) )
|
|
return ARM_DRIVER_ERROR;
|
|
|
|
switch (control)
|
|
{
|
|
case ARM_WATCHDOG_LOCK:
|
|
|
|
/* Lock watchdog. */
|
|
wdt_lock(wdt->regs);
|
|
break;
|
|
|
|
case ARM_WATCHDOG_UNLOCK:
|
|
|
|
/* Unlock watchdog. */
|
|
wdt_unlock(wdt->regs);
|
|
break;
|
|
|
|
default:
|
|
/* Unsupported command */
|
|
ret = ARM_DRIVER_ERROR_UNSUPPORTED;
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
// End of watchdog Interface
|
|
|
|
|
|
/* Watchdog-0 Driver Instance */
|
|
#if (RTE_WDT0)
|
|
|
|
/* Watchdog-0 device configuration */
|
|
static WDT_RESOURCES WDT0 = {
|
|
.regs = (WDT_CTRL_Type *) LOCAL_WDT_CTRL_BASE,
|
|
.flags = 0,
|
|
.timeout = 0
|
|
};
|
|
|
|
|
|
/* Function Name: WDT0_Initialize */
|
|
static int32_t WDT0_Initialize(uint32_t timeout)
|
|
{
|
|
return (WDT_Initialize(timeout, &WDT0));
|
|
}
|
|
|
|
/* Function Name: WDT0_Uninitialize */
|
|
static int32_t WDT0_Uninitialize(void)
|
|
{
|
|
return (WDT_Uninitialize(&WDT0));
|
|
}
|
|
|
|
/* Function Name: WDT0_PowerControl */
|
|
static int32_t WDT0_PowerControl(ARM_POWER_STATE state)
|
|
{
|
|
return (WDT_PowerControl(state, &WDT0));
|
|
}
|
|
|
|
/* Function Name: WDT0_Start */
|
|
static int32_t WDT0_Start(void)
|
|
{
|
|
return (WDT_Start(&WDT0));
|
|
}
|
|
|
|
/* Function Name: WDT0_Feed */
|
|
static int32_t WDT0_Feed(void)
|
|
{
|
|
return (WDT_Feed(&WDT0));
|
|
}
|
|
|
|
/* Function Name: WDT0_Stop */
|
|
static int32_t WDT0_Stop(void)
|
|
{
|
|
return (WDT_Stop(&WDT0));
|
|
}
|
|
|
|
/* Function Name: WDT0_Control */
|
|
static int32_t WDT0_Control(uint32_t control, uint32_t arg)
|
|
{
|
|
return (WDT_Control(control, arg, &WDT0));
|
|
}
|
|
|
|
/* Function Name: WDT0_GetRemainingTime */
|
|
static int32_t WDT0_GetRemainingTime(uint32_t *val)
|
|
{
|
|
return (WDT_GetRemainingTime(val, &WDT0));
|
|
}
|
|
|
|
|
|
extern ARM_DRIVER_WDT Driver_WDT0;
|
|
ARM_DRIVER_WDT Driver_WDT0 =
|
|
{
|
|
WDT_GetVersion,
|
|
WDT_GetCapabilities,
|
|
WDT0_Initialize,
|
|
WDT0_Uninitialize,
|
|
WDT0_PowerControl,
|
|
WDT0_Start,
|
|
WDT0_Feed,
|
|
WDT0_Stop,
|
|
WDT0_Control,
|
|
WDT0_GetRemainingTime
|
|
};
|
|
#endif /* End of RTE_WDT0 */
|
|
|
|
/************************ (C) COPYRIGHT ALIF SEMICONDUCTOR *****END OF FILE****/
|