swm050: Adds WDT peripheral
Reviewed-by: Karl Palsson <karlp@tweak.net.au> (Fixed an &| in wdt_set_time)
This commit is contained in:
parent
dd18b9fdbc
commit
47b59e2df4
@ -31,6 +31,14 @@
|
|||||||
#include <libopencm3/cm3/common.h>
|
#include <libopencm3/cm3/common.h>
|
||||||
#include <libopencm3/swm050/memorymap.h>
|
#include <libopencm3/swm050/memorymap.h>
|
||||||
|
|
||||||
|
/** @defgroup sysctl_bit_defs SYSCTL register bit definitions
|
||||||
|
@{*/
|
||||||
|
#define SYSCTL_SYS_CFG_2_SLEEP (1 << 4)
|
||||||
|
#define SYSCTL_SYS_CFG_1_TIMERSE0 (1 << 6)
|
||||||
|
#define SYSCTL_SYS_CFG_1_TIMERSE1 (1 << 17)
|
||||||
|
#define SYSCTL_SYS_CFG_1_WDT (1 << 4)
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
/** @defgroup sysctl_register SYSCTL Registers
|
/** @defgroup sysctl_register SYSCTL Registers
|
||||||
* @note System configuration registers
|
* @note System configuration registers
|
||||||
* @{*/
|
* @{*/
|
||||||
|
71
include/libopencm3/swm050/wdt.h
Normal file
71
include/libopencm3/swm050/wdt.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/** @defgroup wdt_defines Watchdog Defines
|
||||||
|
*
|
||||||
|
* @brief <b>Defined Constants and Types for the SWM050 Watchdog</b>
|
||||||
|
*
|
||||||
|
* @ingroup SWM050_defines
|
||||||
|
*
|
||||||
|
* LGPL License Terms @ref lgpl_license
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of the libopencm3 project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
|
||||||
|
*
|
||||||
|
* This library is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/**@{*/
|
||||||
|
#ifndef LIBOPENCM3_WDT_H
|
||||||
|
#define LIBOPENCM3_WDT_H
|
||||||
|
|
||||||
|
#include <libopencm3/cm3/common.h>
|
||||||
|
#include <libopencm3/swm050/memorymap.h>
|
||||||
|
|
||||||
|
/* Watchdog mode definitions */
|
||||||
|
/** @defgroup wdt_modes Watchdog mode
|
||||||
|
@{*/
|
||||||
|
enum wdt_modes {
|
||||||
|
/* On timeout, reset the system */
|
||||||
|
WDT_MODE_RESET,
|
||||||
|
/* On timeout, generate an interrupt. If another timeout occurs without
|
||||||
|
the interrupt being cleared, reset the system. */
|
||||||
|
WDT_MODE_INT
|
||||||
|
};
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
|
/** @defgroup wdt_registers Watchdog Registers
|
||||||
|
@{*/
|
||||||
|
#define WDT_CR MMIO32(WDT_BASE + 0x0)
|
||||||
|
#define WDT_TORR MMIO32(WDT_BASE + 0x04)
|
||||||
|
#define WDT_CCVR MMIO32(WDT_BASE + 0x08)
|
||||||
|
#define WDT_CRR MMIO32(WDT_BASE + 0x0C)
|
||||||
|
#define WDT_STAT MMIO32(WDT_BASE + 0x10)
|
||||||
|
#define WDT_EOI MMIO32(WDT_BASE + 0x14)
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
|
BEGIN_DECLS
|
||||||
|
|
||||||
|
void wdt_setup(enum wdt_modes mode, uint8_t time1, uint8_t time2);
|
||||||
|
void wdt_enable(bool en);
|
||||||
|
void wdt_mode(enum wdt_modes mode);
|
||||||
|
void wdt_reset(void);
|
||||||
|
bool wdt_int_status(void);
|
||||||
|
void wdt_clear_int(void);
|
||||||
|
void wdt_clock_enable(bool en);
|
||||||
|
uint32_t wdt_get_value(void);
|
||||||
|
void wdt_set_time(uint8_t time1, uint8_t time2);
|
||||||
|
|
||||||
|
END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/**@}*/
|
@ -38,6 +38,7 @@ OBJS += flash.o
|
|||||||
OBJS += gpio.o
|
OBJS += gpio.o
|
||||||
OBJS += pwr.o
|
OBJS += pwr.o
|
||||||
OBJS += syscon.o
|
OBJS += syscon.o
|
||||||
|
OBJS += wdt.o
|
||||||
VPATH += ../cm3
|
VPATH += ../cm3
|
||||||
|
|
||||||
include ../Makefile.include
|
include ../Makefile.include
|
||||||
|
@ -37,6 +37,6 @@ not get locked out of the MCU.
|
|||||||
*/
|
*/
|
||||||
void pwr_sleep(void)
|
void pwr_sleep(void)
|
||||||
{
|
{
|
||||||
SYSCTL_SYS_CFG_2 |= (1<<4);
|
SYSCTL_SYS_CFG_2 |= SYSCTL_SYS_CFG_2_SLEEP;
|
||||||
}
|
}
|
||||||
/**@}*/
|
/**@}*/
|
||||||
|
168
lib/swm050/wdt.c
Normal file
168
lib/swm050/wdt.c
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
/** @defgroup wdg_file Watchdog peripheral API
|
||||||
|
* @brief SWM050 WDT API.
|
||||||
|
* @ingroup peripheral_apis
|
||||||
|
* LGPL License Terms @ref lgpl_license
|
||||||
|
* @author @htmlonly © @endhtmlonly 2019
|
||||||
|
* Caleb Szalacinski <contact@skiboy.net>
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of the libopencm3 project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
|
||||||
|
*
|
||||||
|
* This library is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/**@{*/
|
||||||
|
#include <libopencm3/swm050/wdt.h>
|
||||||
|
#include <libopencm3/swm050/sysctl.h>
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/** Sets up the WDT before the call to wdt_enable().
|
||||||
|
|
||||||
|
@param mode passed to wdt_mode()
|
||||||
|
|
||||||
|
@param time1 passed to wdt_set_time()
|
||||||
|
|
||||||
|
@param time2 passed to wdt_set_time()
|
||||||
|
*/
|
||||||
|
void wdt_setup(enum wdt_modes mode, uint8_t time1, uint8_t time2)
|
||||||
|
{
|
||||||
|
wdt_clock_enable(1);
|
||||||
|
wdt_set_time(time1, time2);
|
||||||
|
wdt_mode(mode);
|
||||||
|
wdt_reset();
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/** Enables the WDT.
|
||||||
|
|
||||||
|
If WDT_MODE_INT is used, the interrupt should also be enabled
|
||||||
|
using the NVIC before enabling the WDT.
|
||||||
|
|
||||||
|
@param en enable
|
||||||
|
*/
|
||||||
|
void wdt_enable(bool en)
|
||||||
|
{
|
||||||
|
if (en) {
|
||||||
|
WDT_CR |= 0x1;
|
||||||
|
} else {
|
||||||
|
WDT_CR &= ~0x1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/** Sets the WDT's mode of operation.
|
||||||
|
|
||||||
|
@param mode The mode of operation @ref wdt_modes
|
||||||
|
*/
|
||||||
|
void wdt_mode(enum wdt_modes mode)
|
||||||
|
{
|
||||||
|
if (mode == WDT_MODE_INT) {
|
||||||
|
WDT_CR |= (1 << 1);
|
||||||
|
} else {
|
||||||
|
WDT_CR &= ~(1 << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/** Restarts the WDT's counter.
|
||||||
|
|
||||||
|
The "feed the dog" operation. Must be called periodically to avoid a timeout.
|
||||||
|
Calling this also clears any WDT interrupts.
|
||||||
|
*/
|
||||||
|
void wdt_reset(void)
|
||||||
|
{
|
||||||
|
WDT_CRR = 0x76;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/** Gets the WDT's interrupt status.
|
||||||
|
|
||||||
|
Only useful in WDT_MODE_INT.
|
||||||
|
|
||||||
|
@return The WDT's interrupt status. True if an interrupt has not been cleared.
|
||||||
|
*/
|
||||||
|
bool wdt_int_status(void)
|
||||||
|
{
|
||||||
|
return WDT_STAT & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/** Clears the WDT's interrupt.
|
||||||
|
|
||||||
|
Only useful in WDT_MODE_INT.
|
||||||
|
*/
|
||||||
|
void wdt_clear_int(void)
|
||||||
|
{
|
||||||
|
/* Read register to clear the interrupt */
|
||||||
|
uint32_t dummy = WDT_EOI;
|
||||||
|
/* Does nothing, but suppresses a -Wunused-variable warning */
|
||||||
|
(void)dummy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/** Enables the WDT's clock.
|
||||||
|
|
||||||
|
@param en True to enable, false to disable
|
||||||
|
*/
|
||||||
|
void wdt_clock_enable(bool en)
|
||||||
|
{
|
||||||
|
if (en) {
|
||||||
|
SYSCTL_SYS_CFG_1 |= SYSCTL_SYS_CFG_1_WDT;
|
||||||
|
} else {
|
||||||
|
SYSCTL_SYS_CFG_1 &= ~SYSCTL_SYS_CFG_1_WDT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/** Gets the current WDT counter value.
|
||||||
|
|
||||||
|
The vendor-supplied documentation for the WDT_CCVR register appears to be
|
||||||
|
incorrect, and does not seem to be 1 bit wide, which would make no sense.
|
||||||
|
|
||||||
|
@return The current WDT counter value
|
||||||
|
*/
|
||||||
|
uint32_t wdt_get_value(void)
|
||||||
|
{
|
||||||
|
return WDT_CCVR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/** Sets the WDT's initial counter values.
|
||||||
|
|
||||||
|
Both time1 and time2 follow the equation 2^(8 + i), where i is a value from
|
||||||
|
0 to 15, and where the result is in clock cycles.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
time1 = 15
|
||||||
|
2^(8 + time1) / 18Mhz = 0.466s
|
||||||
|
|
||||||
|
The majority of the vendor-supplied documentation appears to be completely
|
||||||
|
incorrect about the equation used for these counters.
|
||||||
|
|
||||||
|
@param time1 The timer value used in both modes. In WDT_MODE_RESET, this value
|
||||||
|
counts down to 0 and resets the system. In WDT_MODE_INT, this value counts down
|
||||||
|
to 0, generates a WDT interrupt, loads time2 into the counter, and counts down.
|
||||||
|
Only the 4 least significant bits of this value are used, e.g. 0 to 15.
|
||||||
|
|
||||||
|
@param time2 The timer value used after time1 in mode WDT_MODE_INT. If this
|
||||||
|
counts down to 0, and the WDT interrupt has not been cleared, the system resets.
|
||||||
|
This has no use in mode WDT_MODE_RESET.
|
||||||
|
Only the 4 least significant bits of this value are used, e.g. 0 to 15.
|
||||||
|
*/
|
||||||
|
void wdt_set_time(uint8_t time1, uint8_t time2)
|
||||||
|
{
|
||||||
|
WDT_TORR = ((0xF & time1) << 4) | (0xF & time2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**@}*/
|
Loading…
x
Reference in New Issue
Block a user