Dlaczego potrzebujemy bootloadera niezależnego od naszego programu aplikacyjnego w mikrokontrolerach?

28

Dlaczego potrzebujemy osobnego programu w tej samej pamięci programu flash mikrokontrolera, a konkretnie STM32F103, który nazywa się bootloaderem?

Czym wyróżnia się to, że jest oddzielone od głównego programu aplikacyjnego?

Ogólnie rzecz biorąc, czy bootloader systemu mikroprocesorowego (powiedzmy PowerPC MPC8270) wykonuje to samo zadanie, co mikrokontroler (powiedzmy ARM STM32F103), czy też wykonują zasadniczo różne zadania od siebie, a mimo to oba są nazywane „bootloaderem” ?

alt-rose
źródło
2
z tego samego powodu, dla którego masz pojedyncze chipy i części, a nie jedną gigantyczną monolityczną strukturę
Emobe
Ty nie. Wystarczy wprowadzić program za pomocą przełączników i lampek na konsoli komputera.
Hot Licks
1
Ściśle mówiąc, nie potrzebujesz osobnego programu ładującego na mikrokontrolerze. Ale najczęściej wybieramy taką, która oferuje dodatkowe funkcje użytkowe, które oferuje. Jeśli te funkcje nie są potrzebne, nie są potrzebne, możesz usunąć program ładujący. Program ładujący mikrokontrolera jest zwykle używany do nagrywania nowego programu we flashu. Czasami może być używany do debugowania funkcji, niektórych punktów przerwania wsparcia i innych przyjemnych w użyciu funkcji. Na mikrokomputerze zazwyczaj bootloader ładuje programy z pamięci masowej i tam będzie potrzebny.
ghellquist

Odpowiedzi:

55

Program ładujący mikrokontrolera jest odpowiedzialny za aktualizację głównego oprogramowania układowego za pośrednictwem kanału komunikacyjnego innego niż nagłówek programowania. Jest to przydatne do aktualizacji oprogramowania w terenie przez BLE, UART, I2C, karty SD, USB itp. Niezwykle niewygodne byłoby wymaganie od klientów zakupu programistów tylko w celu aktualizacji oprogramowania na swoich urządzeniach.

Powodem, dla którego bootloader jest oddzielny, jest niezawodność. Program ładujący i kod aplikacji są umieszczone w osobnych sekcjach pamięci flash, dzięki czemu kod aplikacji może zostać usunięty i ponownie napisany przez program ładujący bez zmiany czegokolwiek związanego z kodem programu ładującego.

Gdyby bootloader i aplikacja były trzymane razem, kod bootloadera musiałby zostać skopiowany do pamięci RAM, zanim będzie mógł działać, ponieważ każda aktualizacja oprogramowania układowego wymazałaby kod bootloadera we flashu. Gdyby odcięto zasilanie za pomocą kodu bootloadera w pamięci RAM, a pamięć flash została wymazana, urządzenie zostałoby zepsute.

