Mit dieser Library kann der interne Watchdog (IWDG) der STM32F4 CPU benutzt werden. (die CPU hat auch noch einen zweiten Watchdog : WWDG)
Der IWDG hängt am internen RC-Oszillator (mit ca. 32kHz) und ist damit unabhängig vom rest der CPU. Wenn der Watchdog einmal gestartet ist, kann er von der Software nicht mehr gestoppt werden und muss zyklisch getriggert werden sonst wird ein Reset ausgelöst.
Der interne RC-Oszillator ist nicht besonders genau aber das spielt für den Zweck des Watchdogs in meinen Augen keine große Rolle. Ich würde einen Sicherheitsfaktor von 2 vorsehen (also wenn der Timeout auf 250ms eingestellt wird, sollte der Trigger ca. alle 100ms aufgerufen werden)
Die Init-Funktion liefert als Rückgabewert ob der letzte Reset-Grund der Watchdog war. Das kann benutzt werden um einen Fehlerstatus auszugeben.
Die Library ist sehr einfach aufgebaut mit zwei Funktionen (Init und Trigger)
In der Demo wird eine Pausenzeit solange vergrößert, bis der Watchdog zuschlägt.
Voraussetzungen :
1 2 | Benutzte Module der CooCox-IDE : RCC, IWDG Benutzte Librarys : keine |
Enumerationen :
1 2 3 4 | typedef enum { RESET_SOURCE_NORMAL =0, // normaler Reset RESET_SOURCE_IWDG // reset durch IWDG }IWDG_RESET_SOURCE_t; |
:
1 2 3 4 5 6 7 8 9 | typedef enum { IWDG_TIME_10ms =0, // Timeout auf ca. 10ms IWDG_TIME_50ms, // Timeout auf ca. 50ms IWDG_TIME_100ms, // Timeout auf ca. 100ms IWDG_TIME_250ms, // Timeout auf ca. 250ms IWDG_TIME_500ms, // Timeout auf ca. 500ms IWDG_TIME_1s, // Timeout auf ca. 1s IWDG_TIME_2s // Timeout auf ca. 2s }IWDG_TIME_t; |
Funktionen :
1 2 | IWDG_RESET_SOURCE_t UB_Init_IWDG(IWDG_TIME_t timeout); // zum starten des Watchdogs void UB_IWDG_Trigger(void); // zum triggern des Watchdogs |
Beispiel :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | //-------------------------------------------------------------- // File : main.c // Datum : 26.05.2013 // Version : 1.0 // Autor : UB // EMail : mc-4u(@)t-online.de // Web : www.mikrocontroller-4u.de // CPU : STM32F4 // IDE : CooCox CoIDE 1.7.0 // Module : CMSIS_BOOT, M4_CMSIS_CORE // Funktion : Demo der IWGD-Library // Hinweis : Diese zwei Files muessen auf 8MHz stehen // "cmsis_boot/stm32f4xx.h" // "cmsis_boot/system_stm32f4xx.c" //-------------------------------------------------------------- #include "main.h" #include "stm32_ub_led.h" #include "stm32_ub_iwdg.h" void Delay(volatile uint32_t nCount) { while(nCount--) { } } int main(void) { IWDG_RESET_SOURCE_t check; uint32_t akt_pause=500000; SystemInit(); // Quarz Einstellungen aktivieren // Init der LEDs UB_Led_Init(); UB_Led_On(LED_ORANGE); // LED einschalten Delay(5000000); // kleine Pause // Watchdog aktivieren (mit ca. 500ms) // und Reset-Quelle auswerten check=UB_Init_IWDG(IWDG_TIME_500ms); if(check==RESET_SOURCE_IWDG) { // letze Reset Quelle war der Watchdog UB_Led_On(LED_RED); } else { // letze Reset Quelle war kein Watchdog UB_Led_On(LED_GREEN); } while(1) { // kleine Pause Delay(akt_pause); // Watchdog triggern UB_IWDG_Trigger(); // blaue LED blinken lassen UB_Led_Toggle(LED_BLUE); // Delay Zeit vergrössern // wenn sie >500ms ist, schlägt der Watchdog zu !! akt_pause+=100000; } } |
Hier die Library zum Download :
Hier der komplette CooCox-Projektordner zum Download :
Hallo. Ich versuche gerade die IWDG-Lib zum Laufen zu bewegen. Sobald ich sie enable (analog dem Beispiel), funktioniert der I2C2 Bus nicht mehr, respektive ich kann auf mein EEPROM nicht mehr zugreifen, ein “UB_I2C2_ReadByte(…) blockiert. Ohne klappt alles wunderbar.
Irgend eine Idee, an was das liegen könnte ?
Board: Olimex H407 (12Mhz und 32.768khz quarze).
Danke und Gruss
was macht die CPU denn ? nach dem enable MUSS zyklisch die Trigger-Funktion aufgerufen werden ansonsten macht die CPU einen Reset.
stelle mal eine Watchdogzeit von 2sec ein, ob es damit dann funktioniert.
Ich komme gar nicht so weit.
Da ich noch nicht herausgefunden habe, wie ich hier schön formatierten Code eingeben kann, wird das wohl etwas murks
main()
{
IWDG_RESET_SOURCE_t check;
system_init();
check=UB_Init_IWDG(IWDG_TIME_100ms);
eeprom_error = UB_M24C08_Init(M24C08_0);
while(1)
{ UB_IWDG_Trigger(); }
}
Wenn ich den IWDG initialisiere geht der nächste Befehl mit dem Lesen eines Bytes vom EEPROM nicht mehr, respektive blockiert. Logischerweise schlägt dann der Watch-Dog zu, und zwar in einem schönen Takt, da I2C nach jedem Reset blockiert.
Irgendwie verhindert das aktivieren des IWDG das funktionieren von I2C.
Hmm, eventuell (hoffentlich) liegt der Bock wirklich bei mir.
Scheinbar dauert ein intialisieren von I2C mit lesen eines einzelnen Bytes mehr als die 100ms. Habe aber gemeint, ich hätte auch mal mit 500ms probiert.
Ich habe jetzt die Library eliminiert, und das Ganze direkt in meinem Program eingebaut, und jetzt läuft es. Also so was:
if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET) {
printf(“…”);
RCC_ClearFlag();
}
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_32);
IWDG_SetReload(500);
IWDG_ReloadCounter();
IWDG_Enable();
Werde es später noch mal probieren, erstmal danke für das Feedback
Gruss
Daniel