W każdym niemalże systemie wbudowanym, bez względu na zastosowanie, potrzebna jest jakaś forma podstawy czasu. Nie chodzi tu bynajmniej o bieżącą godzinę i datę, a o możliwość periodycznego wywoływania określonych zadań oraz pomiar czasu między zdarzeniami. Najprostszym rozwiązaniem jest zaprzęgnięcie do pracy jednego z wielu dostępnych liczników/timerów mikrokontrolera. Niektóre układy posiadają specjalizowane timery służące właśnie generowaniu periodycznych przerwań zapewniających podstawę czasu. W przypadku STM32F407 jest to 24-bitowy licznik SysTick (Cortex System Timer). Charakteryzuje się dużo prostszą budową, niż inne dostępne liczniki. Posiada także własne, dedykowane przerwanie. Od strony sprzętowej, jest to idealny kandydat.
Idealną formą programowej realizacji daemona/usługi zapewniającej czas dla różnych aplikacji, byłaby usługa/demon, do którego poszczególne aplikacje rejestrowałyby swoje callbacki z zadanym okresem wywołania. Można wyobrazić sobie prosty interfejs takiej usługi, w stylu WykonajCo(zadany_czas, moja_funkcja). Innymi słowy jeśli dana aplikacja chciałaby aby operacjaA była wykonywana co 150ms, musiała by zawołać WykonujCo(150ms, operacjaA).
W czasie działania systemu, usługa co np. 10ms przechodziłaby po liście zarejestrowanych funkcji i sprawdzała czy nie minął już zadany okres czasu dla każdej z nich.
Takie podejście zapewnia ogromną elastyczność oraz możliwość dynamicznego rejestrowania/usuwania wpisów z listy. Należy jednak zadać sobie kluczowe pytanie: czy rzeczywiście w naszym systemie wymagane jest aż tak zaawansowane rozwiązanie? Jeśli założyć, że wszystkie callbacki aplikacji są statycznie przypisywane i nie jest konieczna ich rekonfiguracja w czasie pracy urządzenia, można nieco uprościć architekturę usługi.
W tym podejściu istnieje grupa z góry zdefiniowanych “slotów” na callbacki, wywoływanych z określoną częstotliwością, np. co 10ms, co 100ms, co minutę. Ponieważ przypisanie callback’a do danego jest statycznie, można dokonać go na etapie kompilacji. Ostateczna architektura naszej podstawy czasu wygląda następująco:
SysTick dostarcza podstawę czasu o rozdzielczości 1ms. Jest ona następnie dzielona i dystrybuowana na poszczególne sloty: 10ms (SysTick/10), 100ms (SysTick/100), 500ms (SysTick/500), 1sek (SysTick/1000) oraz 1min (SysTick/60000). Każdy slot składa się ze statycznej listy funkcji, które mają zostać wykonane po upłynięciu zadanego okresu czasu. W ten sposób uzyskujemy rozwiązanie prostsze, o nieco mniejszej elastyczności, jednak wciąż spełniające nasze wymagania.
Jutro spróbujemy wykorzystać podstawę czasu do odczytu stanu przycisków. Zapraszam!