--- watchdog_at91.cxx 2004-07-29 22:41:52.000000000 +0200 +++ /opt/ecos/ecos/packages/devs/watchdog/arm/at91/current/src/watchdog_at91.cxx 2004-07-27 23:27:23.000000000 +0200 @@ -42,8 +42,8 @@ //#####DESCRIPTIONBEGIN#### // // Author(s): tkoeller -// Contributors: tkoeller, nickg -// Date: 2002-05-05 +// Contributors: tkoeller, nickg, darnaud +// Date: 2004-07-23 // Purpose: Watchdog class implementation // Description: Contains an implementation of the Watchdog class for use // with the ATMEL AT91 watchdog timer. @@ -73,13 +73,14 @@ //========================================================================== -#define MCLK_FREQUENCY_KHZ (CYGNUM_HAL_ARM_AT91_CLOCK_SPEED/1000) -#define MAX_TICKS 0x0000ffff -#define BASE_TICKS (MCLK_FREQUENCY_KHZ * CYGNUM_DEVS_WATCHDOG_ARM_AT91_DESIRED_TIMEOUT_MS) #if defined(CYGHWR_HAL_ARM_AT91_R40008) || \ defined(CYGHWR_HAL_ARM_AT91_R40807) +#define MCLK_FREQUENCY_KHZ (CYGNUM_HAL_ARM_AT91_CLOCK_SPEED/1000) +#define MAX_TICKS 0x0000ffff +#define BASE_TICKS (MCLK_FREQUENCY_KHZ * CYGNUM_DEVS_WATCHDOG_ARM_AT91_DESIRED_TIMEOUT_MS) + #if BASE_TICKS / 8 <= MAX_TICKS #define DIVIDER 0 #define DIV_FACTOR 8 @@ -96,82 +97,78 @@ #error Desired resolution beyond hardware capabilities #endif -#elif defined(CYGHWR_HAL_ARM_AT91_M55800A) +#define TICKS ((BASE_TICKS / DIV_FACTOR) | 0xfff) +#define RESOLUTION ((cyg_uint64) (TICKS * DIV_FACTOR ) * 1000000 / MCLK_FREQUENCY_KHZ) -#if BASE_TICKS / 32 <= MAX_TICKS -#define DIVIDER 0 -#define DIV_FACTOR 32 -#elif BASE_TICKS / 128 <= MAX_TICKS -#define DIVIDER 1 -#define DIV_FACTOR 128 -#elif BASE_TICKS / 1024 <= MAX_TICKS -#define DIVIDER 2 -#define DIV_FACTOR 1024 -#elif BASE_TICKS / 4096 <= MAX_TICKS -#define DIVIDER 3 -#define DIV_FACTOR 4096 -#else -#error Desired resolution beyond hardware capabilities -#endif +#elif defined(CYGHWR_HAL_ARM_AT91_M42800A) +#define SCLK_FREQUENCY_HZ 32800 // Slow clock in hertz +#define MAX_TICKS 0x0000ffff +#define BASE_TICKS (SCLK_FREQUENCY_HZ * CYGNUM_DEVS_WATCHDOG_ARM_AT91_DESIRED_TIMEOUT_MS/1000) +#if BASE_TICKS/128 > MAX_TICKS +#error Desired resolution beyond hardware capabilities #endif -#define TICKS ((BASE_TICKS / DIV_FACTOR) | 0xfff) -#define RESOLUTION ((cyg_uint64) (TICKS * DIV_FACTOR ) * 1000000 / MCLK_FREQUENCY_KHZ) +#define TICKS ((BASE_TICKS / 128) & 0xffff) +#define RESOLUTION ((cyg_uint64) (TICKS * 128) * 1000000000 / SCLK_FREQUENCY_HZ) +#endif //========================================================================== - +// Reset on watchdog expiration #if defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT) #define OMRVAL (AT91_WD_OMR_OKEY | AT91_WD_OMR_RSTEN | AT91_WD_OMR_WDEN) - -void -Cyg_Watchdog::init_hw(void) -{ - CYG_REPORT_FUNCTION(); - CYG_REPORT_FUNCARGVOID(); - resolution = RESOLUTION; - CYG_REPORT_RETURN(); -} +#define WDMRFLG (AT91_ST_WDMR_RSTEN | AT91_ST_WDMR_EXTEN) +#define IERFLG 0 #else /* defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT) */ //========================================================================== +// Action on watchdog expiration #define OMRVAL (AT91_WD_OMR_OKEY | AT91_WD_OMR_IRQEN | AT91_WD_OMR_WDEN) +#define WDMRFLG 0 +#define IERFLG (AT91_ST_WDOVF) #define INT_PRIO 7 //========================================================================== +// Private definitions +static cyg_ISR watchdog_isr; static Cyg_Watchdog *wd; + //========================================================================== -static cyg_uint32 -isr(cyg_vector vector, CYG_ADDRWORD data) +static Cyg_Interrupt wdint +( + CYGNUM_HAL_INTERRUPT_WATCHDOG, + INT_PRIO, + 0, + watchdog_isr, + NULL + ); + +//========================================================================== + +cyg_uint32 watchdog_isr(cyg_vector vector, CYG_ADDRWORD data) { CYG_REPORT_FUNCTION(); CYG_REPORT_FUNCARG2XV(vector, data); wd->trigger(); - Cyg_Interrupt::acknowledge_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG); + wdint.acknowledge_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG); CYG_REPORT_RETVAL(Cyg_Interrupt::HANDLED); return Cyg_Interrupt::HANDLED; } -//========================================================================== - -static Cyg_Interrupt wdint( - CYGNUM_HAL_INTERRUPT_WATCHDOG, - INT_PRIO, - 0, - isr, - NULL - ); +#endif /* defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT) */ //========================================================================== - +/* + * Init hardware watchdog timer. + */ void Cyg_Watchdog::init_hw(void) { @@ -180,15 +177,9 @@ wd = this; resolution = RESOLUTION; - wdint.configure_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG, false, true); - wdint.attach(); - wdint.acknowledge_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG); - wdint.unmask_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG); + CYG_REPORT_RETURN(); } - -#endif /* defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT) */ - //========================================================================== /* * Reset watchdog timer. This needs to be called regularly to prevent @@ -200,9 +191,14 @@ { CYG_REPORT_FUNCTION(); CYG_REPORT_FUNCARGVOID(); +#if defined(CYGHWR_HAL_ARM_AT91_M42800A) + /* Re-arm watchdog timer */ + HAL_WRITE_UINT32(AT91_ST + AT91_ST_CR, AT91_ST_CR_WDRST); +#else /* Write magic code to reset the watchdog. */ HAL_WRITE_UINT32(AT91_WD + AT91_WD_CR, AT91_WD_CR_RSTKEY); +#endif CYG_REPORT_RETURN(); } @@ -218,6 +214,18 @@ CYG_REPORT_FUNCTION(); CYG_REPORT_FUNCARGVOID(); +#if !defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT) + wdint.configure_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG, false, true); + wdint.attach(); + wdint.acknowledge_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG); + wdint.unmask_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG); +#endif + +#if defined(CYGHWR_HAL_ARM_AT91_M42800A) + HAL_WRITE_UINT32(AT91_ST + AT91_ST_WDMR, TICKS | WDMRFLG ); + HAL_WRITE_UINT32(AT91_ST + AT91_ST_IER, IERFLG ); + HAL_WRITE_UINT32(AT91_ST + AT91_ST_CR, AT91_ST_CR_WDRST ); +#else HAL_WRITE_UINT32(AT91_WD + AT91_WD_OMR, AT91_WD_OMR_OKEY); HAL_WRITE_UINT32( AT91_WD + AT91_WD_CMR, @@ -225,6 +233,7 @@ ); HAL_WRITE_UINT32(AT91_WD + AT91_WD_CR, AT91_WD_CR_RSTKEY); HAL_WRITE_UINT32(AT91_WD + AT91_WD_OMR, OMRVAL); +#endif CYG_REPORT_RETURN(); }