1.10.2014

Konfiguracja Watchdog EK-TM4C123GXL


Mikro-kontroler TM4C123GH6PM posiada dwa moduły watchdog, WDT0 i WDT1. Różnica miedzy modułami polega na korzystaniu z różnych zegarów, Watchdog Timer 0 korzysta z systemowego zegara a Watchdog Timer 1 z PIOS. Timer WDT1 posiada dodatkowy bit zdefiniowany w rejestrze Watchdog Timer Control (WDTCTL) który po zapisie jest zerowany, kolejna operacja na rejestrze może być wykonana po pojawieniu się jedynki w tym bicie. Dodatkowo z modułem  WDT1 związanych jest kilka błędów w samym krzemie i aby go uruchomić należy zastosować się do erraty wydanej przez producenta. Testowałem WDT1 i bez zapoznania się z erratą nie udało się zainicjować jego działania w standardowy sposób. Po dokonaniu zalecanych przez producenta operacji zadziałał.

Watchdog posiada:

  • 32-bitowy licznik z programowalna wartością startową
  • możliwość generowania przerwania, opcjonalnie nie maskowanego NMI
  • możliwość generowania resetu
  • możliwość zablokowania zmian w konfiguracji w trybie działania programu
  • możliwość ustawienia stopu timera podczas kroków debugowania




Aby uruchomić sprzętowy WDT należy w rejestrze Watchdog Timer Run Mode Clock Gating Control (RCGCWD) ustawić bit R0 lub R1. Funkcja SysCtlPeripheralEnable(moduł).

Jeżeli WDT ma zliczać od wartości innej niż pełne słowo 32bit należy wypełnić rejestr WDTLOAD wartością startową. Funkcja WatchdogReloadSet(wartość).

Jeżeli ma być generowany reset, należy ustawić bit RESEN  w rejestrze WDTCTL. Funkcja WatchdogResetEnable().

Można ustawić rodzaj przerwania, bit INTTYPE w rejestrze WDTCTL. 0=normal,1=NMI. Funkcja WatchdogIntTypeSet().

Należy włączyć WDT ustawiając bit INTEN w rejestrze WDTCTL. Przerwanie będzie włączone i WDT zacznie zliczanie. Bit INTEN można programowo ustawić tylko raz, potem zmiany będą ignorowane. Aby wyłączyć WDT należy wykonać reset sprzętowy lub zresetować programowo przez Watchdog Timer Software Reset (SRWD).

Można dodatkowo zablokować możliwość zmian w rejestrach należy wpisać 0x1ACC.E551 do rejestru  Watchdog Lock (WDTLOCK). Odczyt z rejestru zwraca 0 dla nie zablokowanego i 1 dla zablokowanego. Funkcja WatchdogLock().


Prosty kod z wykorzystaniem WDT0 bez generowania resetu, z włączoną obsługą przerwania. Funkcja WatchdogIntRegister() przypisuje wektor do przekazanej funkcji i automatycznie odblokowuje przerwanie globalne.


 

#include "utils/ustdlib.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/debug.h"
#include "driverlib/hibernate.h"
#include "driverlib/gpio.h"
#include "driverlib/systick.h"
#include "driverlib/timer.h"
#include "driverlib/watchdog.h"

void WDT_interrupt(void); // WDT handler

int main(void)
{
 SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_INT);  // 40 MHz int

 //green LED on
 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
 GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
 GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0x08);

 SysCtlPeripheralEnable(SYSCTL_PERIPH_WDOG0);

 WatchdogReloadSet(WATCHDOG0_BASE,0xFEEFEE);

 WatchdogStallEnable(WATCHDOG0_BASE); // debbuger

 WatchdogEnable(WATCHDOG0_BASE);

 WatchdogIntRegister(WATCHDOG0_BASE, WDT_interrupt ); // interrupt handler

 while(1)
 {
 }
}


void WDT_interrupt(){

 WatchdogIntClear(WATCHDOG0_BASE); // clear int
 static unsigned long fl; // flag blink led
 fl^=1; // toggle flag

 if(fl){
  GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0x08);
 }
 else{
  GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0x00);
 }
}