32 bity jak najprościej - STM32F0. Przechowywanie danych w pamięci Flash i monitorowanie zasilania. cz. 5

32 bity jak najprościej - STM32F0. Przechowywanie danych w pamięci Flash i monitorowanie zasilania. cz. 5
Pobierz PDF Download icon
Kolejny przykład dla płytki STM32F0DISCOVERY prezentuje użycie pamięci Flash i monitora napięcia zasilania. Pretekstem do przedstawienia tych bloków mikrokontrolera będzie projekt urządzenia rejestrującego całkowity czas swojej pracy.

Podczas pracy urządzenia następuje zliczanie czasu, a przy wyłączaniu zasilania całkowity czas jego pracy w sekundach jest zapisywany do pamięci Flash. Przy ponownym włączeniu licznik czasu pracy jest inicjowany wartością zapamiętaną w pamięci nieulotnej. Gotowy projekt o nazwie PVD-Flash jest zawarty w nowej wersji pliku F0tutorial.zip.

Przedstawiony przykład może być uruchomiony na dowolnym mikrokontrolerze rodziny STM32F0 za wyjątkiem serii STM32F030, która nie jest wyposażona w monitor napięcia zasilania.

Organizacja pamięci Flash

Pamięć Flash w mikrokontrolerach STM32F0 jest podzielona na strony o rozmiarze 1 KiB. Najmniejszą jednostką kasowania jest strona, a jednostką zapisu - słowo 16-bitowe. W stanie skasowanym wszystkie bity komórki pamięci mają wartość 1. Do bezpiecznego przechowywania danych w pamięci Flash należy zarezerwować przynajmniej dwie strony, tak, aby podczas kasowania jednej z nich informacja była trwale zapisana na drugiej stronie. Cała pamięć Flash stanowi w STM32F0 jeden blok - podczas wykonywania operacji kasowania lub zapisu żadna komórka pamięci Flash nie może być odczytywana. Próba odczytu pamięci, np. w celu pobrania instrukcji, powoduje wstrzymanie pracy procesora do zakończenia operacji kasowania lub zapisu.

Sposób przechowywania danych

Program demonstracyjny będzie zapisywał do pamięci Flash słowa 32-bitowe zwierające wartość licznika czasu pracy. Aby uniknąć zbędnego kasowania pamięci, powodującego jej zużycie, kolejne wartości licznika będą zapisywane do kolejnych komórek pamięci, a zapis będzie następował podczas wyłączania zasilania urządzenia. Na przechowywanie danych zostaną zarezerwowane dwie kolejne strony pamięci położone poza obszarem zajmowanym przez program. Na każdej stronie można zapisać 256 wartości licznika. Kasowanie strony będzie następowało po jej zapełnieniu i zapisaniu pierwszej wartości na drugiej stronie. W ten sposób będziemy mieli gwarancję, że pamięć będzie zawsze zawierała ważną wartość licznika. W rozwiązaniu produkcyjnym należałoby wzmocnić bezpieczeństwo danych przez dodanie zabezpieczenia przed błędnym zapisem, np. poprzez wprowadzenie sumy kontrolnej; w naszym przykładzie pominiemy to zabezpieczenie.

Kasowanie i zapis pamięci Flash

Operacje na pamięci Flash są wykonywane za pośrednictwem sterownika pamięci, którego rejestry sterujące są reprezentowane w języku C przez strukturę FLASH. Przed wykonaniem operacji kasowania lub programowania niezbędne jest włączenie modułu FLASH w rejestrze RCC>AHBENR oraz odblokowanie dostępu do pamięci przez kolejny zapis dwóch kluczy do rejestru FLASH→KEYR. Wartości kluczy są zdefiniowane w pliku stm32f0xx.h pod nazwami FLASH_FKEY1 i FLASH_FKEY2.

Operacje na pamięci są inicjowane przez zapis rejestru FLASH→CR.