CurtisHx
źródło
3
Nasz jest z tego samego powodu. Są w tej samej pamięci flash, ale program ładujący jest wyrównany i wymazuje granicę wymazywania pamięci flash i jest wystarczająco inteligentny, aby wymazać flash tylko wyżej niż własne adresy.
Joshua
3
W niektórych przypadkach nagłówek programowania mikroprocesora może być w rzeczywistości niedostępny bez konieczności demontażu obudowy produktu, więc możliwość przeprogramowania go przez magistralę komunikacyjną bez dodatkowego sprzętu jest kluczowym czynnikiem niezawodności.
John Go-Soco
6
@ alt-rose Program ładujący i aplikacja to osobno skompilowane programy, każdy z własnym kodem startowym i main()funkcją. Po włączeniu uruchamia się kod startowy bootloadera i wywołuje bootloader main(). Program rozruchowy sprawdza poprawność aplikacji, a następnie przeskakuje do kodu startowego aplikacji, który wywołuje program aplikacji main(). Kod startowy każdego programu inicjuje środowisko wykonawcze C dla odpowiedniego programu (tj. Inicjuje zmienne, stos itp.) I zazwyczaj żaden program main()nigdy nie wraca do kodu startowego.
kkrambo
1
@ alt-rose: W ten sam sposób, w jaki procesor otrzymuje adres początkowy programu ładującego - tak nie jest. Zamiast tego CPU określa, jaki będzie używał jako początkowy adres bootloadera, a bootloader określa, co będzie używał jako początkowy adres programu aplikacyjnego.
MSalters
4
@kkrambo Choć powszechnie prawdziwe, nie ma wymogu (ani uniwersalnie prawdziwe fakt), że bootloader być napisany w języku C lub C-języka pochodzi z mainwcale.
Yakk
26
  1. Aby proces ładowania mógł odzyskać po błędach. Załóżmy, że wystąpił błąd komunikacji lub odłączenie zasilania podczas aktualizacji. Jeśli moduł ładujący był częścią aktualizowanej aplikacji, użytkownik nie byłby w stanie spróbować ponownie bez użycia specjalnego sprzętu do ponownego załadowania modułu ładującego.

  2. Niektóre mikrokontrolery nie mogą wykonać kodu z pamięci RAM. Jeśli moduł ładujący został zmieszany z resztą oprogramowania, nie byłoby możliwe uaktualnienie oprogramowania, ponieważ nie można usunąć stron flash, z których obecnie się uruchamiasz. Obejście polega na tym, aby najpierw wypalić nowy kod do drugiej połowy flasha, a następnie przejść do niego. Nowy kod następnie kopiuje się do pierwszej połowy flasha. Oczywiście wadą jest to, że nagrywanie flash jest zwykle powolne, a teraz, gdy musisz to zrobić dwa razy, proces ładowania może potrwać nawet dwa razy dłużej. Również to obejście ogranicza rozmiar aplikacji do nie więcej niż połowy całkowitej pamięci flash.

  3. Dobrze napisane programy ładujące starają się sprawdzić, czy na urządzeniu istnieje prawidłowy kod, zanim spróbujemy go wykonać. Jeśli moduł ładujący i inny kod zostały zmieszane razem, to skąd masz pewność, że procedura sprawdzania poprawności zadziała, jeśli cały kod nie zostanie załadowany?

  4. Poświadczenie. Bezpieczne moduły ładujące próbują sprawdzić, czy załadowana aplikacja odpowiada podpisowi cyfrowemu przed uruchomieniem. Ale jeśli moduł ładujący i inny kod zostały zmieszane razem, nie można kontrolować, co działa na urządzeniu, ponieważ po załadowaniu nowego kodu przez użytkownika nie można kontrolować, co dzieje się podczas uruchamiania.

użytkownik4574
źródło
4
Jako przykład punktu 2, niektóre mikrokontrolery mogą nawet nie mieć dostępnej pamięci RAM podczas uruchamiania: na przykład Raspberry Pi używa swojego procesora graficznego do ładowania bootloadera z karty SD, co następnie włącza procesor ARM i pamięć.
ErikF
11

Są one ogólnie dostępne, aby umożliwić aktualizację głównego programu aplikacji.

Potrzebujesz kodu, który wie, jak wymazać i przeprogramować część wewnętrznej pamięci flash, co nie może być głównym programem, ponieważ kiedy się skasuje, nie będzie mógł przeprogramować.

Colin
źródło
9

Bootloader pozwala MCU komunikować się z czymś innym, aby zaakceptować nowy program, zapisać go i uruchomić po resecie. Jeśli nie masz bootloadera, potrzebny jest programista, aby uzyskać dostęp do pamięci i umieścić program na swoim miejscu.

Skrzyżowanie dróg
źródło
2
To właściwie tyle. MCU może uzyskać kod tylko przez specjalny podsystem programowania (taki jak AVRICE lub JTAG) lub już przez bootloader we flashu. Decyzja aplikacji o tym, jak skomplikowany jest bootloader, np. Niektóre systemy mogą ładować kod z Wi-Fi. Na bardzo niskich jednostkach MCU, takich jak ATTiny, bootloader (i piny szeregowe) są dużym obciążeniem, więc zawsze używasz programatora.
Rich
7

Oprócz innych poprawnych odpowiedzi na temat umożliwienia przeprogramowania głównego oprogramowania układowego z programu ładującego, kolejną zaletą oddzielenia programu ładującego jest to, że można logicznie oddzielić zadania „wykonaj raz po uruchomieniu” od kodu potrzebnego podczas działania. Następnie, gdy program ładujący zakończy swoje zadania początkowej konfiguracji, główne oprogramowanie układowe może eksmitować program ładujący z całym niepotrzebnym już kodem z pamięci, oszczędzając znaczną ilość pamięci RAM. Można to osiągnąć na inne sposoby, ale podział bootloadera / oprogramowania układowego znacznie ułatwia wiele architektur.

