]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Cyclone_V_SoC_DK/Altera_Code/HardwareLibrary/alt_watchdog.c
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS / Demo / CORTEX_A9_Cyclone_V_SoC_DK / Altera_Code / HardwareLibrary / alt_watchdog.c
1 \r
2 /******************************************************************************\r
3 *\r
4 * alt_watchdog.c - API for the Altera SoC FPGA watchdog timers.\r
5 *\r
6 ******************************************************************************/\r
7 \r
8 /******************************************************************************\r
9 *\r
10 * Copyright 2013 Altera Corporation. All Rights Reserved.\r
11 *\r
12 * Redistribution and use in source and binary forms, with or without\r
13 * modification, are permitted provided that the following conditions are met:\r
14 *\r
15 * 1. Redistributions of source code must retain the above copyright notice,\r
16 * this list of conditions and the following disclaimer.\r
17 *\r
18 * 2. Redistributions in binary form must reproduce the above copyright notice,\r
19 * this list of conditions and the following disclaimer in the documentation\r
20 * and/or other materials provided with the distribution.\r
21 *\r
22 * 3. The name of the author may not be used to endorse or promote products\r
23 * derived from this software without specific prior written permission.\r
24 *\r
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR\r
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO\r
28 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\r
30 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\r
33 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\r
34 * OF SUCH DAMAGE.\r
35 *\r
36 ******************************************************************************/\r
37 \r
38 /******************************************************************************\r
39 *\r
40 * The Altera SoC FPGA has six watchdog timers, two are local to the MPU\r
41 * themselves, and the other four are accessable to either MPU.\r
42 *\r
43 ******************************************************************************/\r
44 \r
45 #include <stdint.h>\r
46 #include <stdbool.h>\r
47 #include "socal/hps.h"\r
48 #include "socal/socal.h"\r
49 #include "socal/alt_rstmgr.h"\r
50 #include "socal/alt_l4wd.h"\r
51 #include "socal/alt_tmr.h"\r
52 #include "hwlib.h"\r
53 #include "alt_mpu_registers.h"\r
54 #include "alt_watchdog.h"\r
55 #include "alt_clock_manager.h"\r
56 \r
57 \r
58     /* Useful constants and utilities */\r
59 \r
60 bool cpu_wdog_in_gpt_mode(void)\r
61 {\r
62     return !(alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) & WDOG_WDT_MODE);\r
63 }\r
64 \r
65 static inline bool cpu_wdog_in_wdt_mode(void)\r
66 {\r
67     return (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) & WDOG_WDT_MODE);\r
68 }\r
69 \r
70 \r
71 /* This value must be written to the Counter Restart Register of the\r
72  * peripheral watchdog timers to restart them. */\r
73 #define WDOG_RESET_KEY          0x00000076\r
74 \r
75 #define ALT_WDOG_RST_WIDTH      8                       /* 8 or more MPU clock cycles */\r
76 \r
77 \r
78 inline static void alt_wdog_wait(void* reg, uint32_t cnt)\r
79 {\r
80     for (; cnt ; cnt--)\r
81     {\r
82         (void) alt_read_word(reg);\r
83     }\r
84 }\r
85 \r
86 \r
87 /****************************************************************************************/\r
88 /* Initialize the watchdog timer module before use                                      */\r
89 /****************************************************************************************/\r
90 \r
91 ALT_STATUS_CODE alt_wdog_init(void)\r
92 {\r
93     // put watchdog timer modules into system manager reset if not already there\r
94     alt_wdog_uninit();\r
95     // release L4 watchdog timer modules from system reset (w/ four instruction-cycle delay)\r
96     alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_L4WD0_SET_MSK |\r
97             ALT_RSTMGR_PERMODRST_L4WD1_SET_MSK);\r
98 \r
99     // release *both* ARM watchdog timer modules from system reset (if in reset)\r
100     // does not put either one into watchdog timer mode\r
101     alt_clrbits_word(ALT_RSTMGR_MPUMODRST_ADDR, ALT_RSTMGR_MPUMODRST_WDS_SET_MSK);\r
102     return ALT_E_SUCCESS;\r
103 }\r
104 \r
105 \r
106 /****************************************************************************************/\r
107 /* Return the local ARM watchdog timer back to general-purpose timer mode               */\r
108 /****************************************************************************************/\r
109 \r
110 void alt_ARM_wdog_gpt_mode_set(void)\r
111 {\r
112     while (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) & WDOG_WDT_MODE)\r
113     {\r
114         alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_DISABLE_REG_OFFSET, WDOG_DISABLE_VAL0);\r
115         alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_DISABLE_REG_OFFSET, WDOG_DISABLE_VAL1);\r
116     }\r
117 }\r
118 \r
119 \r
120 /****************************************************************************************/\r
121 /* Set the local ARM watchdog timer to watchdog timer mode                              */\r
122 /****************************************************************************************/\r
123 \r
124 void alt_ARM_wdog_wdog_mode_set(void)\r
125 {\r
126     alt_setbits_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET, WDOG_WDT_MODE);\r
127 }\r
128 \r
129 \r
130 /****************************************************************************************/\r
131 /* Uninitialize the watchdog timer module & return to reset state                        */\r
132 /****************************************************************************************/\r
133 \r
134 ALT_STATUS_CODE alt_wdog_uninit(void)\r
135 {\r
136     // put L4 watchdog modules into system manager reset\r
137     alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR,\r
138             ALT_RSTMGR_PERMODRST_L4WD0_SET_MSK | ALT_RSTMGR_PERMODRST_L4WD1_SET_MSK);\r
139 \r
140         // using the system manager bit to reset the ARM watchdog timer\r
141         // resets *both* ARM watchdog timers, which is often not advisable,\r
142         // so we reset the local ARM watchdog timer manually:\r
143 \r
144         // first, stop the ARM watchdog timer & disable interrupt\r
145     alt_clrbits_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET, WDOG_TMR_ENABLE | WDOG_INT_EN);\r
146         // reset load and counter registers\r
147     alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_LOAD_REG_OFFSET, 0);\r
148         // clear any pending reset and interrupt status\r
149     alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_RSTSTAT_REG_OFFSET, WDOG_RST_STAT_BIT);\r
150     alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_INTSTAT_REG_OFFSET, WDOG_INT_STAT_BIT);\r
151         // return ARM watchdog timer to (initial) general-purpose timer mode\r
152     alt_ARM_wdog_gpt_mode_set();\r
153         // now write zeros to the control register significant bitfields\r
154         // and then verify that all significant bitfields return zero\r
155     alt_clrbits_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET,\r
156             (WDOG_PS_MASK | WDOG_WDT_MODE | WDOG_INT_EN | WDOG_AUTO_RELOAD | WDOG_TMR_ENABLE));\r
157     if (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET)\r
158             & (WDOG_PS_MASK | WDOG_WDT_MODE | WDOG_INT_EN | WDOG_AUTO_RELOAD | WDOG_TMR_ENABLE))\r
159     {\r
160         return ALT_E_ERROR;\r
161     }\r
162     return ALT_E_SUCCESS;\r
163 \r
164 }\r
165 \r
166 \r
167 /****************************************************************************************/\r
168 /* Stops the specified watchdog timer.                                                  */\r
169 /****************************************************************************************/\r
170 \r
171 ALT_STATUS_CODE alt_wdog_stop(ALT_WDOG_TIMER_t tmr_id)\r
172 {\r
173     ALT_STATUS_CODE         ret = ALT_E_BAD_ARG;    // return value\r
174     uint32_t                config;                 // the current configuration\r
175     uint32_t                loadreg;                // current restart value\r
176 \r
177 \r
178     if (tmr_id == ALT_WDOG_CPU)\r
179     {\r
180         alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET,\r
181                 (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) & ~WDOG_TMR_ENABLE));\r
182         ret = ALT_E_SUCCESS;\r
183     }\r
184 \r
185     // these timers can only be reset by using a system manager reset\r
186     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
187     {\r
188         config = alt_read_word(ALT_L4WD0_WDT_CR_ADDR);      // read current timer mode\r
189         loadreg = alt_read_word(ALT_L4WD0_WDT_TORR_ADDR);   // read timer restart values\r
190         alt_write_word(ALT_RSTMGR_PERMODRST_ADDR,\r
191                 alt_read_word(ALT_RSTMGR_PERMODRST_ADDR) | ALT_RSTMGR_PERMODRST_L4WD0_SET_MSK);\r
192                         // assert reset & wait\r
193         alt_wdog_wait(ALT_RSTMGR_PERMODRST_ADDR, ALT_WDOG_RST_WIDTH);\r
194         alt_write_word(ALT_RSTMGR_PERMODRST_ADDR,\r
195                 alt_read_word(ALT_RSTMGR_PERMODRST_ADDR) & ALT_RSTMGR_PERMODRST_L4WD0_CLR_MSK);\r
196                         // release peripheral reset signal by clearing bit\r
197         alt_write_word(ALT_L4WD0_WDT_TORR_ADDR, loadreg);   // restore timer restart value\r
198         alt_write_word(ALT_L4WD0_WDT_CR_ADDR, config & ALT_TMR_TMR1CTLREG_TMR1_EN_CLR_MSK);\r
199                           // restore previous timer mode except timer isn't started\r
200         ret = ALT_E_SUCCESS;\r
201     }\r
202     else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
203     {\r
204         config = alt_read_word(ALT_L4WD1_WDT_CR_ADDR);      // read current timer mode\r
205         loadreg = alt_read_word(ALT_L4WD1_WDT_TORR_ADDR);   // read timer restart values\r
206         alt_write_word(ALT_RSTMGR_PERMODRST_ADDR,\r
207                 alt_read_word(ALT_RSTMGR_PERMODRST_ADDR) | ALT_RSTMGR_PERMODRST_L4WD1_SET_MSK);\r
208                         // assert reset & wait\r
209         alt_write_word(ALT_RSTMGR_PERMODRST_ADDR,\r
210                 alt_read_word(ALT_RSTMGR_PERMODRST_ADDR) & ALT_RSTMGR_PERMODRST_L4WD1_CLR_MSK);\r
211                          // release peripheral reset signal by clearing bit\r
212         alt_write_word(ALT_L4WD1_WDT_TORR_ADDR, loadreg);   // restore timer restart value\r
213         alt_write_word(ALT_L4WD1_WDT_CR_ADDR, config & ALT_TMR_TMR1CTLREG_TMR1_EN_CLR_MSK);\r
214                           // restore previous timer mode except timer isn't started\r
215         ret = ALT_E_SUCCESS;\r
216     }\r
217     return  ret;\r
218 }\r
219 \r
220 /****************************************************************************************/\r
221 /* Start the specified watchdog timer.                                                  */\r
222 /****************************************************************************************/\r
223 \r
224 ALT_STATUS_CODE alt_wdog_start(ALT_WDOG_TIMER_t tmr_id)\r
225 {\r
226     ALT_STATUS_CODE     ret = ALT_E_BAD_ARG;    // return value\r
227     uint32_t            regdata;                // data\r
228 \r
229 \r
230     if (tmr_id == ALT_WDOG_CPU)\r
231     {\r
232         regdata = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET);\r
233         alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET, regdata | WDOG_TMR_ENABLE);\r
234         ret = ALT_E_SUCCESS;\r
235     }\r
236     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
237     {\r
238         regdata = alt_read_word(ALT_L4WD0_WDT_CR_ADDR);\r
239         alt_write_word(ALT_L4WD0_WDT_CR_ADDR, regdata | ALT_L4WD_CR_WDT_EN_SET_MSK);\r
240         ret = ALT_E_SUCCESS;\r
241     }\r
242     else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
243     {\r
244         regdata = alt_read_word(ALT_L4WD1_WDT_CR_ADDR);\r
245         alt_write_word(ALT_L4WD1_WDT_CR_ADDR, regdata | ALT_L4WD_CR_WDT_EN_SET_MSK);\r
246         ret = ALT_E_SUCCESS;\r
247     }\r
248     return  ret;\r
249 }\r
250 \r
251 \r
252 /****************************************************************************************/\r
253 /* Returns whether the specified watchdog timer is currently running or not.            */\r
254 /****************************************************************************************/\r
255 \r
256 bool alt_wdog_tmr_is_enabled(ALT_WDOG_TIMER_t tmr_id)\r
257 {\r
258     bool      ret = false;          // return value\r
259 \r
260 \r
261     if (tmr_id == ALT_WDOG_CPU)\r
262     {\r
263         ret = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) & WDOG_TMR_ENABLE;\r
264     }\r
265     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
266     {\r
267         ret = alt_read_word(ALT_L4WD0_WDT_CR_ADDR) & ALT_L4WD_CR_WDT_EN_SET_MSK;\r
268     }\r
269 \r
270     else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
271     {\r
272         ret = alt_read_word(ALT_L4WD1_WDT_CR_ADDR) & ALT_L4WD_CR_WDT_EN_SET_MSK;\r
273     }\r
274     return  ret;\r
275 }\r
276 \r
277 \r
278 /****************************************************************************************/\r
279 /*  Reloads the counter countdown value and restarts the watchdog timer. User can reset */\r
280 /*  the timer at any time before timeout. Also known as kicking, petting, feeding,      */\r
281 /* waking, or walking the watchdog. Inherently clears the interrupt as well.            */\r
282 /****************************************************************************************/\r
283 \r
284 ALT_STATUS_CODE alt_wdog_reset(ALT_WDOG_TIMER_t tmr_id)\r
285 {\r
286     uint32_t                regdata;        // data read\r
287 \r
288 \r
289     if (tmr_id == ALT_WDOG_CPU)\r
290     {\r
291         regdata = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_LOAD_REG_OFFSET);\r
292         alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_LOAD_REG_OFFSET, regdata);\r
293                 // verify operation when we have hardware,\r
294                 // the ARM documentation is somewhat vague here\r
295 \r
296         if (cpu_wdog_in_wdt_mode())\r
297         {\r
298             alt_write_word((CPU_WDTGPT_TMR_BASE + WDOG_RSTSTAT_REG_OFFSET), WDOG_RST_STAT_BIT);\r
299                       // depending on current mode, clear the reset bit or...\r
300         }\r
301         else\r
302         {\r
303             alt_write_word((CPU_WDTGPT_TMR_BASE + WDOG_INTSTAT_REG_OFFSET), WDOG_INT_STAT_BIT);\r
304                       // ...clear the interrupt status bit by writing one to it\r
305         }\r
306     }\r
307     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
308     {\r
309         alt_write_word(ALT_L4WD0_WDT_CRR_ADDR, WDOG_RESET_KEY);\r
310             //restarts the counter, also clears the watchdog timer interrupt\r
311     }\r
312     else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
313     {\r
314         alt_write_word(ALT_L4WD1_WDT_CRR_ADDR, WDOG_RESET_KEY);\r
315             //restarts the counter, also clears the watchdog timer interrupt\r
316     }\r
317     else {return  ALT_E_BAD_ARG; }\r
318     return ALT_E_SUCCESS;\r
319 }\r
320 \r
321 \r
322 /****************************************************************************************/\r
323 /* Sets the countdown value of the specified timer.                                     */\r
324 /****************************************************************************************/\r
325 \r
326 ALT_STATUS_CODE alt_wdog_counter_set(ALT_WDOG_TIMER_t tmr_id, uint32_t val)\r
327 {\r
328     ALT_STATUS_CODE         ret = ALT_E_BAD_ARG;    // return value\r
329     uint32_t                regdata;                // returned data\r
330 \r
331 \r
332     if (tmr_id == ALT_WDOG_CPU)\r
333     {\r
334         alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_LOAD_REG_OFFSET, val);\r
335         ret = ALT_E_SUCCESS;\r
336         // the ARM documentation is somewhat vague here, but it looks like it should be\r
337         // possible to rewrite this value while counter is running, and that it works in\r
338         // watchdog mode as well as timer mode. Verify operation when we have hardware.\r
339     }\r
340     else if (val <= ALT_WDOG_TIMEOUT2G)\r
341     {\r
342         if (tmr_id == ALT_WDOG0)\r
343         {\r
344             // set regular timeout value\r
345             regdata = alt_read_word(ALT_L4WD0_WDT_TORR_ADDR);\r
346             alt_write_word(ALT_L4WD0_WDT_TORR_ADDR, (regdata & ALT_L4WD_TORR_TOP_CLR_MSK) | val);\r
347             ret = ALT_E_SUCCESS;\r
348         }\r
349         else if (tmr_id == ALT_WDOG1)\r
350         {\r
351             // set regular timeout value\r
352             regdata = alt_read_word(ALT_L4WD1_WDT_TORR_ADDR);\r
353             alt_write_word(ALT_L4WD1_WDT_TORR_ADDR, (regdata & ALT_L4WD_TORR_TOP_CLR_MSK) | val);\r
354             ret = ALT_E_SUCCESS;\r
355         }\r
356         else if (tmr_id == ALT_WDOG0_INIT)\r
357         {\r
358             // set initial timeout value\r
359             regdata = alt_read_word(ALT_L4WD0_WDT_TORR_ADDR);\r
360             regdata = (regdata & ALT_L4WD_TORR_TOP_INIT_CLR_MSK) |\r
361                     (val << ALT_L4WD_TORR_TOP_INIT_LSB);\r
362             alt_write_word(ALT_L4WD0_WDT_TORR_ADDR, regdata);\r
363             ret = ALT_E_SUCCESS;\r
364         }\r
365         else if (tmr_id == ALT_WDOG1_INIT)\r
366         {\r
367             // set initial timeout value\r
368             regdata = alt_read_word(ALT_L4WD1_WDT_TORR_ADDR);\r
369             regdata = (regdata & ALT_L4WD_TORR_TOP_INIT_CLR_MSK) |\r
370                     (val << ALT_L4WD_TORR_TOP_INIT_LSB);\r
371             alt_write_word(ALT_L4WD1_WDT_TORR_ADDR, regdata);\r
372             ret = ALT_E_SUCCESS;\r
373         }\r
374     }\r
375     return  ret;\r
376 }\r
377 \r
378 \r
379 /****************************************************************************************/\r
380 /* Returns the current counter value of the specified timer.                            */\r
381 /****************************************************************************************/\r
382 \r
383 uint32_t alt_wdog_counter_get_current(ALT_WDOG_TIMER_t tmr_id)\r
384 {\r
385     uint32_t     ret = 0;           // return value\r
386 \r
387     if (tmr_id == ALT_WDOG_CPU)\r
388     {\r
389         ret = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CNTR_REG_OFFSET);\r
390     }\r
391     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
392     {\r
393         ret = alt_read_word(ALT_L4WD0_WDT_CCVR_ADDR);\r
394     }\r
395     else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
396     {\r
397         ret = alt_read_word(ALT_L4WD1_WDT_CCVR_ADDR);\r
398     }\r
399     return ret;\r
400 }\r
401 \r
402 \r
403 /****************************************************************************************/\r
404 /* Returns the current counter value of the specified timer, as measured in             */\r
405 /* milliseconds. For ALT_CPU_WATCHDOG, this includes the effects of the prescaler       */\r
406 /* setting.                                                                             */\r
407 /****************************************************************************************/\r
408 \r
409 uint32_t alt_wdog_counter_get_curtime_millisecs(ALT_WDOG_TIMER_t tmr_id)\r
410 {\r
411     uint32_t        time = 0;           // return value\r
412     uint64_t        bigtime;            // temp for math\r
413     alt_freq_t      freq;               // clock frequency\r
414     ALT_CLK_t       clk;                // clock ID\r
415 \r
416     if (tmr_id == ALT_WDOG_CPU)\r
417     {\r
418         clk = ALT_CLK_MPU_PERIPH;\r
419     }\r
420     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG1) ||\r
421             (tmr_id == ALT_WDOG0_INIT) || (tmr_id == ALT_WDOG1_INIT))\r
422     {\r
423         clk = ALT_CLK_OSC1;\r
424     }\r
425     else { return time; }\r
426 \r
427     if ((alt_clk_freq_get(clk, &freq) == ALT_E_SUCCESS) && (freq != 0))\r
428     {                               // get clock frequency & test\r
429         time = alt_wdog_counter_get_current(tmr_id);    // get current counter value\r
430         if (time != 0)\r
431         {\r
432             bigtime = (uint64_t) time;\r
433                   // the current time period is not counted, only whole periods are counted\r
434             if (tmr_id == ALT_WDOG_CPU)\r
435             {\r
436                 bigtime *= (uint64_t) (alt_wdog_core_prescaler_get() + 1);\r
437             }\r
438             bigtime *= ALT_MILLISECS_IN_A_SEC;\r
439             bigtime /= freq;          // cycles-per-second becomes milliseconds-per-cycle\r
440             time = (bigtime > (uint64_t) UINT32_MAX) ? 0 : (uint32_t) bigtime;\r
441         }\r
442     }\r
443     return  time;\r
444 }\r
445 \r
446 \r
447 // see the return value range calculations below at alt_wdog_counter_get_inittime_millisecs().\r
448 \r
449 /****************************************************************************************/\r
450 /* Returns the initial counter value of the specified timer as a 32-bit integer         */\r
451 /* value. This is the value that will be reloaded when the timer is reset or restarted. */\r
452 /* For the timers where this value is set as an encoded powers-of-two between 15 and    */\r
453 /* 31, the value is converted into the equivalent binary value before returning it. For */\r
454 /* ALT_CPU_WATCHDOG, the returned value does not include the effects of the prescaler   */\r
455 /* setting                                                                              */\r
456 /****************************************************************************************/\r
457 \r
458 uint32_t alt_wdog_counter_get_init(ALT_WDOG_TIMER_t tmr_id)\r
459 {\r
460     uint32_t                ret = 0;        //    value to return\r
461 \r
462     if (tmr_id == ALT_WDOG_CPU)\r
463     {\r
464         ret = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_LOAD_REG_OFFSET);\r
465     }\r
466     else if (tmr_id == ALT_WDOG0)\r
467     {\r
468         ret = ALT_L4WD_TORR_TOP_GET(alt_read_word(ALT_L4WD0_WDT_TORR_ADDR));\r
469         ret = (ret >  ALT_L4WD_TORR_TOP_E_TMO2G) ? 0 : ALT_TWO_TO_POW16 << ret;\r
470     }\r
471     else if (tmr_id == ALT_WDOG1)\r
472     {\r
473         ret = ALT_L4WD_TORR_TOP_GET(alt_read_word(ALT_L4WD1_WDT_TORR_ADDR));\r
474         ret = (ret >  ALT_L4WD_TORR_TOP_E_TMO2G) ? 0 : ALT_TWO_TO_POW16 << ret;\r
475     }\r
476     else if (tmr_id == ALT_WDOG0_INIT)\r
477     {\r
478         ret = ALT_L4WD_TORR_TOP_INIT_GET(alt_read_word(ALT_L4WD0_WDT_TORR_ADDR));\r
479         ret = (ret >  ALT_L4WD_TORR_TOP_INIT_E_TMO2G) ? 0 : ALT_TWO_TO_POW16 << ret;\r
480     }\r
481     else if (tmr_id == ALT_WDOG1_INIT)\r
482     {\r
483         ret = ALT_L4WD_TORR_TOP_INIT_GET(alt_read_word(ALT_L4WD1_WDT_TORR_ADDR));\r
484         ret = (ret >  ALT_L4WD_TORR_TOP_INIT_E_TMO2G) ? 0 : ALT_TWO_TO_POW16 << ret;\r
485     }\r
486     return  ret;\r
487 }\r
488 \r
489 \r
490 /****************************************************************************************/\r
491 /* Returns the initial value of the specified timer in nanoseconds. This is the         */\r
492 /* value that will be reloaded when the timer is reset or restarted. For                */\r
493 /* ALT_CPU_WATCHDOG, this includes the effects of the prescaler setting.  This call     */\r
494 /* returns a more precise result than alt_wdog_counter_get_inittime_millisecs(), but    */\r
495 /* as an unsigned 64-bit integer.                                                       */\r
496 /****************************************************************************************/\r
497 \r
498 uint64_t alt_wdog_counter_get_inittime_nanosecs(ALT_WDOG_TIMER_t tmr_id)\r
499 {\r
500     uint64_t    time = 0;\r
501     alt_freq_t  freq;\r
502     ALT_CLK_t   clk;\r
503 \r
504     if (tmr_id == ALT_WDOG_CPU)\r
505     {\r
506         clk = ALT_CLK_MPU_PERIPH;\r
507     }\r
508     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG1) ||\r
509             (tmr_id == ALT_WDOG0_INIT) || (tmr_id == ALT_WDOG1_INIT))\r
510     {\r
511         clk = ALT_CLK_OSC1;\r
512     }\r
513     else { return time; }            // zero always indicates an error for an init time\r
514 \r
515     if ((alt_clk_freq_get(clk, &freq) == ALT_E_SUCCESS) && (freq != 0))\r
516     {                               // get clock frequency & test\r
517         time = (uint64_t) alt_wdog_counter_get_init(tmr_id);     // get reset value\r
518         if (time != 0)\r
519         {\r
520             time += 1;\r
521             if (tmr_id == ALT_WDOG_CPU)\r
522             {\r
523                 time *= (uint64_t) (alt_wdog_core_prescaler_get() + 1);\r
524             }\r
525             time *= ALT_NANOSECS_IN_A_SEC;\r
526             time /= freq;              // cycles-per-second becomes nanoseconds per cycle\r
527         }\r
528     }\r
529 \r
530     return  time;\r
531 }\r
532 \r
533 \r
534 /*  For reviewers:\r
535  * minimum clock divider for ALT_CPU_WATCHDOG is 1\r
536  * maximum clock divider for ALT_CPU_WATCHDOG is ((0xFFFF FFFF + 1) x (0x0000 0100) = 0x0000 0100 0000 0000)\r
537  * multiply that by the number of nanoseconds in a second (1,000,000,000)\r
538  *                              = 1,099,511,627,776,000,000,000 (0x9ACA 0000 0000 0000)\r
539  * so the countdown time with the slowest mpu_peripheral clock (2.5 MHz) =\r
540  *                              400 nS to 439,804.6511104 seconds (0x0001 9000 0000 0000 nS)\r
541  * and with the fastest mpu_peripheral clock (200 MHz) =\r
542  *                              5 nS to 5,497,558,138,880 nanoseconds ( 0x0000 0500 0000 0000 nS)\r
543  *\r
544  * minimum clock divider for peripheral watchdogs is 2**16 = (65,536 = 0x00010000)\r
545  * maximum clock divider for peripheral watchdogs is 2**31 = (2,147,483,648 = 0x8000 0000)\r
546  * multiply that by the number of nanoseconds in a second (1,000,000,000) =\r
547  *              4,096,000,000,000 (0x0000 03B9 ACA0 0000) to 2,147,483,648,000,000,000 (0x1DCD 6500 0000 0000)\r
548  * so the countdown time with the slowest l4_sp_clk (625 kHz) =\r
549  *              6,553,600 nS (0x0064 0000) to 3,435,973,836,800 nS (0x0000 0320 0000 0000 nS)\r
550  * and with the fastest l4_sp_clk (100 MHz) =\r
551  *              40,960 ns (0xA000) to 21,474,836,480 nS (0x0000 0005 0000 0000 nS)\r
552  */\r
553 \r
554 /****************************************************************************************/\r
555 /* Returns the initial value of the specified timer in milliseconds. This is the        */\r
556 /* value that will be reloaded when the timer is reset or restarted. For                */\r
557 /* ALT_CPU_WATCHDOG, this includes the effects of the prescaler setting. This call      */\r
558 /* returns a 32-bit unsigned integer, though is less precise than                       */\r
559 /* alt_wdog_counter_get_inittime_nanosecs().                                            */\r
560 /****************************************************************************************/\r
561 \r
562 uint32_t alt_wdog_counter_get_inittime_millisecs(ALT_WDOG_TIMER_t tmr_id)\r
563 {\r
564     uint32_t        time = 0;\r
565     alt_freq_t      freq;\r
566     ALT_CLK_t       clk;\r
567     uint64_t        bigtime;\r
568 \r
569     if (tmr_id == ALT_WDOG_CPU)\r
570     {\r
571         clk = ALT_CLK_MPU_PERIPH;\r
572     }\r
573     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG1) ||\r
574             (tmr_id == ALT_WDOG0_INIT) || (tmr_id == ALT_WDOG1_INIT))\r
575     {\r
576         clk = ALT_CLK_OSC1;\r
577     }\r
578     else { return time; }                             // must be an invalid tmr_id\r
579 \r
580     if ((alt_clk_freq_get(clk, &freq) == ALT_E_SUCCESS) && (freq != 0))\r
581     {                               // get clock frequency & test\r
582         time = alt_wdog_counter_get_init(tmr_id);    // get reset value\r
583         if (time != 0)\r
584         {\r
585             bigtime = ((uint64_t) time) + 1;\r
586             if (tmr_id == ALT_WDOG_CPU)         // the only watchdog with a prescaler\r
587             {\r
588                 bigtime *= (uint64_t) (alt_wdog_core_prescaler_get() + 1);\r
589             }\r
590             bigtime *= ALT_MILLISECS_IN_A_SEC;                         // scale value\r
591             bigtime /= freq;              // cycles-per-second becomes milliseconds per cycle\r
592             time = (bigtime > (uint64_t) UINT32_MAX) ? 0 : (uint32_t) bigtime;\r
593         }\r
594     }\r
595     return  time;\r
596 }\r
597 \r
598 \r
599 /*  For reviewers:\r
600  * minimum clock divider for ALT_CPU_WATCHDOG is 1\r
601  * maximum clock divider for ALT_CPU_WATCHDOG is ((0xFFFF FFFF + 1) x (0x0000 0100) = 0x0000 0100 0000 0000)\r
602  * multiply that by the number of milliseconds in a second (1,000)\r
603  *                    = 1,000 (0x3e8) to 1,099,511,627,776,000 (0x0003 E800 0000 0000)\r
604  * so the countdown time with the slowest mpu_peripheral clock (2.5 MHz) =\r
605  *                      0 mS to 439,804.6511104 seconds (0x1A36 E2EB mS)\r
606  * and with the fastest mpu_peripheral clock (200 MHz) =\r
607  *                      0 mS to 5,497.55813888 seconds ( 0x0053 E2D6 mS)\r
608  *\r
609  * minimum clock divider for peripheral watchdogs is 2**16 = (65,536 = 0x00010000)\r
610  * maximum clock divider for peripheral watchdogs is 2**31 = (2,147,483,648 = 0x8000 0000)\r
611  * multiply that by the number of milliseconds in a second (1,000) =\r
612  *              65,536,000 (0x3E8 0000) to 2,147,483,648,000 (0x01F4 0000 0000)\r
613  * so the countdown time with the slowest l4_sp_clk (625 kHz) =\r
614  *                  104 mS (0x0068) to 3,435,973 mS (0x0034 6DC5 mS)\r
615  * and with the fastest l4_sp_clk (100 MHz) = 0 mS to 21,474 mS (0x0000 53E2 mS)\r
616  */\r
617 \r
618 /****************************************************************************************/\r
619 /* Sets the value of the CPU watchdog timer ALT_CPU_WATCHDOG prescaler.                 */\r
620 /****************************************************************************************/\r
621 \r
622 ALT_STATUS_CODE alt_wdog_core_prescaler_set(uint32_t val)\r
623 {\r
624     ALT_STATUS_CODE     ret = ALT_E_BAD_ARG;            // return value\r
625     uint32_t            regdata;\r
626 \r
627     if (val <= WDOG_PS_MAX)\r
628     {\r
629         if (alt_wdog_tmr_is_enabled(ALT_WDOG_CPU))\r
630         {\r
631             ret = ALT_E_ERROR;\r
632         }\r
633         else\r
634         {\r
635             regdata = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET);\r
636             alt_write_word((CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET),\r
637                     (regdata & ~WDOG_PS_MASK) | (val << WDOG_PS_SHIFT));\r
638             ret = ALT_E_SUCCESS;\r
639         }\r
640     }\r
641     return  ret;\r
642 }\r
643 \r
644 \r
645 /****************************************************************************************/\r
646 /* Returns the value of the prescaler of the CPU core watchdog timer.                   */\r
647 /****************************************************************************************/\r
648 \r
649 uint32_t alt_wdog_core_prescaler_get(void)\r
650 {\r
651     return  (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) &\r
652                     WDOG_PS_MASK) >> WDOG_PS_SHIFT;\r
653 }\r
654 \r
655 \r
656 /****************************************************************************************/\r
657 /* Returns the maximum possible counter value of the specified timer as a 32-bit value. */\r
658 /* For the timers where this value is encoded (as powers-of-two between 15 and 31), the */\r
659 /* encoded value is converted into the equivalent binary value before returning it.     */\r
660 /* This does not include the effects of the prescaler available for ALT_CPU_WATCHDOG.   */\r
661 /****************************************************************************************/\r
662 \r
663 uint32_t alt_wdog_counter_get_max(ALT_WDOG_TIMER_t tmr_id)\r
664 {\r
665     uint32_t                ret = 0;        // return value\r
666 \r
667     if (tmr_id == ALT_WDOG_CPU)\r
668     {\r
669         ret = WDOG_TMR_MAX;\r
670     }\r
671     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG1)\r
672             || (tmr_id == ALT_WDOG0_INIT) || (tmr_id == ALT_WDOG1_INIT))\r
673     {\r
674         ret = ((uint32_t) ALT_TWO_TO_POW16) << ALT_WDOG_TIMEOUT2G;\r
675     }\r
676 \r
677     return  ret;\r
678 }\r
679 \r
680 \r
681 /****************************************************************************************/\r
682 /* Returns the maximum possible delay time of the specified timer specified in          */\r
683 /* nanoseconds. For ALT_CPU_WATCHDOG, this includes the prescaler setting. This call    */\r
684 /* returns a more precise reading of the counter than                                   */\r
685 /* alt_wdog_counter_get_max_millisecs(), though in an unsigned 64-bit integer.          */\r
686 /****************************************************************************************/\r
687 \r
688 uint64_t alt_wdog_counter_get_max_nanosecs(ALT_WDOG_TIMER_t tmr_id)\r
689 {\r
690     uint64_t    time = 0;\r
691     alt_freq_t  freq;\r
692     ALT_CLK_t   clk;\r
693 \r
694     if (tmr_id == ALT_WDOG_CPU)\r
695     {\r
696         clk = ALT_CLK_MPU_PERIPH;\r
697     }\r
698     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG1) ||\r
699             (tmr_id == ALT_WDOG0_INIT) || (tmr_id == ALT_WDOG1_INIT))\r
700     {\r
701         clk = ALT_CLK_OSC1;\r
702     }\r
703     else { return time; }\r
704 \r
705     if ((alt_clk_freq_get(clk, &freq) == ALT_E_SUCCESS) && (freq != 0))\r
706     {                    // get clock frequency & test\r
707         time = (uint64_t) alt_wdog_counter_get_max(tmr_id);     // get maximum reset value\r
708         if (time != 0)\r
709         {\r
710             time += 1;\r
711             if (tmr_id == ALT_WDOG_CPU)\r
712             {\r
713                 time *= (WDOG_PS_MAX + 1);          // maximum prescaler\r
714             }\r
715             time *= ALT_NANOSECS_IN_A_SEC;\r
716             time /= freq;               //cycles-per-second becomes nanoseconds-per-cycle\r
717         }\r
718     }\r
719     return  time;\r
720 }\r
721 \r
722 \r
723 \r
724 /****************************************************************************************/\r
725 /* Returns the maximum possible delay time of the specified timer specified in          */\r
726 /* milliseconds. For ALT_CPU_WATCHDOG, this includes the prescaler setting. This call   */\r
727 /* returns a 32-bit unsigned integer, though is less precise than                       */\r
728 /* alt_wdog_counter_get_max_nanosecs().                                                 */\r
729 /****************************************************************************************/\r
730 \r
731 uint32_t alt_wdog_counter_get_max_millisecs(ALT_WDOG_TIMER_t tmr_id)\r
732 {\r
733     uint32_t        time = 0;\r
734     alt_freq_t      freq;\r
735     ALT_CLK_t       clk;\r
736     uint64_t        bigtime;\r
737 \r
738     if (tmr_id == ALT_WDOG_CPU)\r
739     {\r
740         clk = ALT_CLK_MPU_PERIPH;\r
741     }\r
742     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG1) ||\r
743             (tmr_id == ALT_WDOG0_INIT) || (tmr_id == ALT_WDOG1_INIT))\r
744     {\r
745         clk = ALT_CLK_OSC1;\r
746     }\r
747     else { return time; }\r
748 \r
749     if ((alt_clk_freq_get(clk, &freq) == ALT_E_SUCCESS) && (freq != 0))\r
750     {                   // get clock frequency & test\r
751         time = alt_wdog_counter_get_max(tmr_id);     // get reset value\r
752         if (time != 0)\r
753         {\r
754             bigtime = ((uint64_t) time) + 1;\r
755             if (tmr_id == ALT_WDOG_CPU)\r
756             {\r
757                 bigtime *= (WDOG_PS_MAX + 1);           // maximum prescaler\r
758             }\r
759             bigtime *= ALT_MILLISECS_IN_A_SEC;\r
760             bigtime /= freq;              //cycles-per-second becomes milliseconds-per-cycle\r
761             time = (bigtime > (uint64_t) UINT32_MAX) ? 0 : (uint32_t) bigtime;\r
762         }\r
763     }\r
764     return  time;\r
765 }\r
766 \r
767 \r
768 /****************************************************************************************/\r
769 /* Disables the interrupt of the specified watchdog timer module. If the watchdog timer */\r
770 /* is one of the watchdog timers that can be used in general-purpose mode, and if the   */\r
771 /* timer is in general-purpose timer mode, disable the interrupt.                       */\r
772 /****************************************************************************************/\r
773 \r
774 ALT_STATUS_CODE alt_wdog_int_disable(ALT_WDOG_TIMER_t tmr_id)\r
775 {\r
776     ALT_STATUS_CODE         ret = ALT_E_BAD_ARG;            // return value\r
777 \r
778     if (tmr_id == ALT_WDOG_CPU)\r
779     {\r
780         if (cpu_wdog_in_wdt_mode())\r
781         {\r
782             ret = ALT_E_ERROR;\r
783         }\r
784         else\r
785         {\r
786             alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET,\r
787                   (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) & ~WDOG_INT_EN));\r
788             ret = ALT_E_SUCCESS;\r
789         }\r
790     }\r
791             // returns an error for the other four watchdog timers\r
792             // since their interrupts cannot be disabled\r
793             // (this could change in v13.1)\r
794     return  ret;\r
795 }\r
796 \r
797 \r
798 /****************************************************************************************/\r
799 /* Sets/enables the interrupt of the specified watchdog timer module. If the watchdog   */\r
800 /* timer is one of the watchdog timers that can be used in general-purpose mode, and    */\r
801 /* if the timer is in general-purpose timer mode, enable the interrupt.                 */\r
802 /****************************************************************************************/\r
803 \r
804 ALT_STATUS_CODE alt_wdog_int_enable(ALT_WDOG_TIMER_t tmr_id)\r
805 {\r
806     ALT_STATUS_CODE         ret = ALT_E_BAD_ARG;            // return value\r
807 \r
808     if (tmr_id == ALT_WDOG_CPU)\r
809     {\r
810         if (cpu_wdog_in_wdt_mode())\r
811         {\r
812             ret = ALT_E_ERROR;\r
813         }\r
814         else\r
815         {\r
816             alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET,\r
817                   (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) | WDOG_INT_EN));\r
818             ret = ALT_E_SUCCESS;\r
819         }\r
820     }\r
821     return  ret;\r
822                 // other watchdog timers always have interrupt enabled if they are running\r
823 }\r
824 \r
825 \r
826 /****************************************************************************************/\r
827 /* Returns the status of the interrupt of the specified watchdog timer module but does  */\r
828 /* not clear it. Return TRUE if the interrupt of the specified general purpose timer    */\r
829 /* module is pending and FALSE otherwise.                                               */\r
830 /****************************************************************************************/\r
831 \r
832 bool alt_wdog_int_is_pending(ALT_WDOG_TIMER_t tmr_id)\r
833 {\r
834     bool        ret = false;            //return value\r
835 \r
836     if ((tmr_id == ALT_WDOG_CPU) && cpu_wdog_in_gpt_mode())\r
837     {\r
838         ret = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_INTSTAT_REG_OFFSET) & WDOG_INT_STAT_BIT;\r
839     }\r
840     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
841     {\r
842         ret = alt_read_word(ALT_L4WD0_WDT_STAT_ADDR) & ALT_L4WD_STAT_WDT_STAT_SET_MSK;\r
843     }\r
844     else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
845     {\r
846         ret = alt_read_word(ALT_L4WD1_WDT_STAT_ADDR) & ALT_L4WD_STAT_WDT_STAT_SET_MSK;\r
847     }\r
848     return ret;\r
849 }\r
850 \r
851 \r
852 /****************************************************************************************/\r
853 /* Returns the state of the interrupt of the specified watchdog timer module. If the    */\r
854 /* watchdog timer is one of the watchdog timers that can be used in general-purpose     */\r
855 /* mode, and if the timer is in general-purpose timer mode, returns TRUE if the         */\r
856 /* interrupt of the specified general purpose timer module is enabled and FALSE if      */\r
857 /* disabled. If the timer is not in general-purpose timer mode, returns TRUE, as        */\r
858 /* watchdog interrupts are always enabled.                                              */\r
859 /****************************************************************************************/\r
860 \r
861 bool alt_wdog_int_is_enabled(ALT_WDOG_TIMER_t tmr_id)\r
862 {\r
863     bool        ret = false;            //return value\r
864 \r
865     if (tmr_id == ALT_WDOG_CPU)\r
866     {\r
867         ret = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET) &\r
868                     (WDOG_INT_EN | WDOG_WDT_MODE);\r
869             // if in watchdog mode OR if in general purpose timer mode\r
870             // AND the interrupt is enabled\r
871     }\r
872     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
873     {\r
874         ret = alt_read_word(ALT_L4WD0_WDT_CR_ADDR) & ALT_L4WD_CR_WDT_EN_SET_MSK;\r
875         // if these timers are running, their interrupt is enabled\r
876     }\r
877     else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
878     {\r
879         ret = alt_read_word(ALT_L4WD1_WDT_CR_ADDR) & ALT_L4WD_CR_WDT_EN_SET_MSK;\r
880             // if these timers are running, their interrupt is enabled\r
881     }\r
882     return ret;\r
883 }\r
884 \r
885 \r
886 /****************************************************************************************/\r
887 /* Clears the pending status of the interrupt of the specified watchdog timer module.   */\r
888 /****************************************************************************************/\r
889 \r
890 ALT_STATUS_CODE alt_wdog_int_clear(ALT_WDOG_TIMER_t tmr_id)\r
891 {\r
892 \r
893 \r
894     if (tmr_id == ALT_WDOG_CPU)\r
895     {\r
896         alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_INTSTAT_REG_OFFSET, WDOG_INT_STAT_BIT);\r
897              // clear int by writing to status bit\r
898     }\r
899     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
900     {\r
901         (void) alt_read_word(ALT_L4WD0_WDT_EOI_ADDR);\r
902             // clear int by reading from end-of-interrupt register\r
903             // adding the void cast tells armcc not to throw a error for this usage\r
904     }\r
905     else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
906     {\r
907         (void) alt_read_word(ALT_L4WD1_WDT_EOI_ADDR);\r
908             // clear int by reading from end-of-interrupt register\r
909     }\r
910     else {return  ALT_E_ERROR; }\r
911     return ALT_E_SUCCESS;\r
912 }\r
913 \r
914 \r
915 /****************************************************************************************/\r
916 /* Returns the status of the interrupt of the specified watchdog timer module and also  */\r
917 /* clears it. Return TRUE if the interrupt of the specified general purpose timer       */\r
918 /* module is pending and FALSE otherwise.                                               */\r
919 /****************************************************************************************/\r
920 \r
921 bool alt_wdog_int_if_pending_clear(ALT_WDOG_TIMER_t tmr_id)\r
922 {\r
923     uint32_t                ret = false;    //    value to return\r
924 \r
925 \r
926     if (tmr_id == ALT_WDOG_CPU)\r
927     {\r
928         ret = (alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_INTSTAT_REG_OFFSET) & WDOG_INT_STAT_BIT);\r
929         if (ret)\r
930         {\r
931             alt_write_word(CPU_WDTGPT_TMR_BASE + WDOG_INTSTAT_REG_OFFSET, WDOG_INT_STAT_BIT);\r
932             // clear int by writing to status bit\r
933         }\r
934     }\r
935     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
936     {\r
937         ret = alt_read_word(ALT_L4WD0_WDT_STAT_ADDR) & ALT_L4WD_STAT_WDT_STAT_SET_MSK;\r
938         if (ret)\r
939         {\r
940             (void) alt_read_word(ALT_L4WD0_WDT_EOI_ADDR);\r
941                 // clear int by reading from end-of-interrupt register\r
942                 // adding the void cast tells armcc not to throw a error for this usage\r
943 \r
944        }\r
945     }\r
946     else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
947     {\r
948         ret = alt_read_word(ALT_L4WD1_WDT_STAT_ADDR) & ALT_L4WD_STAT_WDT_STAT_SET_MSK;\r
949 \r
950         if (ret)\r
951         {\r
952             (void) alt_read_word(ALT_L4WD1_WDT_EOI_ADDR);\r
953                     // clear int by reading from end-of-interrupt register\r
954         }\r
955     }\r
956 \r
957     return  ret;\r
958 }\r
959 \r
960 \r
961 /****************************************************************************************/\r
962 /* Sets the timeout response mode of the specified watchdog timer. For ALT_WATCHDOG0,   */\r
963 /* ALT_WATCHDOG1, \b ALT_WATCHDOG0_INITIAL or \b ALT_WATCHDOG1_INITIAL, the options     */\r
964 /* are to generate a system reset or to generate an interrupt and then generate a       */\r
965 /* system reset if the interrupt is not cleared by the next time the watchdog timer     */\r
966 /* counter rolls over. For ALT_CPU_WATCHDOG, the options are to trigger an interrupt    */\r
967 /* request (with the result set in the interrupt manager) or a reset request (with the  */\r
968 /* result set in the reset manager) plus two more options available when it is used     */\r
969 /* as a general-purpose timer.                                                          */\r
970 /****************************************************************************************/\r
971 \r
972 ALT_STATUS_CODE alt_wdog_response_mode_set(ALT_WDOG_TIMER_t tmr_id, ALT_WDOG_RESET_TYPE_t type)\r
973 {\r
974     ALT_STATUS_CODE         ret = ALT_E_BAD_ARG;        // return value\r
975     uint32_t                regdata;                    // register data\r
976 \r
977 \r
978     if (tmr_id == ALT_WDOG_CPU)\r
979     {\r
980         regdata = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET);\r
981         if (type == ALT_WDOG_TIMER_MODE_ONESHOT)\r
982         {\r
983             alt_write_word((CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET), regdata & ~WDOG_AUTO_RELOAD);\r
984             ret = ALT_E_SUCCESS;\r
985         }\r
986         else if (type == ALT_WDOG_TIMER_MODE_FREERUN)\r
987         {\r
988             alt_write_word((CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET), regdata | WDOG_AUTO_RELOAD);\r
989             ret = ALT_E_SUCCESS;\r
990         }\r
991     }\r
992     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
993     {\r
994         regdata = alt_read_word(ALT_L4WD0_WDT_CR_ADDR);\r
995         if (type == ALT_WDOG_WARM_RESET)\r
996         {\r
997             alt_write_word(ALT_L4WD0_WDT_CR_ADDR, regdata & ALT_L4WD_CR_RMOD_CLR_MSK);\r
998             ret = ALT_E_SUCCESS;\r
999         }\r
1000         else if (type == ALT_WDOG_INT_THEN_RESET)\r
1001         {\r
1002             alt_write_word(ALT_L4WD0_WDT_CR_ADDR, regdata | ALT_L4WD_CR_RMOD_SET_MSK);\r
1003             ret = ALT_E_SUCCESS;\r
1004         }\r
1005     }\r
1006     else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
1007     {\r
1008         regdata = alt_read_word(ALT_L4WD1_WDT_CR_ADDR);\r
1009         if (type == ALT_WDOG_WARM_RESET)\r
1010         {\r
1011             alt_write_word(ALT_L4WD1_WDT_CR_ADDR, regdata & ALT_L4WD_CR_RMOD_CLR_MSK);\r
1012             ret = ALT_E_SUCCESS;\r
1013         }\r
1014         else if (type == ALT_WDOG_INT_THEN_RESET)\r
1015         {\r
1016             alt_write_word(ALT_L4WD1_WDT_CR_ADDR, regdata | ALT_L4WD_CR_RMOD_SET_MSK);\r
1017             ret = ALT_E_SUCCESS;\r
1018         }\r
1019     }\r
1020     return  ret;            // rejects a bad tmr_id argument/type argument combination\r
1021 }\r
1022 \r
1023 \r
1024 /****************************************************************************************/\r
1025 /* Returns the response mode of the specified timer.                                    */\r
1026 /****************************************************************************************/\r
1027 \r
1028 int32_t alt_wdog_response_mode_get(ALT_WDOG_TIMER_t tmr_id)\r
1029 {\r
1030     int32_t             ret = ALT_E_BAD_ARG;     // return value\r
1031     uint32_t            regdata;                 // read value\r
1032 \r
1033 \r
1034     if (tmr_id == ALT_WDOG_CPU)\r
1035     {\r
1036         regdata = alt_read_word(CPU_WDTGPT_TMR_BASE + WDOG_CTRL_REG_OFFSET);\r
1037         ret = (regdata & WDOG_AUTO_RELOAD) ? ALT_WDOG_TIMER_MODE_FREERUN : ALT_WDOG_TIMER_MODE_ONESHOT;\r
1038     }\r
1039     else if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
1040     {\r
1041         regdata = alt_read_word(ALT_L4WD0_WDT_CR_ADDR);\r
1042         ret = (regdata & ALT_L4WD_CR_RMOD_SET_MSK) ? ALT_WDOG_INT_THEN_RESET : ALT_WDOG_WARM_RESET;\r
1043     }\r
1044     else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
1045     {\r
1046         regdata = alt_read_word(ALT_L4WD1_WDT_CR_ADDR);\r
1047         ret = (regdata & ALT_L4WD_CR_RMOD_SET_MSK) ? ALT_WDOG_INT_THEN_RESET : ALT_WDOG_WARM_RESET;\r
1048     }\r
1049 \r
1050     return  ret;\r
1051 }\r
1052 \r
1053 \r
1054 \r
1055 /****************************************************************************************/\r
1056 /* Returns the component code of the watchdog timer module. Only valid for              */\r
1057 /* ALT_WATCHDOG0, ALT_WATCHDOG1, ALT_WATCHDOG0_INITIAL or ALT_WATCHDOG1_INITIAL.        */\r
1058 /****************************************************************************************/\r
1059 \r
1060 uint32_t alt_wdog_compcode_get(ALT_WDOG_TIMER_t tmr_id)\r
1061 {\r
1062     uint32_t    component = 0;                  // component code of the module\r
1063 \r
1064     if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
1065     {\r
1066         component = alt_read_word(ALT_L4WD0_WDT_COMP_TYPE_ADDR);\r
1067     }\r
1068     else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
1069     {\r
1070         component = alt_read_word(ALT_L4WD1_WDT_COMP_TYPE_ADDR);\r
1071 \r
1072     }\r
1073     return  component;\r
1074 }\r
1075 \r
1076 \r
1077 /****************************************************************************************/\r
1078 /* Returns the version code of the watchdog timer module. Only valid for ALT_WATCHDOG0, */\r
1079 /* ALT_WATCHDOG1, ALT_WATCHDOG0_INITIAL or ALT_WATCHDOG1_INITIAL.                       */\r
1080 /****************************************************************************************/\r
1081 \r
1082 uint32_t alt_wdog_ver_get(ALT_WDOG_TIMER_t tmr_id)\r
1083 {\r
1084     uint32_t    ver = 0;                  // revision code of the module\r
1085 \r
1086     if ((tmr_id == ALT_WDOG0) || (tmr_id == ALT_WDOG0_INIT))\r
1087     {\r
1088         ver = alt_read_word(ALT_L4WD0_WDT_COMP_VER_ADDR);\r
1089     }\r
1090     else if ((tmr_id == ALT_WDOG1) || (tmr_id == ALT_WDOG1_INIT))\r
1091     {\r
1092         ver = alt_read_word(ALT_L4WD1_WDT_COMP_VER_ADDR);\r
1093 \r
1094     }\r
1095     return  ver;\r
1096 }\r
1097 \r
1098 \r
1099 /****************************************************************************************/\r
1100 \r
1101 \r