W celu skasowania strony należy:

  • zapisać do rejestru FLASH→CR słowo z ustawionym bitem PER;
  • zapisać do rejestru FLASH→AR adres należący do kasowanej strony;
  • zapisać do rejestru FLASH→CR słowo z ustawionym bitem STRT.

W celu zapisu słowa 16-bitowego do pamięci należy zapisać do rejestru FLASH→CR słowo z ustawionym bitem PG, a następnie zapisać programowaną wartość słowa 16-bitowego pod adres, pod którym ma ono być umieszczone w pamięci Flash.

Operacja kasowania może trwać do 40 ms, a zapisu słowa - do 60 µs. Ponieważ program jest wykonywany z pamięci Flash, jego wykonanie zostaje wstrzymane na czas operacji - dlatego w programie nie jest sprawdzany bit BSY w rejestrze FLASH→SR. Stan ostatnio zleconej operacji można odczytać z rejestru FLASH→SR po jej zakończeniu. Bit EOP oznacza jej pomyślne zakończenie. Po zakończeniu operacji należy ten bit wyzerować, zapisując do FLASH→SR słowo z ustawionym bitem EOP.

Monitor napięcia zasilania

Monitor napięcia zasilania jest częścią modułu PWR. Jego działanie polega na generowaniu pojedynczego sygnału PVDO, który przyjmuje wartość 0 gdy napięcie zasilania przekracza zaprogramowaną wartość progową, a 1 - gdy napięcie zasilania spadnie poniżej określonej granicy. Komparator napięcia charakteryzuje się histerezą ok. 100 mV.

Dostęp do rejestrów modułu PWR wymaga włączenia w rejestrze RCC→APB1ENR. Monitor zasilania jest programowany poprzez zapis do rejestru PWR→CR. Ustawienie bitu PVDE powoduje jego włączenie, a 3-bitowe pole PLS zawiera zadaną wartość napięcia progowego. Odwzorowanie wartości pola w poziomy napięć jest opisane w dokumencie STM32F051xx Datasheet. Ponieważ na płytce STM32F0DISCOVERY mikrokontroler jest zasilany napięciem ok. 3 V, w przykładzie zaprogramowano detektor na nominalne napięcie progowe 2,58 V.

Aktualną wartość wyjścia PVD można odczytać programowo z bitu PVDO rejestru PWR→CSR. Zmiana tej wartości może również spowodować zgłoszenia przerwania za pośrednictwem modułu EX TI.

Sterownik przerwań EXTI

Listing 1. Program demonstracyjny

Sterownik przerwań EXTI pośredniczy w generowaniu sygnałów zgłoszenia przerwań z tych bloków mikrokontrolera, które mogą pracować w stanach głębokiego uśpienia i mogą powodować wybudzenie mikrokontrolera. Jednym z takich bloków jest monitor napięcia zasilania, dlatego uaktywnienie przerwania PVD wymaga zaprogramowania zarówno sterownika EXTI, jaki i głównego sterownika przerwań rdzenia Cortex-M0 - NVIC. Sygnał stanu detektora PVDO jest doprowadzony na wejście EXTI o numerze 16. W celu umożliwienia zgłoszenia przerwania przy spadku napięcia zasilania, sygnalizowanego zmianą stanu PVDO z 0 na 1, należy:

  • ustawić bit 16 rejestru zezwolenia na zgłoszenie przerwania od narastającego zbocza sygnału - EXTI→RTSR;
  • ustawić bit 16 rejestru zezwolenia na zgłoszenie przerwań z poszczególnych źródeł - EXTI→IMR;
  • włączyć przerwanie PVD w sterowniku przerwań NVIC.

Procedura obsługi przerwania PVD musi jawnie skasować zgłoszenie przerwania poprzez zapis do rejestru EXTI→PR słowa z ustawionym bitem 16.

Działanie programu

Listing 1. c.d.

Plik źródłowy program przedstawiono na listingu 1. Program demonstracyjny odmierza czas swojego działania i wysyła go co sekundę w postaci znakowej przez UART, a przy zaniku zachowuje licznik czasu pracy w pamięci Flash.