Nate S - Przywróć Monikę
źródło
1
W mikrokontrolerze kod najprawdopodobniej nigdy nie znajduje się w pamięci RAM, więc nie można go eksmitować. Oczywiście możesz odrzucić dane bootloadera z pamięci RAM.
Ben Voigt
@BenVoigt, to zależy od mikrokontrolera. Niektóre (głównie te z pamięcią flash NOR) pozwalają na wykonywanie bezpośrednio z pamięci flash, ale inne (zwykle z flashem NAND, który staje się coraz bardziej powszechny) wymagają wykonania poza pamięcią RAM. Czasami nie ma nawet wbudowanej pamięci flash i musisz skopiować kod z zewnętrznego układu pamięci flash do lokalnej pamięci SRAM, zanim cokolwiek wykonasz.
Nate S - Przywróć Monikę
2

Krótka odpowiedź jest taka, że ​​oprogramowanie jest niesamowite.

Możesz mieć wszystko, co bootloader jest „czystym sprzętem”. Ale o wiele łatwiej jest mieć zadania, które bootloader zapisuje jako oprogramowanie, a następnie interpretuje sprzętowo.

Zadania te mogą obejmować konfigurację sprzętu do uruchomienia „prawdziwego” oprogramowania (na przykład na Raspberry Pi (przez @ErikF)), posiadającego protokół zastępujący „prawdziwy” program przed jego uruchomieniem (sprawdź pin, jeśli ten pin jest ustawiany, a następnie ponownie flashowany prawdziwy program), a nawet konfigurowanie środowiska programowego dla „prawdziwego” programu.

W przypadku oprogramowania w mniejszej skali, po uruchomieniu pliku wykonywalnego program ładujący aplikacje przenosi takie rzeczy, jak ładowanie części danych do pamięci, czasami naprawia adresy, ustawia argumenty na główne lub inne globalne rzeczy, obraca biblioteki dostarczone przez system operacyjny i następnie przeskakuje na początek _mainkodu. Niektóre z tych rzeczy można wykonać za pomocą programu ładującego.

W mikrokontrolerze niektóre zadania, które wykonuje bootloader, można podzielić na program. Kompilator dla Twojej platformy może automatycznie wstrzykiwać kod „setup” do każdego pliku wykonywalnego.

Ale posiadanie go w bootloaderze oznacza, że ​​ten sam kompilator może działać na innym sprzęcie, ponieważ bootloader może „ukryć” różnicę między platformami.

Do tego dochodzi fakt, że flashowanie programu głównego nie ryzykuje bootloadera (i możliwości reflashowania programu głównego), a posiadanie nietrywialnego bootloadera to świetna rzecz.

Jak
źródło
-1

Jedną z odpowiedzi, która nie została uwzględniona, jest potrzeba oddzielenia problemów z powodu ograniczeń języka C.

Generalnie programy ładujące są napisane w połączeniu Asemblera i C, z bardzo wczesnym etapem uruchamiania w Asemblerze.

Robi się to, aby skonfigurować pewne rzeczy, takie jak:

  • przydzielanie stosu C.
  • wczytywanie wskaźnika stosu do rejestru
  • wczytywanie licznika programu do rejestru
  • deklarowanie resetowania wektorów
  • ładowanie drugiego etapu (initramfs) do pamięci RAM.

Jest to bardzo przybliżone przybliżenie podjętych kroków i opisuję proces rozruchu ARM, znów jest inaczej dla x86 i innych architektur.

Jednak główny powód pozostaje ten sam: alokacja stosu C musi odbywać się od złożenia.

BitShift
źródło
Dlaczego głosowanie negatywne? Jest to zarówno trafne, jak i dokładne.
BitShift
-1

Jedną częścią pytania, na które dotychczas nie udzielono odpowiedzi, jest różnica między programami ładującymi na mikrokontrolerach i systemach mikroprocesorowych.

Mikrokontroler

Większość mikrokontrolerów ma wbudowaną pamięć ROM, która zawiera kod programu. Zmiana tego kodu zwykle wymaga urządzenia programującego, które łączy się z interfejsem programowania mikrokontrolera (np. ISP w ATMega). Ale te interfejsy programowania zwykle nie są zbyt wygodne w użyciu w porównaniu z innymi interfejsami, ponieważ mogą nie być łatwo dostępne w danym kontekście. Na przykład, chociaż prawie każdy komputer ma porty USB, interfejs SPI wymagany dla ISP jest znacznie rzadszy, a inne interfejsy, takie jak interfejs PID używany w ATXMega, są obsługiwane tylko przez dedykowany sprzęt do programowania.

Na przykład, jeśli chcesz zaktualizować oprogramowanie ze zwykłego komputera bez zewnętrznego sprzętu, możesz użyć programu ładującego, który odczytuje z innego rodzaju interfejsu (np. RS232, USB lub RS232 przez USB, jak na Arduino), aby zaprogramować urządzenie przez popularne interfejsy.

