--- /dev/null
+\r
+/******************************************************************************\r
+*\r
+* alt_watchdog.c - API for the Altera SoC FPGA watchdog timers.\r
+*\r
+******************************************************************************/\r
+\r
+/******************************************************************************\r
+*\r
+* Copyright 2013 Altera Corporation. All Rights Reserved.\r
+*\r
+* Redistribution and use in source and binary forms, with or without\r
+* modification, are permitted provided that the following conditions are met:\r
+*\r
+* 1. Redistributions of source code must retain the above copyright notice,\r
+* this list of conditions and the following disclaimer.\r
+*\r
+* 2. Redistributions in binary form must reproduce the above copyright notice,\r
+* this list of conditions and the following disclaimer in the documentation\r
+* and/or other materials provided with the distribution.\r
+*\r
+* 3. The name of the author may not be used to endorse or promote products\r
+* derived from this software without specific prior written permission.\r
+*\r
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR\r
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO\r
+* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\r
+* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\r
+* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\r
+* OF SUCH DAMAGE.\r
+*\r
+******************************************************************************/\r
+\r
+/******************************************************************************\r
+*\r
+* The Altera SoC FPGA has six watchdog timers, two are local to the MPU\r
+* themselves, and the other four are accessable to either MPU.\r
+*\r
+******************************************************************************/\r
+\r
+#include <stdint.h>\r
+#include <stdbool.h>\r
+#include "socal/hps.h"\r
+#include "socal/socal.h"\r
+#include "socal/alt_rstmgr.h"\r
+#include "socal/alt_l4wd.h"\r
+#include "socal/alt_tmr.h"\r
+#include "hwlib.h"\r
+#include "alt_mpu_registers.h"\r
+#include "alt_watchdog.h"\r
+#include "alt_clock_manager.h"\r
+\r
+\r
+ /* Useful constants and utilities */\r
+\r
+bool cpu_wdog_in_gpt_mode(void)\r
+{\r
+ return !(alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) & WDOG_WDT_MODE);\r
+}\r
+\r
+static inline bool cpu_wdog_in_wdt_mode(void)\r
+{\r
+ return (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) & WDOG_WDT_MODE);\r
+}\r
+\r
+\r
+/* This value must be written to the Counter Restart Register of the\r
+ * peripheral watchdog timers to restart them. */\r
+#define WDOG_RESET_KEY 0x00000076\r
+\r
+#define ALT_WDOG_RST_WIDTH 8 /* 8 or more MPU clock cycles */\r
+\r
+\r
+inline static void alt_wdog_wait(void* reg, uint32_t cnt)\r
+{\r
+ for (; cnt ; cnt--)\r
+ {\r
+ (void) alt_read_word(reg);\r
+ }\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Initialize the watchdog timer module before use */\r
+/****************************************************************************************/\r
+\r
+ALT_STATUS_CODE alt_wdog_init(void)\r
+{\r
+ // put watchdog timer modules into system manager reset if not already there\r
+ alt_wdog_uninit();\r
+ // release L4 watchdog timer modules from system reset (w/ four instruction-cycle delay)\r
+ alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_L4WD0_SET_MSK |\r
+ ALT_RSTMGR_PERMODRST_L4WD1_SET_MSK);\r
+\r
+ // release *both* ARM watchdog timer modules from system reset (if in reset)\r
+ // does not put either one into watchdog timer mode\r
+ alt_clrbits_word(ALT_RSTMGR_MPUMODRST_ADDR, ALT_RSTMGR_MPUMODRST_WDS_SET_MSK);\r
+ return ALT_E_SUCCESS;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Return the local ARM watchdog timer back to general-purpose timer mode */\r
+/****************************************************************************************/\r
+\r
+void alt_ARM_wdog_gpt_mode_set(void)\r
+{\r
+ while (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) & WDOG_WDT_MODE)\r
+ {\r
+ alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_DISABLE_REG_OFFSET, WDOG_DISABLE_VAL0);\r
+ alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_DISABLE_REG_OFFSET, WDOG_DISABLE_VAL1);\r
+ }\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Set the local ARM watchdog timer to watchdog timer mode */\r
+/****************************************************************************************/\r
+\r
+void alt_ARM_wdog_wdog_mode_set(void)\r
+{\r
+ alt_setbits_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET, WDOG_WDT_MODE);\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Uninitialize the watchdog timer module & return to reset state */\r
+/****************************************************************************************/\r
+\r
+ALT_STATUS_CODE alt_wdog_uninit(void)\r
+{\r
+ // put L4 watchdog modules into system manager reset\r
+ alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR,\r
+ ALT_RSTMGR_PERMODRST_L4WD0_SET_MSK | ALT_RSTMGR_PERMODRST_L4WD1_SET_MSK);\r
+\r
+ // using the system manager bit to reset the ARM watchdog timer\r
+ // resets *both* ARM watchdog timers, which is often not advisable,\r
+ // so we reset the local ARM watchdog timer manually:\r
+\r
+ // first, stop the ARM watchdog timer & disable interrupt\r
+ alt_clrbits_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET, WDOG_TMR_ENABLE | WDOG_INT_EN);\r
+ // reset load and counter registers\r
+ alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_LOAD_REG_OFFSET, 0);\r
+ // clear any pending reset and interrupt status\r
+ alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_RSTSTAT_REG_OFFSET, WDOG_RST_STAT_BIT);\r
+ alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_INTSTAT_REG_OFFSET, WDOG_INT_STAT_BIT);\r
+ // return ARM watchdog timer to (initial) general-purpose timer mode\r
+ alt_ARM_wdog_gpt_mode_set();\r
+ // now write zeros to the control register significant bitfields\r
+ // and then verify that all significant bitfields return zero\r
+ alt_clrbits_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET,\r
+ (WDOG_PS_MASK | WDOG_WDT_MODE | WDOG_INT_EN | WDOG_AUTO_RELOAD | WDOG_TMR_ENABLE));\r
+ if (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET)\r
+ & (WDOG_PS_MASK | WDOG_WDT_MODE | WDOG_INT_EN | WDOG_AUTO_RELOAD | WDOG_TMR_ENABLE))\r
+ {\r
+ return ALT_E_ERROR;\r
+ }\r
+ return ALT_E_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Stops the specified watchdog timer. */\r
+/****************************************************************************************/\r
+\r
+ALT_STATUS_CODE alt_wdog_stop(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ ALT_STATUS_CODE ret = ALT_E_BAD_ARG; // return value\r
+ uint32_t config; // the current configuration\r
+ uint32_t loadreg; // current restart value\r
+\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET,\r
+ (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) & ~WDOG_TMR_ENABLE));\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+\r
+ // these timers can only be reset by using a system manager reset\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
+ {\r
+ config = alt_read_word(ALT_L4WD0_WDT_CR_ADDR); // read current timer mode\r
+ loadreg = alt_read_word(ALT_L4WD0_WDT_TORR_ADDR); // read timer restart values\r
+ alt_write_word(ALT_RSTMGR_PERMODRST_ADDR,\r
+ alt_read_word(ALT_RSTMGR_PERMODRST_ADDR) | ALT_RSTMGR_PERMODRST_L4WD0_SET_MSK);\r
+ // assert reset & wait\r
+ alt_wdog_wait(ALT_RSTMGR_PERMODRST_ADDR, ALT_WDOG_RST_WIDTH);\r
+ alt_write_word(ALT_RSTMGR_PERMODRST_ADDR,\r
+ alt_read_word(ALT_RSTMGR_PERMODRST_ADDR) & ALT_RSTMGR_PERMODRST_L4WD0_CLR_MSK);\r
+ // release peripheral reset signal by clearing bit\r
+ alt_write_word(ALT_L4WD0_WDT_TORR_ADDR, loadreg); // restore timer restart value\r
+ alt_write_word(ALT_L4WD0_WDT_CR_ADDR, config & ALT_TMR_TMR1CTLREG_TMR1_EN_CLR_MSK);\r
+ // restore previous timer mode except timer isn't started\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ config = alt_read_word(ALT_L4WD1_WDT_CR_ADDR); // read current timer mode\r
+ loadreg = alt_read_word(ALT_L4WD1_WDT_TORR_ADDR); // read timer restart values\r
+ alt_write_word(ALT_RSTMGR_PERMODRST_ADDR,\r
+ alt_read_word(ALT_RSTMGR_PERMODRST_ADDR) | ALT_RSTMGR_PERMODRST_L4WD1_SET_MSK);\r
+ // assert reset & wait\r
+ alt_write_word(ALT_RSTMGR_PERMODRST_ADDR,\r
+ alt_read_word(ALT_RSTMGR_PERMODRST_ADDR) & ALT_RSTMGR_PERMODRST_L4WD1_CLR_MSK);\r
+ // release peripheral reset signal by clearing bit\r
+ alt_write_word(ALT_L4WD1_WDT_TORR_ADDR, loadreg); // restore timer restart value\r
+ alt_write_word(ALT_L4WD1_WDT_CR_ADDR, config & ALT_TMR_TMR1CTLREG_TMR1_EN_CLR_MSK);\r
+ // restore previous timer mode except timer isn't started\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ return ret;\r
+}\r
+\r
+/****************************************************************************************/\r
+/* Start the specified watchdog timer. */\r
+/****************************************************************************************/\r
+\r
+ALT_STATUS_CODE alt_wdog_start(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ ALT_STATUS_CODE ret = ALT_E_BAD_ARG; // return value\r
+ uint32_t regdata; // data\r
+\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ regdata = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET);\r
+ alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET, regdata | WDOG_TMR_ENABLE);\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
+ {\r
+ regdata = alt_read_word(ALT_L4WD0_WDT_CR_ADDR);\r
+ alt_write_word(ALT_L4WD0_WDT_CR_ADDR, regdata | ALT_L4WD_CR_WDT_EN_SET_MSK);\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ regdata = alt_read_word(ALT_L4WD1_WDT_CR_ADDR);\r
+ alt_write_word(ALT_L4WD1_WDT_CR_ADDR, regdata | ALT_L4WD_CR_WDT_EN_SET_MSK);\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ return ret;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns whether the specified watchdog timer is currently running or not. */\r
+/****************************************************************************************/\r
+\r
+bool alt_wdog_tmr_is_enabled(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ bool ret = false; // return value\r
+\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ ret = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) & WDOG_TMR_ENABLE;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
+ {\r
+ ret = alt_read_word(ALT_L4WD0_WDT_CR_ADDR) & ALT_L4WD_CR_WDT_EN_SET_MSK;\r
+ }\r
+\r
+ else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ ret = alt_read_word(ALT_L4WD1_WDT_CR_ADDR) & ALT_L4WD_CR_WDT_EN_SET_MSK;\r
+ }\r
+ return ret;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Reloads the counter countdown value and restarts the watchdog timer. User can reset */\r
+/* the timer at any time before timeout. Also known as kicking, petting, feeding, */\r
+/* waking, or walking the watchdog. Inherently clears the interrupt as well. */\r
+/****************************************************************************************/\r
+\r
+ALT_STATUS_CODE alt_wdog_reset(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ uint32_t regdata; // data read\r
+\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ regdata = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_LOAD_REG_OFFSET);\r
+ alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_LOAD_REG_OFFSET, regdata);\r
+ // verify operation when we have hardware,\r
+ // the ARM documentation is somewhat vague here\r
+\r
+ if (cpu_wdog_in_wdt_mode())\r
+ {\r
+ alt_write_word((CPU_WDTGPT_TMR_BASE + WDOG_RSTSTAT_REG_OFFSET), WDOG_RST_STAT_BIT);\r
+ // depending on current mode, clear the reset bit or...\r
+ }\r
+ else\r
+ {\r
+ alt_write_word((CPU_WDTGPT_TMR_BASE + WDOG_INTSTAT_REG_OFFSET), WDOG_INT_STAT_BIT);\r
+ // ...clear the interrupt status bit by writing one to it\r
+ }\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
+ {\r
+ alt_write_word(ALT_L4WD0_WDT_CRR_ADDR, WDOG_RESET_KEY);\r
+ //restarts the counter, also clears the watchdog timer interrupt\r
+ }\r
+ else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ alt_write_word(ALT_L4WD1_WDT_CRR_ADDR, WDOG_RESET_KEY);\r
+ //restarts the counter, also clears the watchdog timer interrupt\r
+ }\r
+ else {return ALT_E_BAD_ARG; }\r
+ return ALT_E_SUCCESS;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Sets the countdown value of the specified timer. */\r
+/****************************************************************************************/\r
+\r
+ALT_STATUS_CODE alt_wdog_counter_set(ALT_WDOG_TIMER_t tmr_id, uint32_t val)\r
+{\r
+ ALT_STATUS_CODE ret = ALT_E_BAD_ARG; // return value\r
+ uint32_t regdata; // returned data\r
+\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_LOAD_REG_OFFSET, val);\r
+ ret = ALT_E_SUCCESS;\r
+ // the ARM documentation is somewhat vague here, but it looks like it should be\r
+ // possible to rewrite this value while counter is running, and that it works in\r
+ // watchdog mode as well as timer mode. Verify operation when we have hardware.\r
+ }\r
+ else if (val <= ALT_WDOG_TIMEOUT2G)\r
+ {\r
+ if (tmr_id == ALT_WDOG0)\r
+ {\r
+ // set regular timeout value\r
+ regdata = alt_read_word(ALT_L4WD0_WDT_TORR_ADDR);\r
+ alt_write_word(ALT_L4WD0_WDT_TORR_ADDR, (regdata & ALT_L4WD_TORR_TOP_CLR_MSK) | val);\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ else if (tmr_id == ALT_WDOG1)\r
+ {\r
+ // set regular timeout value\r
+ regdata = alt_read_word(ALT_L4WD1_WDT_TORR_ADDR);\r
+ alt_write_word(ALT_L4WD1_WDT_TORR_ADDR, (regdata & ALT_L4WD_TORR_TOP_CLR_MSK) | val);\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ else if (tmr_id == ALT_WDOG0_INIT)\r
+ {\r
+ // set initial timeout value\r
+ regdata = alt_read_word(ALT_L4WD0_WDT_TORR_ADDR);\r
+ regdata = (regdata & ALT_L4WD_TORR_TOP_INIT_CLR_MSK) |\r
+ (val << ALT_L4WD_TORR_TOP_INIT_LSB);\r
+ alt_write_word(ALT_L4WD0_WDT_TORR_ADDR, regdata);\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ else if (tmr_id == ALT_WDOG1_INIT)\r
+ {\r
+ // set initial timeout value\r
+ regdata = alt_read_word(ALT_L4WD1_WDT_TORR_ADDR);\r
+ regdata = (regdata & ALT_L4WD_TORR_TOP_INIT_CLR_MSK) |\r
+ (val << ALT_L4WD_TORR_TOP_INIT_LSB);\r
+ alt_write_word(ALT_L4WD1_WDT_TORR_ADDR, regdata);\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ }\r
+ return ret;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns the current counter value of the specified timer. */\r
+/****************************************************************************************/\r
+\r
+uint32_t alt_wdog_counter_get_current(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ uint32_t ret = 0; // return value\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ ret = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CNTR_REG_OFFSET);\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
+ {\r
+ ret = alt_read_word(ALT_L4WD0_WDT_CCVR_ADDR);\r
+ }\r
+ else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ ret = alt_read_word(ALT_L4WD1_WDT_CCVR_ADDR);\r
+ }\r
+ return ret;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns the current counter value of the specified timer, as measured in */\r
+/* milliseconds. For ALT_CPU_WATCHDOG, this includes the effects of the prescaler */\r
+/* setting. */\r
+/****************************************************************************************/\r
+\r
+uint32_t alt_wdog_counter_get_curtime_millisecs(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ uint32_t time = 0; // return value\r
+ uint64_t bigtime; // temp for math\r
+ alt_freq_t freq; // clock frequency\r
+ ALT_CLK_t clk; // clock ID\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ clk = ALT_CLK_MPU_PERIPH;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG1) ||\r
+ (tmr_id == ALT_WDOG0_INIT) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ clk = ALT_CLK_OSC1;\r
+ }\r
+ else { return time; }\r
+\r
+ if ((alt_clk_freq_get(clk, &freq) == ALT_E_SUCCESS) && (freq != 0))\r
+ { // get clock frequency & test\r
+ time = alt_wdog_counter_get_current(tmr_id); // get current counter value\r
+ if (time != 0)\r
+ {\r
+ bigtime = (uint64_t) time;\r
+ // the current time period is not counted, only whole periods are counted\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ bigtime *= (uint64_t) (alt_wdog_core_prescaler_get() + 1);\r
+ }\r
+ bigtime *= ALT_MILLISECS_IN_A_SEC;\r
+ bigtime /= freq; // cycles-per-second becomes milliseconds-per-cycle\r
+ time = (bigtime > (uint64_t) UINT32_MAX) ? 0 : (uint32_t) bigtime;\r
+ }\r
+ }\r
+ return time;\r
+}\r
+\r
+\r
+// see the return value range calculations below at alt_wdog_counter_get_inittime_millisecs().\r
+\r
+/****************************************************************************************/\r
+/* Returns the initial counter value of the specified timer as a 32-bit integer */\r
+/* value. This is the value that will be reloaded when the timer is reset or restarted. */\r
+/* For the timers where this value is set as an encoded powers-of-two between 15 and */\r
+/* 31, the value is converted into the equivalent binary value before returning it. For */\r
+/* ALT_CPU_WATCHDOG, the returned value does not include the effects of the prescaler */\r
+/* setting */\r
+/****************************************************************************************/\r
+\r
+uint32_t alt_wdog_counter_get_init(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ uint32_t ret = 0; // value to return\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ ret = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_LOAD_REG_OFFSET);\r
+ }\r
+ else if (tmr_id == ALT_WDOG0)\r
+ {\r
+ ret = ALT_L4WD_TORR_TOP_GET(alt_read_word(ALT_L4WD0_WDT_TORR_ADDR));\r
+ ret = (ret > ALT_L4WD_TORR_TOP_E_TMO2G) ? 0 : ALT_TWO_TO_POW16 << ret;\r
+ }\r
+ else if (tmr_id == ALT_WDOG1)\r
+ {\r
+ ret = ALT_L4WD_TORR_TOP_GET(alt_read_word(ALT_L4WD1_WDT_TORR_ADDR));\r
+ ret = (ret > ALT_L4WD_TORR_TOP_E_TMO2G) ? 0 : ALT_TWO_TO_POW16 << ret;\r
+ }\r
+ else if (tmr_id == ALT_WDOG0_INIT)\r
+ {\r
+ ret = ALT_L4WD_TORR_TOP_INIT_GET(alt_read_word(ALT_L4WD0_WDT_TORR_ADDR));\r
+ ret = (ret > ALT_L4WD_TORR_TOP_INIT_E_TMO2G) ? 0 : ALT_TWO_TO_POW16 << ret;\r
+ }\r
+ else if (tmr_id == ALT_WDOG1_INIT)\r
+ {\r
+ ret = ALT_L4WD_TORR_TOP_INIT_GET(alt_read_word(ALT_L4WD1_WDT_TORR_ADDR));\r
+ ret = (ret > ALT_L4WD_TORR_TOP_INIT_E_TMO2G) ? 0 : ALT_TWO_TO_POW16 << ret;\r
+ }\r
+ return ret;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns the initial value of the specified timer in nanoseconds. This is the */\r
+/* value that will be reloaded when the timer is reset or restarted. For */\r
+/* ALT_CPU_WATCHDOG, this includes the effects of the prescaler setting. This call */\r
+/* returns a more precise result than alt_wdog_counter_get_inittime_millisecs(), but */\r
+/* as an unsigned 64-bit integer. */\r
+/****************************************************************************************/\r
+\r
+uint64_t alt_wdog_counter_get_inittime_nanosecs(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ uint64_t time = 0;\r
+ alt_freq_t freq;\r
+ ALT_CLK_t clk;\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ clk = ALT_CLK_MPU_PERIPH;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG1) ||\r
+ (tmr_id == ALT_WDOG0_INIT) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ clk = ALT_CLK_OSC1;\r
+ }\r
+ else { return time; } // zero always indicates an error for an init time\r
+\r
+ if ((alt_clk_freq_get(clk, &freq) == ALT_E_SUCCESS) && (freq != 0))\r
+ { // get clock frequency & test\r
+ time = (uint64_t) alt_wdog_counter_get_init(tmr_id); // get reset value\r
+ if (time != 0)\r
+ {\r
+ time += 1;\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ time *= (uint64_t) (alt_wdog_core_prescaler_get() + 1);\r
+ }\r
+ time *= ALT_NANOSECS_IN_A_SEC;\r
+ time /= freq; // cycles-per-second becomes nanoseconds per cycle\r
+ }\r
+ }\r
+\r
+ return time;\r
+}\r
+\r
+\r
+/* For reviewers:\r
+ * minimum clock divider for ALT_CPU_WATCHDOG is 1\r
+ * maximum clock divider for ALT_CPU_WATCHDOG is ((0xFFFF FFFF + 1) x (0x0000 0100) = 0x0000 0100 0000 0000)\r
+ * multiply that by the number of nanoseconds in a second (1,000,000,000)\r
+ * = 1,099,511,627,776,000,000,000 (0x9ACA 0000 0000 0000)\r
+ * so the countdown time with the slowest mpu_peripheral clock (2.5 MHz) =\r
+ * 400 nS to 439,804.6511104 seconds (0x0001 9000 0000 0000 nS)\r
+ * and with the fastest mpu_peripheral clock (200 MHz) =\r
+ * 5 nS to 5,497,558,138,880 nanoseconds ( 0x0000 0500 0000 0000 nS)\r
+ *\r
+ * minimum clock divider for peripheral watchdogs is 2**16 = (65,536 = 0x00010000)\r
+ * maximum clock divider for peripheral watchdogs is 2**31 = (2,147,483,648 = 0x8000 0000)\r
+ * multiply that by the number of nanoseconds in a second (1,000,000,000) =\r
+ * 4,096,000,000,000 (0x0000 03B9 ACA0 0000) to 2,147,483,648,000,000,000 (0x1DCD 6500 0000 0000)\r
+ * so the countdown time with the slowest l4_sp_clk (625 kHz) =\r
+ * 6,553,600 nS (0x0064 0000) to 3,435,973,836,800 nS (0x0000 0320 0000 0000 nS)\r
+ * and with the fastest l4_sp_clk (100 MHz) =\r
+ * 40,960 ns (0xA000) to 21,474,836,480 nS (0x0000 0005 0000 0000 nS)\r
+ */\r
+\r
+/****************************************************************************************/\r
+/* Returns the initial value of the specified timer in milliseconds. This is the */\r
+/* value that will be reloaded when the timer is reset or restarted. For */\r
+/* ALT_CPU_WATCHDOG, this includes the effects of the prescaler setting. This call */\r
+/* returns a 32-bit unsigned integer, though is less precise than */\r
+/* alt_wdog_counter_get_inittime_nanosecs(). */\r
+/****************************************************************************************/\r
+\r
+uint32_t alt_wdog_counter_get_inittime_millisecs(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ uint32_t time = 0;\r
+ alt_freq_t freq;\r
+ ALT_CLK_t clk;\r
+ uint64_t bigtime;\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ clk = ALT_CLK_MPU_PERIPH;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG1) ||\r
+ (tmr_id == ALT_WDOG0_INIT) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ clk = ALT_CLK_OSC1;\r
+ }\r
+ else { return time; } // must be an invalid tmr_id\r
+\r
+ if ((alt_clk_freq_get(clk, &freq) == ALT_E_SUCCESS) && (freq != 0))\r
+ { // get clock frequency & test\r
+ time = alt_wdog_counter_get_init(tmr_id); // get reset value\r
+ if (time != 0)\r
+ {\r
+ bigtime = ((uint64_t) time) + 1;\r
+ if (tmr_id == ALT_WDOG_CPU) // the only watchdog with a prescaler\r
+ {\r
+ bigtime *= (uint64_t) (alt_wdog_core_prescaler_get() + 1);\r
+ }\r
+ bigtime *= ALT_MILLISECS_IN_A_SEC; // scale value\r
+ bigtime /= freq; // cycles-per-second becomes milliseconds per cycle\r
+ time = (bigtime > (uint64_t) UINT32_MAX) ? 0 : (uint32_t) bigtime;\r
+ }\r
+ }\r
+ return time;\r
+}\r
+\r
+\r
+/* For reviewers:\r
+ * minimum clock divider for ALT_CPU_WATCHDOG is 1\r
+ * maximum clock divider for ALT_CPU_WATCHDOG is ((0xFFFF FFFF + 1) x (0x0000 0100) = 0x0000 0100 0000 0000)\r
+ * multiply that by the number of milliseconds in a second (1,000)\r
+ * = 1,000 (0x3e8) to 1,099,511,627,776,000 (0x0003 E800 0000 0000)\r
+ * so the countdown time with the slowest mpu_peripheral clock (2.5 MHz) =\r
+ * 0 mS to 439,804.6511104 seconds (0x1A36 E2EB mS)\r
+ * and with the fastest mpu_peripheral clock (200 MHz) =\r
+ * 0 mS to 5,497.55813888 seconds ( 0x0053 E2D6 mS)\r
+ *\r
+ * minimum clock divider for peripheral watchdogs is 2**16 = (65,536 = 0x00010000)\r
+ * maximum clock divider for peripheral watchdogs is 2**31 = (2,147,483,648 = 0x8000 0000)\r
+ * multiply that by the number of milliseconds in a second (1,000) =\r
+ * 65,536,000 (0x3E8 0000) to 2,147,483,648,000 (0x01F4 0000 0000)\r
+ * so the countdown time with the slowest l4_sp_clk (625 kHz) =\r
+ * 104 mS (0x0068) to 3,435,973 mS (0x0034 6DC5 mS)\r
+ * and with the fastest l4_sp_clk (100 MHz) = 0 mS to 21,474 mS (0x0000 53E2 mS)\r
+ */\r
+\r
+/****************************************************************************************/\r
+/* Sets the value of the CPU watchdog timer ALT_CPU_WATCHDOG prescaler. */\r
+/****************************************************************************************/\r
+\r
+ALT_STATUS_CODE alt_wdog_core_prescaler_set(uint32_t val)\r
+{\r
+ ALT_STATUS_CODE ret = ALT_E_BAD_ARG; // return value\r
+ uint32_t regdata;\r
+\r
+ if (val <= WDOG_PS_MAX)\r
+ {\r
+ if (alt_wdog_tmr_is_enabled(ALT_WDOG_CPU))\r
+ {\r
+ ret = ALT_E_ERROR;\r
+ }\r
+ else\r
+ {\r
+ regdata = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET);\r
+ alt_write_word((CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET),\r
+ (regdata & ~WDOG_PS_MASK) | (val << WDOG_PS_SHIFT));\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ }\r
+ return ret;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns the value of the prescaler of the CPU core watchdog timer. */\r
+/****************************************************************************************/\r
+\r
+uint32_t alt_wdog_core_prescaler_get(void)\r
+{\r
+ return (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) &\r
+ WDOG_PS_MASK) >> WDOG_PS_SHIFT;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns the maximum possible counter value of the specified timer as a 32-bit value. */\r
+/* For the timers where this value is encoded (as powers-of-two between 15 and 31), the */\r
+/* encoded value is converted into the equivalent binary value before returning it. */\r
+/* This does not include the effects of the prescaler available for ALT_CPU_WATCHDOG. */\r
+/****************************************************************************************/\r
+\r
+uint32_t alt_wdog_counter_get_max(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ uint32_t ret = 0; // return value\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ ret = WDOG_TMR_MAX;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG1)\r
+ || (tmr_id == ALT_WDOG0_INIT) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ ret = ((uint32_t) ALT_TWO_TO_POW16) << ALT_WDOG_TIMEOUT2G;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns the maximum possible delay time of the specified timer specified in */\r
+/* nanoseconds. For ALT_CPU_WATCHDOG, this includes the prescaler setting. This call */\r
+/* returns a more precise reading of the counter than */\r
+/* alt_wdog_counter_get_max_millisecs(), though in an unsigned 64-bit integer. */\r
+/****************************************************************************************/\r
+\r
+uint64_t alt_wdog_counter_get_max_nanosecs(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ uint64_t time = 0;\r
+ alt_freq_t freq;\r
+ ALT_CLK_t clk;\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ clk = ALT_CLK_MPU_PERIPH;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG1) ||\r
+ (tmr_id == ALT_WDOG0_INIT) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ clk = ALT_CLK_OSC1;\r
+ }\r
+ else { return time; }\r
+\r
+ if ((alt_clk_freq_get(clk, &freq) == ALT_E_SUCCESS) && (freq != 0))\r
+ { // get clock frequency & test\r
+ time = (uint64_t) alt_wdog_counter_get_max(tmr_id); // get maximum reset value\r
+ if (time != 0)\r
+ {\r
+ time += 1;\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ time *= (WDOG_PS_MAX + 1); // maximum prescaler\r
+ }\r
+ time *= ALT_NANOSECS_IN_A_SEC;\r
+ time /= freq; //cycles-per-second becomes nanoseconds-per-cycle\r
+ }\r
+ }\r
+ return time;\r
+}\r
+\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns the maximum possible delay time of the specified timer specified in */\r
+/* milliseconds. For ALT_CPU_WATCHDOG, this includes the prescaler setting. This call */\r
+/* returns a 32-bit unsigned integer, though is less precise than */\r
+/* alt_wdog_counter_get_max_nanosecs(). */\r
+/****************************************************************************************/\r
+\r
+uint32_t alt_wdog_counter_get_max_millisecs(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ uint32_t time = 0;\r
+ alt_freq_t freq;\r
+ ALT_CLK_t clk;\r
+ uint64_t bigtime;\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ clk = ALT_CLK_MPU_PERIPH;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG1) ||\r
+ (tmr_id == ALT_WDOG0_INIT) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ clk = ALT_CLK_OSC1;\r
+ }\r
+ else { return time; }\r
+\r
+ if ((alt_clk_freq_get(clk, &freq) == ALT_E_SUCCESS) && (freq != 0))\r
+ { // get clock frequency & test\r
+ time = alt_wdog_counter_get_max(tmr_id); // get reset value\r
+ if (time != 0)\r
+ {\r
+ bigtime = ((uint64_t) time) + 1;\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ bigtime *= (WDOG_PS_MAX + 1); // maximum prescaler\r
+ }\r
+ bigtime *= ALT_MILLISECS_IN_A_SEC;\r
+ bigtime /= freq; //cycles-per-second becomes milliseconds-per-cycle\r
+ time = (bigtime > (uint64_t) UINT32_MAX) ? 0 : (uint32_t) bigtime;\r
+ }\r
+ }\r
+ return time;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Disables the interrupt of the specified watchdog timer module. If the watchdog timer */\r
+/* is one of the watchdog timers that can be used in general-purpose mode, and if the */\r
+/* timer is in general-purpose timer mode, disable the interrupt. */\r
+/****************************************************************************************/\r
+\r
+ALT_STATUS_CODE alt_wdog_int_disable(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ ALT_STATUS_CODE ret = ALT_E_BAD_ARG; // return value\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ if (cpu_wdog_in_wdt_mode())\r
+ {\r
+ ret = ALT_E_ERROR;\r
+ }\r
+ else\r
+ {\r
+ alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET,\r
+ (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) & ~WDOG_INT_EN));\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ }\r
+ // returns an error for the other four watchdog timers\r
+ // since their interrupts cannot be disabled\r
+ // (this could change in v13.1)\r
+ return ret;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Sets/enables the interrupt of the specified watchdog timer module. If the watchdog */\r
+/* timer is one of the watchdog timers that can be used in general-purpose mode, and */\r
+/* if the timer is in general-purpose timer mode, enable the interrupt. */\r
+/****************************************************************************************/\r
+\r
+ALT_STATUS_CODE alt_wdog_int_enable(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ ALT_STATUS_CODE ret = ALT_E_BAD_ARG; // return value\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ if (cpu_wdog_in_wdt_mode())\r
+ {\r
+ ret = ALT_E_ERROR;\r
+ }\r
+ else\r
+ {\r
+ alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET,\r
+ (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) | WDOG_INT_EN));\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ }\r
+ return ret;\r
+ // other watchdog timers always have interrupt enabled if they are running\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns the status of the interrupt of the specified watchdog timer module but does */\r
+/* not clear it. Return TRUE if the interrupt of the specified general purpose timer */\r
+/* module is pending and FALSE otherwise. */\r
+/****************************************************************************************/\r
+\r
+bool alt_wdog_int_is_pending(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ bool ret = false; //return value\r
+\r
+ if ((tmr_id == ALT_WDOG_CPU) && cpu_wdog_in_gpt_mode())\r
+ {\r
+ ret = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_INTSTAT_REG_OFFSET) & WDOG_INT_STAT_BIT;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
+ {\r
+ ret = alt_read_word(ALT_L4WD0_WDT_STAT_ADDR) & ALT_L4WD_STAT_WDT_STAT_SET_MSK;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ ret = alt_read_word(ALT_L4WD1_WDT_STAT_ADDR) & ALT_L4WD_STAT_WDT_STAT_SET_MSK;\r
+ }\r
+ return ret;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns the state of the interrupt of the specified watchdog timer module. If the */\r
+/* watchdog timer is one of the watchdog timers that can be used in general-purpose */\r
+/* mode, and if the timer is in general-purpose timer mode, returns TRUE if the */\r
+/* interrupt of the specified general purpose timer module is enabled and FALSE if */\r
+/* disabled. If the timer is not in general-purpose timer mode, returns TRUE, as */\r
+/* watchdog interrupts are always enabled. */\r
+/****************************************************************************************/\r
+\r
+bool alt_wdog_int_is_enabled(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ bool ret = false; //return value\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ ret = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) &\r
+ (WDOG_INT_EN | WDOG_WDT_MODE);\r
+ // if in watchdog mode OR if in general purpose timer mode\r
+ // AND the interrupt is enabled\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
+ {\r
+ ret = alt_read_word(ALT_L4WD0_WDT_CR_ADDR) & ALT_L4WD_CR_WDT_EN_SET_MSK;\r
+ // if these timers are running, their interrupt is enabled\r
+ }\r
+ else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ ret = alt_read_word(ALT_L4WD1_WDT_CR_ADDR) & ALT_L4WD_CR_WDT_EN_SET_MSK;\r
+ // if these timers are running, their interrupt is enabled\r
+ }\r
+ return ret;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Clears the pending status of the interrupt of the specified watchdog timer module. */\r
+/****************************************************************************************/\r
+\r
+ALT_STATUS_CODE alt_wdog_int_clear(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_INTSTAT_REG_OFFSET, WDOG_INT_STAT_BIT);\r
+ // clear int by writing to status bit\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
+ {\r
+ (void) alt_read_word(ALT_L4WD0_WDT_EOI_ADDR);\r
+ // clear int by reading from end-of-interrupt register\r
+ // adding the void cast tells armcc not to throw a error for this usage\r
+ }\r
+ else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ (void) alt_read_word(ALT_L4WD1_WDT_EOI_ADDR);\r
+ // clear int by reading from end-of-interrupt register\r
+ }\r
+ else {return ALT_E_ERROR; }\r
+ return ALT_E_SUCCESS;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns the status of the interrupt of the specified watchdog timer module and also */\r
+/* clears it. Return TRUE if the interrupt of the specified general purpose timer */\r
+/* module is pending and FALSE otherwise. */\r
+/****************************************************************************************/\r
+\r
+bool alt_wdog_int_if_pending_clear(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ uint32_t ret = false; // value to return\r
+\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ ret = (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_INTSTAT_REG_OFFSET) & WDOG_INT_STAT_BIT);\r
+ if (ret)\r
+ {\r
+ alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_INTSTAT_REG_OFFSET, WDOG_INT_STAT_BIT);\r
+ // clear int by writing to status bit\r
+ }\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
+ {\r
+ ret = alt_read_word(ALT_L4WD0_WDT_STAT_ADDR) & ALT_L4WD_STAT_WDT_STAT_SET_MSK;\r
+ if (ret)\r
+ {\r
+ (void) alt_read_word(ALT_L4WD0_WDT_EOI_ADDR);\r
+ // clear int by reading from end-of-interrupt register\r
+ // adding the void cast tells armcc not to throw a error for this usage\r
+\r
+ }\r
+ }\r
+ else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ ret = alt_read_word(ALT_L4WD1_WDT_STAT_ADDR) & ALT_L4WD_STAT_WDT_STAT_SET_MSK;\r
+\r
+ if (ret)\r
+ {\r
+ (void) alt_read_word(ALT_L4WD1_WDT_EOI_ADDR);\r
+ // clear int by reading from end-of-interrupt register\r
+ }\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Sets the timeout response mode of the specified watchdog timer. For ALT_WATCHDOG0, */\r
+/* ALT_WATCHDOG1, \b ALT_WATCHDOG0_INITIAL or \b ALT_WATCHDOG1_INITIAL, the options */\r
+/* are to generate a system reset or to generate an interrupt and then generate a */\r
+/* system reset if the interrupt is not cleared by the next time the watchdog timer */\r
+/* counter rolls over. For ALT_CPU_WATCHDOG, the options are to trigger an interrupt */\r
+/* request (with the result set in the interrupt manager) or a reset request (with the */\r
+/* result set in the reset manager) plus two more options available when it is used */\r
+/* as a general-purpose timer. */\r
+/****************************************************************************************/\r
+\r
+ALT_STATUS_CODE alt_wdog_response_mode_set(ALT_WDOG_TIMER_t tmr_id, ALT_WDOG_RESET_TYPE_t type)\r
+{\r
+ ALT_STATUS_CODE ret = ALT_E_BAD_ARG; // return value\r
+ uint32_t regdata; // register data\r
+\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ regdata = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET);\r
+ if (type == ALT_WDOG_TIMER_MODE_ONESHOT)\r
+ {\r
+ alt_write_word((CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET), regdata & ~WDOG_AUTO_RELOAD);\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ else if (type == ALT_WDOG_TIMER_MODE_FREERUN)\r
+ {\r
+ alt_write_word((CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET), regdata | WDOG_AUTO_RELOAD);\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
+ {\r
+ regdata = alt_read_word(ALT_L4WD0_WDT_CR_ADDR);\r
+ if (type == ALT_WDOG_WARM_RESET)\r
+ {\r
+ alt_write_word(ALT_L4WD0_WDT_CR_ADDR, regdata & ALT_L4WD_CR_RMOD_CLR_MSK);\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ else if (type == ALT_WDOG_INT_THEN_RESET)\r
+ {\r
+ alt_write_word(ALT_L4WD0_WDT_CR_ADDR, regdata | ALT_L4WD_CR_RMOD_SET_MSK);\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ }\r
+ else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ regdata = alt_read_word(ALT_L4WD1_WDT_CR_ADDR);\r
+ if (type == ALT_WDOG_WARM_RESET)\r
+ {\r
+ alt_write_word(ALT_L4WD1_WDT_CR_ADDR, regdata & ALT_L4WD_CR_RMOD_CLR_MSK);\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ else if (type == ALT_WDOG_INT_THEN_RESET)\r
+ {\r
+ alt_write_word(ALT_L4WD1_WDT_CR_ADDR, regdata | ALT_L4WD_CR_RMOD_SET_MSK);\r
+ ret = ALT_E_SUCCESS;\r
+ }\r
+ }\r
+ return ret; // rejects a bad tmr_id argument/type argument combination\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns the response mode of the specified timer. */\r
+/****************************************************************************************/\r
+\r
+int32_t alt_wdog_response_mode_get(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ int32_t ret = ALT_E_BAD_ARG; // return value\r
+ uint32_t regdata; // read value\r
+\r
+\r
+ if (tmr_id == ALT_WDOG_CPU)\r
+ {\r
+ regdata = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET);\r
+ ret = (regdata & WDOG_AUTO_RELOAD) ? ALT_WDOG_TIMER_MODE_FREERUN : ALT_WDOG_TIMER_MODE_ONESHOT;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
+ {\r
+ regdata = alt_read_word(ALT_L4WD0_WDT_CR_ADDR);\r
+ ret = (regdata & ALT_L4WD_CR_RMOD_SET_MSK) ? ALT_WDOG_INT_THEN_RESET : ALT_WDOG_WARM_RESET;\r
+ }\r
+ else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ regdata = alt_read_word(ALT_L4WD1_WDT_CR_ADDR);\r
+ ret = (regdata & ALT_L4WD_CR_RMOD_SET_MSK) ? ALT_WDOG_INT_THEN_RESET : ALT_WDOG_WARM_RESET;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns the component code of the watchdog timer module. Only valid for */\r
+/* ALT_WATCHDOG0, ALT_WATCHDOG1, ALT_WATCHDOG0_INITIAL or ALT_WATCHDOG1_INITIAL. */\r
+/****************************************************************************************/\r
+\r
+uint32_t alt_wdog_compcode_get(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ uint32_t component = 0; // component code of the module\r
+\r
+ if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
+ {\r
+ component = alt_read_word(ALT_L4WD0_WDT_COMP_TYPE_ADDR);\r
+ }\r
+ else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ component = alt_read_word(ALT_L4WD1_WDT_COMP_TYPE_ADDR);\r
+\r
+ }\r
+ return component;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+/* Returns the version code of the watchdog timer module. Only valid for ALT_WATCHDOG0, */\r
+/* ALT_WATCHDOG1, ALT_WATCHDOG0_INITIAL or ALT_WATCHDOG1_INITIAL. */\r
+/****************************************************************************************/\r
+\r
+uint32_t alt_wdog_ver_get(ALT_WDOG_TIMER_t tmr_id)\r
+{\r
+ uint32_t ver = 0; // revision code of the module\r
+\r
+ if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
+ {\r
+ ver = alt_read_word(ALT_L4WD0_WDT_COMP_VER_ADDR);\r
+ }\r
+ else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
+ {\r
+ ver = alt_read_word(ALT_L4WD1_WDT_COMP_VER_ADDR);\r
+\r
+ }\r
+ return ver;\r
+}\r
+\r
+\r
+/****************************************************************************************/\r
+\r
+\r