blob: 1ad3e8922adce5dbb9447d4ccf7d0a1527928fe5 [file] [log] [blame]
/*
* Copyright (c) 2015-2017, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdint.h>
#include <stdlib.h>
/*
* By default disable both asserts and log for this module.
* This must be done before DebugP.h is included.
*/
#ifndef DebugP_ASSERT_ENABLED
#define DebugP_ASSERT_ENABLED 0
#endif
#ifndef DebugP_LOG_ENABLED
#define DebugP_LOG_ENABLED 0
#endif
#include <ti/drivers/dpl/DebugP.h>
#include <ti/drivers/dpl/HwiP.h>
#include <ti/drivers/dpl/ClockP.h>
#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerCC32XX.h>
#include <ti/drivers/watchdog/WatchdogCC32XX.h>
#include <ti/devices/cc32xx/inc/hw_types.h>
#include <ti/devices/cc32xx/driverlib/rom.h>
#include <ti/devices/cc32xx/driverlib/rom_map.h>
#include <ti/devices/cc32xx/driverlib/wdt.h>
/* Function prototypes */
void WatchdogCC32XX_clear(Watchdog_Handle handle);
void WatchdogCC32XX_close(Watchdog_Handle handle);
int_fast16_t WatchdogCC32XX_control(Watchdog_Handle handle,
uint_fast16_t cmd, void *arg);
void WatchdogCC32XX_init(Watchdog_Handle handle);
Watchdog_Handle WatchdogCC32XX_open(Watchdog_Handle handle, Watchdog_Params *params);
int_fast16_t WatchdogCC32XX_setReload(Watchdog_Handle handle,
uint32_t value);
uint32_t WatchdogCC32XX_convertMsToTicks(Watchdog_Handle handle,
uint32_t milliseconds);
/* Watchdog function table for CC32XX implementation */
const Watchdog_FxnTable WatchdogCC32XX_fxnTable = {
WatchdogCC32XX_clear,
WatchdogCC32XX_close,
WatchdogCC32XX_control,
WatchdogCC32XX_init,
WatchdogCC32XX_open,
WatchdogCC32XX_setReload,
WatchdogCC32XX_convertMsToTicks
};
/* Maximum allowable setReload value */
#define MAX_RELOAD_VALUE 0xFFFFFFFF
#define MS_RATIO 1000 /* millisecond to second ratio */
/*
* ======== WatchdogCC32XX_clear ========
*/
void WatchdogCC32XX_clear(Watchdog_Handle handle)
{
WatchdogCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
MAP_WatchdogIntClear(hwAttrs->baseAddr);
}
/*
* ======== WatchdogCC32XX_close ========
*/
void WatchdogCC32XX_close(Watchdog_Handle handle)
{
/*
* Not supported for CC32XX - Once the INTEN bit of the WDTCTL
* register has been set, it can only be cleared by a hardware
* reset.
*/
DebugP_assert(false);
}
/*
* ======== WatchdogCC32XX_control ========
* @pre Function assumes that the handle is not NULL
*/
int_fast16_t WatchdogCC32XX_control(Watchdog_Handle handle, uint_fast16_t cmd,
void *arg)
{
WatchdogCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
switch (cmd) {
/* Specific Watchdog CMDs */
case (WatchdogCC32XX_CMD_IS_TIMER_ENABLE):
*(bool *)arg = MAP_WatchdogRunning(hwAttrs->baseAddr);
return (Watchdog_STATUS_SUCCESS);
case (WatchdogCC32XX_CMD_GET_TIMER_VALUE):
*(uint32_t *)arg = MAP_WatchdogValueGet(hwAttrs->baseAddr);
return (Watchdog_STATUS_SUCCESS);
case (WatchdogCC32XX_CMD_IS_TIMER_LOCKED):
*(bool *)arg = MAP_WatchdogLockState(hwAttrs->baseAddr);
return (Watchdog_STATUS_SUCCESS);
case (WatchdogCC32XX_CMD_GET_TIMER_RELOAD_VALUE):
*(uint32_t *)arg = MAP_WatchdogReloadGet(hwAttrs->baseAddr);
return (Watchdog_STATUS_SUCCESS);
default:
DebugP_log1("Watchdog: Watchdog CMD undefined: %d",cmd);
return (Watchdog_STATUS_UNDEFINEDCMD);
}
}
/*
* ======== Watchdog_init ========
*/
void WatchdogCC32XX_init(Watchdog_Handle handle)
{
WatchdogCC32XX_Object *object = handle->object;
object->isOpen = false;
}
/*
* ======== WatchdogCC32XX_open ========
*/
Watchdog_Handle WatchdogCC32XX_open(Watchdog_Handle handle, Watchdog_Params *params)
{
uintptr_t key;
HwiP_Handle hwiHandle;
HwiP_Params hwiParams;
WatchdogCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
WatchdogCC32XX_Object *object = handle->object;
/* Don't allow preemption */
key = HwiP_disable();
/* Check if the Watchdog is open already with the HWAttrs */
if (object->isOpen == true) {
HwiP_restore(key);
DebugP_log1("Watchdog: Handle %x already in use.", (uintptr_t)handle);
return (NULL);
}
object->isOpen = true;
HwiP_restore(key);
/* Register the interrupt for this watchdog */
if (params->callbackFxn) {
HwiP_Params_init(&hwiParams);
hwiParams.arg = (uintptr_t)handle;
hwiParams.priority = hwAttrs->intPriority;
hwiHandle = HwiP_create(hwAttrs->intNum, params->callbackFxn,
&hwiParams);
if (hwiHandle == NULL) {
return (NULL);
}
}
/* Set power dependency on WDT */
Power_setDependency(PowerCC32XX_PERIPH_WDT);
/* Don't allow the processor to go into LPDS (DeepSleep is ok) */
Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
MAP_WatchdogUnlock(hwAttrs->baseAddr);
MAP_WatchdogReloadSet(hwAttrs->baseAddr, hwAttrs->reloadValue);
MAP_WatchdogIntClear(hwAttrs->baseAddr);
/* Set debug stall mode */
if (params->debugStallMode == Watchdog_DEBUG_STALL_ON) {
MAP_WatchdogStallEnable(hwAttrs->baseAddr);
}
else {
MAP_WatchdogStallDisable(hwAttrs->baseAddr);
}
MAP_WatchdogEnable(hwAttrs->baseAddr);
MAP_WatchdogLock(hwAttrs->baseAddr);
DebugP_log1("Watchdog: handle %x opened" ,(uintptr_t)handle);
/* Return handle of the Watchdog object */
return (handle);
}
/*
* ======== WatchdogCC32XX_setReload ========
*/
int_fast16_t WatchdogCC32XX_setReload(Watchdog_Handle handle, uint32_t value)
{
WatchdogCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
/* Set value */
MAP_WatchdogUnlock(hwAttrs->baseAddr);
MAP_WatchdogReloadSet(hwAttrs->baseAddr, value);
MAP_WatchdogLock(hwAttrs->baseAddr);
DebugP_log2("Watchdog: WDT with handle 0x%x has been set to "
"reload to 0x%x", (uintptr_t)handle, value);
return (Watchdog_STATUS_SUCCESS);
}
/*
* ======== WatchdogCC32XX_convertMsToTicks ========
* This function converts the input value from milliseconds to
* Watchdog clock ticks.
*/
uint32_t WatchdogCC32XX_convertMsToTicks(Watchdog_Handle handle,
uint32_t milliseconds)
{
uint32_t tickValue;
uint32_t convertRatio;
uint32_t maxConvertMs;
ClockP_FreqHz freq;
/* Determine milliseconds to clock ticks conversion ratio */
ClockP_getCpuFreq(&freq);
/* Watchdog clock ticks/ms = CPU clock / MS_RATIO */
convertRatio = freq.lo / MS_RATIO;
maxConvertMs = MAX_RELOAD_VALUE / convertRatio;
/* Convert milliseconds to watchdog timer ticks */
/* Check if value exceeds maximum */
if (milliseconds > maxConvertMs) {
tickValue = 0; /* Return zero to indicate overflow */
}
else {
tickValue = (uint32_t)(milliseconds * convertRatio);
}
return(tickValue);
}