To powiedziawszy, jeśli nie potrzebujesz tej funkcji, bootloader jest całkowicie opcjonalny. Mikrokontroler nadal może uruchamiać swój kod całkowicie bez bootloadera.

Mikroprocesor

W mikroprocesorze sprawy wyglądają trochę inaczej. Podczas gdy większość mikroprocesorów jest wyposażona w pamięć ROM wystarczająco dużą dla bootloadera, te pamięci ROM nie są wystarczająco duże, aby pomieścić pełny system operacyjny. Celem bootloadera jest więc inicjalizacja sprzętu, poszukiwanie bootowalnego systemu operacyjnego, załadowanie go i uruchomienie. Bootloader jest więc kluczowy dla każdego rozruchu.

W systemach x86 / x64 ten moduł ładujący jest systemem BIOS lub UEFI (w zasadzie nowszą wersją systemu BIOS).

Czasami może nawet istnieć wiele programów ładujących działających w łańcuchu. Na przykład, jeśli masz system podwójnego rozruchu z systemami Windows i Linux, możesz skończyć z następującymi:

  • BIOS / UEFI uruchamia się i stwierdza, że ​​GRUB jest zainstalowany. Następnie ładuje GRUB (= Grand Unified Bootloader)
  • GRUB znajduje jakiś system Linux i moduł ładujący systemu Windows. Użytkownik wybiera moduł ładujący systemu Windows.
  • Program rozruchowy systemu Windows uruchamia się i znajduje zainstalowany system Windows 7 i Windows 10. Użytkownik wybiera system Windows 10.
  • Windows 10 wreszcie się uruchamia.

Tak więc w tym przypadku były trzy programy, które można uznać za bootloader. Zarówno GRUB, jak i Windows Bootloader są tam głównie po to, aby dać użytkownikowi wygodniejszą opcję wyboru rozruchu niż system BIOS / UEFI. Umożliwia także uruchamianie wielu systemów operacyjnych z tego samego dysku twardego lub nawet z tej samej partycji.

TLDR

Podczas gdy w obu systemach bootloader robi podobne rzeczy (pomagając użytkownikowi wybrać kod, który ma zostać uruchomiony), oba różnią się znacznie tym, jak to robią i co robią dokładnie.

Dakkaron
źródło
Chociaż przydatne jest rozróżnienie systemów z wystarczającą ilością nieulotnej pamięci o dostępie swobodnym (ROM lub flash), aby pomieścić cały program od tych, które muszą uruchamiać kod z pamięci RAM, istnieją mikrokontrolery obu typów i mikroprocesory obu typów.
supercat
Oczywiście różnica między mikrokontrolerem a mikroprocesorem nie jest twardą ramką, a niektóre mikrokontrolery zachowują się bardziej jak mikroprocesor i odwrotnie. Dlatego wziąłem AtMega / Arduino i x86 / x64 jako przykłady, ponieważ zachowują się w ten sposób.
Dakkaron
„mikroprocesory mają ROM wystarczająco duży dla bootloadera… W systemach x86 / x64 ten bootloader to BIOS lub UEFI” Nie. BIOS lub UEFI są przechowywane w zewnętrznej pamięci flash. Pamięć ROM na chipie zapewnia jeszcze niższe funkcje, takie jak inicjalizacja mikrokodu.
Ben Voigt
@Dakkaron: Chciałbym wytyczyć granicę między mikroprocesorem a mikrokontrolerem w oparciu o to, czy układ jest zaprojektowany do użytku w nietypowych celach, bez niczego innego na magistrali adresowej. 8031 nie kwalifikuje się chyba , że jest on funkcjonalnie 8051 (który jest zdecydowanie mikrokontroler), które nie są określone jako mające coś pożytecznego w wewnętrznej pamięci ROM, ale w przeciwnym razie byłyby przeznaczone do użytku wyłącznie z pamięci wewnętrznej). Coś w rodzaju RCA / CDP 1802 nie kwalifikuje się, nawet jeśli można go użyć do napędzania metek LED ...
supercat
... bez zewnętrznej pamięci RAM i ROM, ponieważ projekty bez pamięci RAM / ROM są ograniczone do prostych zadań. Coś takiego jak TMS 32050, który, o ile pamiętam, ma bootloader i kilka tysięcy słów 16-bitowych słów RAM, kwalifikowałby się jednak jako mikrokontroler; chociaż wiele aplikacji wymagałoby więcej dodawania większej ilości pamięci RAM, jeśli zostanie podłączony przez UART do innego systemu, może służyć do wielu celów bez niczego na swojej magistrali pamięci.
supercat