[PATCH 36] LEON3: GPTIMER timer watchdog driver

Joel Sherrill joel.sherrill at OARcorp.com
Wed Apr 18 15:53:10 UTC 2012



+ Looks like tabs on indentation in the new C file

+ 2011 date

+ You are proposing new bsp_watchdog methods. I am
not opposed to them but they shouldn't go in your bsp.h.
It would be better to add this as a possible API for all BSPs.
This would have to be reconciled with the following existing
code in the tree:

./cpukit/libcsupport/include/rtems/watchdogdrv.h
./c/src/lib/libcpu/powerpc/mpc55xx/include/watchdog.h
./c/src/lib/libbsp/powerpc/mpc55xxevb/startup/start-watchdog.c

And I did some work on a prototype which never got the
attention it deserved. Chris and I discussed this as a libchip
framework where you could have multiple reset watchdogs
for different pieces of hardware.

I prototyped a simple one based upon a test fixture reset
driver and a some code for the Intel ich4 chipset watchdog.
Longer term, we envisioned a library of watchdog management
code which helped the application. Say reset from timer or
a special task.

I would like to take this as an opportunity to discuss this
all again and get on the right path long term. Your
"bsp_watchdog_xxx" could be the names for the
main board reset and the framework could be
layered on top of it.

You seem to be the lucky guy who asks the questions which
need to be answered. :)