Do odmierzania czasu użyto timera systemowego SystTick. zaprogramowanego na częstotliwość 100 Hz. Podobnie, jak w kilku poprzednich projektach, moduł UART został zaprogramowany tak, że wyjście TXD (PA9) mikrokontrolera może zostać połączone bezpośrednio z wejściem RXD interfejsu RS232 (styk 2 złącza DB9), bez potrzeby stosowania translatora poziomów. Ponieważ interfejs USB zapewnia połączenia mas, w warunkach doświadczalnych można użyć pojedynczego przewodu. Wartość licznika można wyświetlić na komputerze PC w programie terminala, skonfigurowanym na parametry transmisji 115200, 8, n, 1.

Podczas inicjowania następuje obniżenie priorytetu przerwania SysTick, tak, aby przerwanie od zaniku zasilania powodowało natychmiastowe wywołanie jego obsługi i zapis danych do pamięci Flash. Adres fragmentu pamięci Flash używanego do zapisu danych określa stała DFLASH_ADDR.

Po zaprogramowaniu rejestrów peryferiali program najpierw sprawdza, czy wartości licznika są zapisane na obu stronach pamięci Flash używanych do przechowywania danych. Może to mieć miejsce tylko wtedy, gdy przy poprzednim wyłączeniu wartość licznika została zapisana jako pierwsza na nowej stronie. W takim przypadku program kasuje stronę zawierającą starsze (mniejsze) wartości licznik a.

Następnie program sprawdza, która strona zawiera zapisane wartości licznika, po czym odczytuje z tej strony kolejne wartości tak długo, dopóki nie znajdzie pustego słowa (o wartości 0xFFFFFFFF). Zmienna prev_up_time, przechowująca wartość czasu zapisaną w pamięci Flash, zostaje zainicjowana ostatnią znalezioną wartością niepustą; jednocześnie zmienna idx zostaje ustawiona tak, by wskazywała ona pierwsze puste słowo pamięci, w którym będzie zapisana nowa wartość licznika. Wartość prev_up_time służy do zainicjowania zmiennej up_time, która służy jako licznik sekund czasu pracy. Odliczanie czasu następuje w procedurze obsług przerwania timera SysTick. Po zliczeniu każdej sekundy następuje konwersja wartości czasu pracy do postaci znakowej i wysłanie go przez UART przy użyciu DMA.

Spadek napięcia zasilania powoduje zgłoszenie przerwania PVD i wywołanie jego obsługi. Jeżeli bieżąca wartość licznika czasu różni się od wartości przechowanej w pamięci Flash, w procedurze obsługi przerwania następuje zapis do pamięci nowej wartości w dwóch porcjach po 16 bitów.

Jeżeli wartość napięcia zasilania wróci do normy, nie spowoduje to żadnych negatywnych skutków. Przy kolejnym spadku nastąpi ewentualny kolejny zapis, o ile licznik czasu pracy zmienił swoją wartość.

Grzegorz Mazur

Artykuł ukazał się w
Elektronika Praktyczna
maj 2014
DO POBRANIA
Pobierz PDF Download icon

Elektronika Praktyczna Plus lipiec - grudzień 2012

Elektronika Praktyczna Plus

Monograficzne wydania specjalne

Elektronik kwiecień 2024

Elektronik

Magazyn elektroniki profesjonalnej

Raspberry Pi 2015

Raspberry Pi

Wykorzystaj wszystkie możliwości wyjątkowego minikomputera

Świat Radio marzec - kwiecień 2024

Świat Radio

Magazyn krótkofalowców i amatorów CB

Automatyka, Podzespoły, Aplikacje kwiecień 2024

Automatyka, Podzespoły, Aplikacje

Technika i rynek systemów automatyki

Elektronika Praktyczna kwiecień 2024

Elektronika Praktyczna

Międzynarodowy magazyn elektroników konstruktorów

Elektronika dla Wszystkich maj 2024

Elektronika dla Wszystkich

Interesująca elektronika dla pasjonatów