poniedziałek, 15 lutego 2016

[2] STM32F4 - Discovery - Biblioteka - Niezależny układ czuwający Watchdog

W tym poście zaprezentuję sposób wykonania biblioteki dla niezależnego układu czuwającego, który został opisany w poście [8]. Całość będzie się składała z dwóch plików.

Elementy biblioteki:



Tak naprawdę cała biblioteka będzie się składała z jednej funkcji, która na podstawie podanych zmiennych głównych będzie odpowiednio inicjować układ czuwający.

Poniżej przedstawiam plik nagłówkowy .h:

#ifndef WATCHDOG_H
#define WATCHDOG_H 60
 
#include "stm32f4xx.h"
 
//Reset systemu jest wywolywany co okreslony czas
//zdefiniowany wedlug wybranej zmiennej.
 
#define CzasPrze_10ms     1
#define CzasPrze_250ms    2
#define CzasPrze_500ms    3
#define CzasPrze_1s    4
#define CzasPrze_2s    5
#define CzasPrze_4s    6
#define CzasPrze_8s    7
 
//Ustawienie dzielnika:
 
//Wartosc binarna: 000
#define Dzielnik_4         0x00
//Wartosc binarna: 001
#define Dzielnik_8         0x01
//Wartosc binarna: 010
#define Dzielnik_16        0x02
//Wartosc binarna: 011
#define Dzielnik_32        0x03
//Wartosc binarna: 100
#define Dzielnik_64        0x04
//Wartosc binarna: 101
#define Dzielnik_128       0x05
//Wartosc binarna: 110
#define Dzielnik_256       0x06
 
void IWDGKonfiguracjaReg(uint16_t wartosc, uint8_t dzielnik);
void IWDGKonfiguracja(uint16_t wartosc, uint8_t dzielnik) ;
 
#endif

Teraz kolej na plik zawierający główną funkcję. Prezentuje się on następująco:

#include "STM32F4_Watchdog.h"
 
void IWDGKonfiguracjaReg(uint16_t wartosc, uint8_t dzielnik) 
{
 //Zezwolenie na zapis do rejestrów IWDG_PR oraz IWDG_RLR
 IWDG->KR = 0x5555;
 
        //Ustawienie watrtosci poczatkowej
 if (wartosc == CzasPrze_10ms) 
 {
  IWDG->RLR = 10;
  IWDG->PR = Dzielnik_32;
 } 
        else if (wartosc == CzasPrze_250ms) 
 {
  IWDG->RLR = 255;
  IWDG->PR = Dzielnik_32;
 } 
 else if (wartosc == CzasPrze_500ms) {
  IWDG->RLR = 511;
  IWDG->PR = Dzielnik_32;
 } 
 else if (wartosc == CzasPrze_1s) 
 {
  IWDG->RLR = 1023;
  IWDG->PR = Dzielnik_32;
 } 
 else if (wartosc == CzasPrze_2s) 
 {
  IWDG->RLR = 2047;
  IWDG->PR = Dzielnik_32;
 } 
 else if (wartosc == CzasPrze_4s) 
 {
  //Maksymalna wartosc jaka mozna wprowadzic
  //do tego rejestru
  IWDG->RLR = 4095;
  IWDG->PR = Dzielnik_32;
 } 
 else if (wartosc == CzasPrze_8s) 
 {
  IWDG->RLR = 1023;
  IWDG->PR = Dzielnik_256;
 }
 else
 {
  IWDG->RLR = wartosc;
  IWDG->PR = dzielnik;
 }
 
 //Przeladowanie wybranej konfiguraci
 IWDG->KR = 0xAAAA;
 
 //Wlaczenie watchdoga oraz sygnalu taktujacego LSI
 IWDG->KR = 0xCCCC;
}
 
void IWDGKonfiguracja(uint16_t wartosc, uint8_t dzielnik) 
{
 //Zezwolenie na zapis do rejestrów IWDG_PR oraz IWDG_RLR (0x5555)
 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
 
        //Ustawienie watrtosci poczatkowej
 if (wartosc == CzasPrze_10ms) 
 {
  //IWDG_SetReload(0xA);
  IWDG_SetReload(10);
  IWDG_SetPrescaler(IWDG_Prescaler_32);
 } 
        else if (wartosc == CzasPrze_250ms) 
 {
  //IWDG_SetReload(0xFF);
  IWDG_SetReload(255);
  IWDG_SetPrescaler(IWDG_Prescaler_32);
 } 
 else if (wartosc == CzasPrze_500ms) 
 {
  //IWDG_SetReload(0x1FF);
  IWDG_SetReload(511);
  IWDG_SetPrescaler(IWDG_Prescaler_32);
 } 
 else if (wartosc == CzasPrze_1s) 
 {
  //IWDG_SetReload(0x3FF);
  IWDG_SetReload(1023);
  IWDG_SetPrescaler(IWDG_Prescaler_32);
 } 
 else if (wartosc == CzasPrze_2s) 
 {
  //IWDG_SetReload(0x7FF);
  IWDG_SetReload(2047);
  IWDG_SetPrescaler(IWDG_Prescaler_32);
 } 
 else if (wartosc == CzasPrze_4s) 
 {
  //Maksymalna wartosc jaka mozna wprowadzic
  //do tego rejestru
  //IWDG_SetReload(0xFFF);
  IWDG_SetReload(4095);
  IWDG_SetPrescaler(IWDG_Prescaler_32);
 } 
 else if (wartosc == CzasPrze_8s) 
 {
  //IWDG_SetReload(0x3FF);
  IWDG_SetReload(1023);
  IWDG_SetPrescaler(IWDG_Prescaler_32);
 }
 else
 {
  IWDG_SetReload(wartosc);
  IWDG_SetPrescaler(dzielnik);
 }
 
 //Przeladowanie wybranej konfiguraci
 IWDG_ReloadCounter();
 
 //Wlaczenie watchdoga oraz sygnalu taktujacego LSI
 IWDG_Enable();
}

W głównej części zawarłem dwa sposoby inicjalizacji pracy watchdoga na rejestrach, oraz z wykorzystaniem bibliotek API.

Czas minimalny oraz maksymalny jaki będzie resetowanie mikrokontrolera oraz jego odświeżenie należy obliczyć z następujących danych wzorów:


W głównym programie należy pamiętać o zainicjowaniu funkcji watchdoga, sprawdzeniu czy praca się od resetu wywołanego przez układ czuwający, oraz o przeładowaniu licznika. Pozostałe elementy są należy umieszczać według potrzeby.

//Warunek sprawdzajacy czy system zaczal prace po wykorzystaniu resetu
//przez uklad czuwajacy, Jezeli tak to wejscie w petle
if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET)
{
    //Wyczyszczenie flagi resetu
    RCC_ClearFlag();
    //Petla opózniajaca
    for (i=0;i<10000000;i++);
}
.
.
IWDGKonfiguracjaReg();
.
.
IWDG_ReloadCounter();
.
.