Bootloader to program działający w mikrokontrolerze, który ma zostać zaprogramowany. Odbiera informacje o nowym programie zewnętrznie za pomocą niektórych środków komunikacji i zapisuje te informacje w pamięci programu procesora.
Jest to sprzeczne z normalnym sposobem wprowadzania programu do mikrokontrolera, który odbywa się za pomocą specjalnego sprzętu wbudowanego w mikro w tym celu. W przypadku PIC jest to interfejs podobny do SPI. O ile dobrze pamiętam, AVR-y używają Jtag, a przynajmniej niektóre z nich. Tak czy inaczej, wymaga to zewnętrznego sprzętu, który porusza pinami programującymi w sam raz, aby zapisać informacje w pamięci programu. Plik HEX opisujący zawartość pamięci programu pochodzi z komputera ogólnego przeznaczenia, więc sprzęt ten łączy się z komputerem z jednej strony, a specjalne piny programujące mikro z drugiej. Moja firma robi programistów PIC między innymi jako linię boczną, więc jestem całkiem zaznajomiony z tym procesem na PIC.
Ważnym punktem programowania zewnętrznego za pośrednictwem specjalistycznego sprzętu jest to, że działa niezależnie od istniejącej zawartości pamięci programu. Mikrokontrolery zaczynają się od skasowania pamięci programu lub w nieznanym stanie, więc programowanie zewnętrzne to jedyny sposób na przeniesienie pierwszego programu do mikro.
Jeśli masz pewność co do programu, który chcesz załadować do swojego produktu, a twoje wolumeny są wystarczająco duże, możesz poprosić o chipy producenta lub dystrybutora. Chip jest przylutowany do płyty, jak każdy inny układ, i jednostka jest gotowa do pracy. Może to być odpowiednie na przykład w przypadku zabawki. Gdy oprogramowanie układowe jest gotowe, jest prawie gotowe i będzie produkowane w dużych ilościach.
Jeśli woluminy są niższe lub, co ważniejsze, oczekujesz ciągłego rozwoju oprogramowania układowego i naprawiania błędów, nie chcesz kupować wstępnie zaprogramowanych układów. W takim przypadku puste płyty są montowane na płycie, a oprogramowanie układowe musi zostać załadowane na chip jako część procesu produkcyjnego. W takim przypadku linie programowania sprzętu muszą zostać w jakiś sposób udostępnione. Może to być za pomocą wyraźnego złącza lub padów pogo pin, jeśli chcesz stworzyć produkcyjne urządzenie testowe. Często takie produkty muszą zostać przetestowane i być może skalibrowane, więc dodatkowy koszt pisania programu na procesorze jest zwykle minimalny. Czasami, gdy używane są małe procesory, do procesora najpierw ładowane jest specjalne oprogramowanie testowe. Służy to do testowania i kalibracji urządzenia, wtedy prawdziwe oprogramowanie układowe jest ładowane po tym, jak sprzęt okaże się dobry. W tym przypadku istnieją pewne względy dotyczące projektowania obwodu, aby umożliwić dostęp do linii programowania w stopniu wystarczającym do działania procesu programowania, ale także nie nadmiernie utrudniać obwodu. Aby uzyskać więcej informacji na ten temat, zobacz mójzapis programowania w obwodzie.
Jak dotąd tak dobrze i nie jest potrzebny żaden program ładujący. Zastanów się jednak nad produktem ze stosunkowo złożonym oprogramowaniem układowym, który chcesz zaktualizować w terenie, a nawet pozwolić klientowi końcowemu na aktualizację. Nie można oczekiwać, że klient końcowy będzie miał gadżet programisty lub że będzie wiedział, jak prawidłowo go używać, nawet jeśli go dostarczyłeś. Tak naprawdę robi to jeden z moich klientów. Jeśli kupisz specjalną opcję dostosowywania pola, dostaniesz jednego z moich programistów z produktem.
Jednak w większości przypadków po prostu chcesz, aby klient uruchomił program na komputerze i magicznie zaktualizował oprogramowanie układowe. W tym miejscu pojawia się bootloader, szczególnie jeśli twój produkt ma już port komunikacyjny, który może łatwo łączyć się z komputerem, takim jak USB, RS-232 lub Ethernet. Klient uruchamia program na PC, który rozmawia z bootloaderem już w mikro. To wysyła nowy plik binarny do programu ładującego, który zapisuje go w pamięci programu, a następnie powoduje uruchomienie nowego kodu.
Brzmi prosto, ale nie jest tak, przynajmniej jeśli nie chcesz, aby ten proces był niezawodny. Co się stanie, jeśli wystąpi błąd komunikacji, a nowe oprogramowanie układowe zostanie uszkodzone, zanim dotrze do programu ładującego? Co się stanie, jeśli nastąpi przerwa w zasilaniu podczas rozruchu? Co się stanie, jeśli bootloader ma błąd i bzdury?
Uproszczonym scenariuszem jest to, że bootloader zawsze uruchamia się od resetu. Próbuje komunikować się z hostem. Jeśli host odpowie, to albo mówi programowi ładującemu, że nie ma nic nowego, ani wysyła mu nowy kod. Wraz z nadejściem nowego kodu stary kod jest zastępowany. Zawsze dołączasz sumę kontrolną z przesłanym kodem, aby bootloader mógł stwierdzić, czy nowa aplikacja jest nienaruszona. Jeśli nie, pozostaje w bootloaderze stale żądając przesłania, dopóki coś z prawidłową sumą kontrolną nie zostanie załadowane do pamięci. Może to być akceptowalne dla urządzenia, które jest zawsze podłączone i gdzie możliwe jest uruchomienie zadania w tle na hoście, który odpowiada na żądania bootloadera. Ten schemat nie jest dobry dla jednostek, które są w dużej mierze autonomiczne i tylko sporadycznie łączą się z komputerem hosta.
Zwykle prosty program ładujący, jak opisano powyżej, jest nie do przyjęcia, ponieważ nie jest bezpieczny w razie awarii. Jeśli nowy obraz aplikacji nie zostanie nienaruszony, chcesz, aby urządzenie kontynuowało działanie starego obrazu, aby nie było martwe do momentu pomyślnego przesłania. Z tego powodu zwykle w oprogramowaniu wbudowanym są dwa specjalne moduły: program ładujący i program ładujący. Program do przesyłania jest częścią głównej aplikacji. W ramach regularnej komunikacji z hostem można przesłać nowy obraz aplikacji. Wymaga to oddzielnej pamięci od głównego obrazu aplikacji, takiego jak zewnętrzna pamięć EEPROM lub użycie większego procesora, aby połowę miejsca w pamięci programu można było przeznaczyć na przechowywanie nowego obrazu aplikacji. Przesyłający zapisuje gdzieś otrzymany nowy obraz aplikacji, ale go nie uruchamia. Gdy procesor zostanie zresetowany, co może się zdarzyć na polecenie hosta po przesłaniu, bootloader działa. Jest to teraz całkowicie samodzielny program, który nie wymaga możliwości komunikacji zewnętrznej. Porównuje bieżące i przesłane wersje aplikacji, sprawdza ich sumy kontrolne i kopiuje nowy obraz do obszaru aplikacji, jeśli wersje różnią się, i sprawdza nową sumę kontrolną obrazu. Jeśli nowy obraz jest uszkodzony, po prostu uruchamia starą aplikację jak poprzednio.
Zrobiłem wiele programów ładujących i nie ma dwóch takich samych. Nie ma bootloadera ogólnego przeznaczenia, pomimo tego, w co niektóre firmy zajmujące się mikrokontrolerem chcą, abyś w to wierzył. Każde urządzenie ma swoje wymagania i szczególne okoliczności dotyczące obsługi hosta. Oto tylko niektóre konfiguracje bootloadera i czasami uploadera:
- Podstawowy program ładujący. To urządzenie miało linię szeregową i będzie podłączone do hosta i włączone w razie potrzeby. Program ładujący uruchomił się od resetu i wysłał kilka odpowiedzi na żądanie przesłania do hosta. Jeśli program do przesyłania działał, zareagowałby i wysłał nowy obraz aplikacji. Jeśli nie zareaguje w ciągu 500 ms, bootloader zrezygnuje i uruchomi istniejącą aplikację. Aby zaktualizować oprogramowanie wewnętrzne, musisz najpierw uruchomić aplikację aktualizującą na hoście, a następnie podłączyć i włączyć urządzenie.
- Program do przesyłania pamięci. Tutaj użyliśmy PIC o następnym rozmiarze, który miał dwa razy więcej pamięci programu. Pamięć programu została z grubsza podzielona na 49% głównej aplikacji, 49% nowego obrazu aplikacji i 2% bootloadera. Program ładujący uruchomiłby się od resetu i skopiował nowy obraz aplikacji na bieżący obraz aplikacji w odpowiednich warunkach.
- Zewnętrzny obraz EEPROM. Podobnie jak nr 2 z wyjątkiem tego, że do przechowywania nowego obrazu aplikacji użyto zewnętrznej pamięci EEPROM. W tym przypadku procesor z większą pamięcią byłby również fizycznie większy i należałby do innej podrodziny, w której nie było potrzebnych nam urządzeń peryferyjnych.
- Program ładujący TCP. To był najbardziej złożony ze wszystkich. Zastosowano duży PIC 18F. Ostatnia 1/4 pamięci zawierała bootloader, który miał własną kompletną kopię stosu sieciowego TCP. Program ładujący uruchomił się od resetu i próbował połączyć się ze specjalnym serwerem wysyłającym pod znanym portem pod wcześniej skonfigurowanym adresem IP. Dotyczyło to dużych instalacji, w których zawsze była dedykowana maszyna serwerowa dla całego systemu. Każde małe urządzenie po resecie zaloguje się na serwerze przesyłania i otrzyma nową kopię aplikacji. Program ładujący nadpisze istniejącą aplikację nową kopią, ale uruchom ją tylko wtedy, gdy zostanie zaznaczona suma kontrolna. Jeśli nie, wróci do serwera przesyłania i spróbuje ponownie.
Ponieważ sam bootloader był skomplikowanym kodem zawierającym pełny stos sieciowy TCP, również musiał być możliwy do uaktualnienia w terenie. Sposób, w jaki to zrobiliśmy, polegał na tym, aby serwer wysyłający nakarmił go specjalną aplikacją, której jedynym celem było zastąpienie bootloadera po jego uruchomieniu, a następnie zresetowanie komputera, aby uruchomił się nowy bootloader, co spowodowałoby, że serwer uploadu wysłał najnowszy obraz głównej aplikacji. Technicznie usterka zasilania w ciągu kilku milisekund potrzebnych specjalnej aplikacji do skopiowania nowego obrazu za pomocą programu ładującego byłaby nie do naprawienia. W praktyce tak się nigdy nie stało. Byliśmy w porządku z bardzo mało prawdopodobną szansą na to, ponieważ te urządzenia były częścią dużych instalacji, w których już byli ludzie, którzy przeprowadziliby konserwację systemu, co czasami oznaczało wymianę urządzeń wbudowanych z innych powodów.
Mamy nadzieję, że zauważysz, że istnieje wiele innych możliwości, każda z własnymi kompromisami ryzyka, szybkości, kosztów, łatwości użytkowania, przestojów itp.