On 04/18/2012 10:19 AM, Daniel Hellstrom wrote:
> Last timer instance of GPTIMER is sometimes a watchdog timer that
> can reset the system on timer underflow.
>
> Signed-off-by: Daniel Hellstrom<daniel at gaisler.com>
> ---
>   c/src/lib/libbsp/sparc/leon3/Makefile.am      |    1 +
>   c/src/lib/libbsp/sparc/leon3/include/bsp.h    |   25 +++++++
>   c/src/lib/libbsp/sparc/leon3/timer/watchdog.c |   89 +++++++++++++++++++++++++
>   3 files changed, 115 insertions(+), 0 deletions(-)
>   create mode 100644 c/src/lib/libbsp/sparc/leon3/timer/watchdog.c
>
> diff --git a/c/src/lib/libbsp/sparc/leon3/Makefile.am b/c/src/lib/libbsp/sparc/leon3/Makefile.am
> index cc25993..9b8af4b 100644
> --- a/c/src/lib/libbsp/sparc/leon3/Makefile.am
> +++ b/c/src/lib/libbsp/sparc/leon3/Makefile.am
> @@ -115,6 +115,7 @@ libbsp_a_SOURCES += ../../sparc/shared/i2c/i2cmst.c
>
>   # timer
>   libbsp_a_SOURCES += timer/timer.c
> +libbsp_a_SOURCES += timer/watchdog.c
>
>   if HAS_SMP
>   libbsp_a_SOURCES += smp/getcpuid.c
> diff --git a/c/src/lib/libbsp/sparc/leon3/include/bsp.h b/c/src/lib/libbsp/sparc/leon3/include/bsp.h
> index d883064..32407dd 100644
> --- a/c/src/lib/libbsp/sparc/leon3/include/bsp.h
> +++ b/c/src/lib/libbsp/sparc/leon3/include/bsp.h
> @@ -192,6 +192,31 @@ extern void BSP_shared_interrupt_unmask(int irq);
>    */
>   extern void BSP_shared_interrupt_mask(int irq);
>
> +/* Initialize BSP watchdog routines. Returns number of watchdog timers found.
> + * Currently only one is supported.
> + */
> +extern int bsp_watchdog_init(void);
> +
> +/* Reload watchdog (last timer on the first GPTIMER core), all systems does not
> + * feature a watchdog, it is expected that if this function is called the
> + * user knows that there is a watchdog available.
> + *
> + * The prescaler is normally set to number of MHz of system, this is to
> + * make the system clock tick be stable.
> + *
> + * Arguments
> + *  watchdog       - Always 0 for now
> + *  reload_value   - Number of timer clocks (after prescaler) to count before
> + *                   watchdog is woken.
> + */
> +extern void bsp_watchdog_reload(int watchdog, unsigned int reload_value);
> +
> +/* Stop watchdog timer */
> +extern void bsp_watchdog_stop(int watchdog);
> +
> +/* Use watchdog0 timer to reset the system */
> +extern void bsp_watchdog_system_reset(void);
> +
>   #ifdef __cplusplus
>   }
>   #endif
> diff --git a/c/src/lib/libbsp/sparc/leon3/timer/watchdog.c b/c/src/lib/libbsp/sparc/leon3/timer/watchdog.c
> new file mode 100644
> index 0000000..d3a9c15
> --- /dev/null
> +++ b/c/src/lib/libbsp/sparc/leon3/timer/watchdog.c
> @@ -0,0 +1,89 @@
> +/*  GPTIMER Watchdog timer routines. On some systems the first GPTIMER
> + *  core's last Timer instance underflow signal is connected to system
> + *  reset.
> + *
> + *  COPYRIGHT (c) 2011
> + *  Aeroflex Gaisler
> + *
> + *  The license and distribution terms for this file may be
> + *  found in the file LICENSE in this distribution or at
> + *  http://www.rtems.com/license/LICENSE.
> + */
> +
> +#include<bsp.h>
> +#include<grlib.h>
> +
> +extern volatile struct gptimer_regs *LEON3_Timer_Regs;
> +
> +struct gptimer_watchdog_priv {
> +	struct gptimer_regs *regs;
> +	struct gptimer_timer_regs *timer;
> +	int timerno;
> +};
> +
> +struct gptimer_watchdog_priv bsp_watchdogs[1];
> +int bsp_watchdog_count = 0;
> +
> +int bsp_watchdog_init(void)
> +{
> +	int timercnt;
> +
> +	if (!LEON3_Timer_Regs)
> +		return 0;
> +
> +	/* Get Watchdogs in system, this is implemented for one GPTIMER core
> +	 * only.
> +	 *
> +	 * First watchdog is a special case, we can get the first timer core by
> +	 * looking at LEON3_Timer_Regs, the watchdog within a timer core is
> +	 * always the last timer. Unfortunately we can not know it the watchdog
> +	 * functionality is available or not, we assume that it is if we
> +	 * reached this function.
> +	 */
> +	bsp_watchdogs[0].regs = (struct gptimer_regs *)LEON3_Timer_Regs;
> +
> +	/* Find Timer that has watchdog functionality */
> +	timercnt = bsp_watchdogs[0].regs->cfg&  0x7;
> +	if (timercnt<  2) /* First timer system clock timer */
> +		return 0;
> +
> +	bsp_watchdogs[0].timerno = timercnt - 1;
> +	bsp_watchdogs[0].timer =&bsp_watchdogs[0].regs->timer[bsp_watchdogs[0].timerno];
> +
> +	bsp_watchdog_count = 1;
> +	return bsp_watchdog_count;
> +}
> +
> +void bsp_watchdog_reload(int watchdog, unsigned int reload_value)
> +{
> +	if (bsp_watchdog_count == 0)
> +		bsp_watchdog_init();
> +
> +	if (bsp_watchdog_count<= watchdog)
> +		return;
> +
> +	/* Kick watchdog, and clear interrupt pending bit */
> +	bsp_watchdogs[watchdog].timer->reload = reload_value;
> +	bsp_watchdogs[watchdog].timer->ctrl =
> +		(LEON3_GPTIMER_LD | LEON3_GPTIMER_EN) |
> +		(bsp_watchdogs[watchdog].timer->ctrl&  ~(1<<4));
> +}
> +
> +void bsp_watchdog_stop(int watchdog)
> +{
> +	if (bsp_watchdog_count == 0)
> +		bsp_watchdog_init();
> +
> +	if (bsp_watchdog_count<= watchdog)
> +		return;
> +
> +	/* Stop watchdog timer */
> +	bsp_watchdogs[watchdog].timer->ctrl = 0;
> +}
> +
> +/* Use watchdog timer to reset system */
> +void bsp_watchdog_system_reset(void)
> +{
> +	sparc_disable_interrupts();
> +	bsp_watchdog_reload(0, 1);
> +}


-- 
Joel Sherrill, Ph.D.             Director of Research&   Development
joel.sherrill at OARcorp.com        On-Line Applications Research
Ask me about RTEMS: a free RTOS  Huntsville AL 35805
     Support Available             (256) 722-9985





More information about the devel mailing list