ISP przy użyciu USB w mikrokontrolerach LPC1300
System plików FAT emulowany przez pamięć ROM służącą do bootowania składa się z jednego pliku nazwanego firmware.bin, w którym zapisana jest cała zawartość pamięci Flash układu. Zwykle dysk musi być nieco większy niż zapisane na nim dane, gdyż konieczne jest zapisanie tablicy alokacji i struktury folderów. W przypadku emulowanego przez LPC1300 systemu plików, potrzebne są 4 bloki, zawierające: katalog główny, sektor rozruchowy (Boot Block) oraz tablicę alokacji plików. Jako że musi być możliwość zaprogramowania całej pamięci za pomocą ISP, te dodatkowe bloki są emulowane za pomocą pamięci RAM i ROM, zamiast być mapowane na Flash. W związku z tym, metadane systemu plików nie są zachowywane przy odłączaniu zasilania – zapisywane są tylko dane wprowadzone do pamięci Flash poprzez plik firmware.bin.
Dane zapisane w systemie plików są zorganizowane w pamięci Flash w blokach, przy czym zawartość pamięci zaczyna się od bloku 4. Gdy plik firmware.bin jest usuwany, host na którym działa system Windows zaalokuje jakikolwiek inny plik, rozpoczynający się od bloku 4 i użyje coraz wyższych numerów bloków przy zapisie kolejnych informacji. Oznacza to, że w przypadku systemu Windows, jakiekolwiek standardowe narzędzie czy program może zostać użyte do zapisywania nowego firmware’u procesora LPC1300, np. w Eksploratorze Windows, użytkownik może usunąć plik firmware.bin i przeciągnąć nowy plik, aby zaprogramować Flash. Na maszynach Linuksowych i Macintosh system plików FAT jest, niestety, obsługiwany inaczej, gdyż systemy te często alokują bloki dla plików w innej kolejności. W konsekwencji, zapisany firmware ulega reorganizacji i staje się bezużyteczny. Są dwie drogi obejścia tego problemu. Najprostszy sposób polega na nadpisaniu istniejącego pliku firmware.bin. Bardziej „brutalną” metodą, wymagającą uprawnień administratora, jest bezpośrednie zapisywanie „na urządzenie” przez /dev.
Automatyzacja In-System Programmingu przez USB
Czasami wymagane może być, aby aktualizacje firmware’u były wykonywane bez ingerencji użytkownika. Pytanie użytkownika o to, który dysk jest przypisany do programowanego układu, podłączonego przez USB lub proszenie o ręczne usunięcie i nadpisanie pliku może być po prostu zbyt skomplikowane. Firmware często musi być aktualizowany w pełni automatycznie, za pomocą programu działającego na komputerze-hoście. Ten rozdział wyjaśni, jak można wcielić w życie takie rozwiązanie. Aby w pełni zautomatyzować proces po stronie komputera PC, program powinien sam odnaleźć urządzenie USB, które ma zostać zaktualizowane, przekształcić „uchwyt” urządzenia w ścieżkę do pliku, sprawdzić tryb CRP, zapisać plik z zawartością pamięci Flash oraz odłączyć (wymontować) urządzenie, by zapewnić, że pamięć została nadpisana. Każdy z tych kroków zostanie omówiony osobno. Użyteczna może być też forma weryfikacji lub walidacji pliku z firmwarem, który ma zostać użyty do aktualizacji. Można to zrobić przy pomocy kryteriów prawidłowości kodu, opisanych w sekcji Criterion for Valid User Code podręcznika użytkownika układów LPC134x, które zostały zaimplementowane w narzędziu ISP dla systemu Windows. Można też sprawdzać czy plik ma rozmiar odpowiadający pojemności pamięci Flash programowanego urządzenia, co zostało zaimplementowane w przykładach dla systemów Linuksowych i Mac OS.
Uwaga: odstępstwa od opisywanych kroków są dopuszczalne i mogą uprościć implementację w różnych systemach operacyjnych, każdy przypadek należy rozpatrywać osobno. |
Odnajdowanie właściwego urządzenia USB
Sposoby numerowania urządzeń USB są różne w różnych systemach operacyjnych . W Linuksach, większość dystrybucji jest wyposażona w narzędzie nazwane lsusb, które pozwala na wyszukanie urządzenia USB o konkretnym identyfikatorze Vendor ID oraz Product ID (03CC:0003). Następnie można użyć programu udevadm (dostępnego w systemach używających systemu plików udev) do wylistowania identyfikatora Model ID oraz ścieżki do urządzenia w systemie. Model ID układów rodziny LPC1300 ma wartość „NXP_LPC13XX_IFLASH”. Gdy mamy już potwierdzone identyfikatory dostawcy (Vendor ID), produktu (Product ID) i modelu (Model ID), można mieć pewność, że odnaleziony został mikrokontroler NXP LPC1300, który pracuje w trybie In-System Programming. W systemach Windows oraz Mac OS-X ten krok wygląda nieco inaczej. Jako że w systemach Mac OS informacja o modelu urządzeń USB jest dostępna w bazie woluminów dyskowych, system przeszukuje tę bazę dopóki nie znajdzie dysku o właściwych identyfikatorach Vendor i Device Model. Podobny proces jest wykorzystywany w Windowsach, gdzie informacja o urządzeniach dyskowych jest wyszukiwana przy pomocy klasy iTuner UsbManager.
Przekształcanie „uchwytu” urządzenia USB w ścieżkę pliku
W systemach Linuksowych operacja ta może zostać wykonana przez iterowanie po wszystkich dyskach w systemie plików udev i odpytywanie udevadm o ich ścieżki systemowe, aż do znalezienia właściwego urządzenia.
- lsusb jest wywoływany dla Vendor ID i Product ID urządzenia NXP pracującego w trybie ISP (04CC:0003). lsusb zwraca numer magistrali oraz identyfikator urządzenia na standardowe wyjście (czyli konsolę). Te zwracane wartości są przechwytywane i używane do stworzenia ścieżki w systemie udev dla urządzenia USB. Dla przykładu, urządzenie 3 na szynie 2 miałoby ścieżkę /dev/bus/usb/002/003.
- Nazwa dysku jest wyciągana z /dev. W przykładowym skrypcie używamy wieloznacznego porównania z /dev/sd[a-z] i wyszukujemy wszystkie urządzenia pasujące do tego wzorca – /dev/sda, /dev/sdb, /dev/sdc itd. Taka operacja znajdzie wszystkie dyski w systemie, włącznie z dyskami twardymi i pamięciami USB.
- Kompletną niskopoziomową ścieżkę pliku napędu dyskowego można znaleźć za pomocą polecenia udevadm info –q path –n /dev/sdX. Zwrócona ścieżka pliku powinna się zaczynać od niskopoziomowej ścieżki urządzenia USB, jeśli dany dysk odpowiada urządzeniu USB, które znaleźliśmy.
- Na zakończenie procesu, wartość zwracana przez komendę mount jest używana do określenia czy nazwa napędu dyskowego sprawdzana w punkcie 2 jest zamontowana w systemie plików Linuksa. W ten sposób mamy ścieżkę urządzenia USB pracującego w trybie ISP i dostęp do pliku firmware.bin.
Sprawdzanie Code Read Protection (CRP)
Mikrokontroler LPC1300 podłączony przez USB w trybie ISP ma jako etykietę dysku (widoczną w systemie hosta) opis trybu CRP w jakim pracuje. Solidny projekt wykorzystujący programowanie pamięci Flash przez USB powinien sprawdzać etykietę dysku, aby mieć pewność, że ochrona przed zapisem nie jest włączona. W Linuksach, etykiety dysków systemu plików FAT można odczytać za pomocą pakietu mtools. Nie jest to jednak opcja zalecana, gdyż wymaga uprawnień administratora. Innym sposobem odczytania etykiet jest użycie komendy mount –l, o ile jest ona obsługiwana przez posiadaną przez użytkownika wersję narzędzia mount. Zwraca ona listę wszystkich zamontowanych systemów plików i ich etykiet. Na maszynach Macowych i Windowsowych, etykiety dysków są dostępne odpowiednio w: katalogu DiscDescription i obiekcie Volume znajdującym się w WMI (Windows Managment Instrumentation).
Jeśli włączone jest CRP1 lub CRP2, plik firmware.bin na urządzeniu USB pracującym w trybie ISP musi zostać usunięty przed wpisaniem nowego firmware’u, aby wyłączyć ochronę kodu. Po usunięciu firmware.bin, urządzenie należy zrestartować, odłączając zasilanie, aby ustawienia CRP uległy zmianie i aktualizacja była możliwa. Jeśli włączony jest tryb CRP3, urządzenia nie da się „wyczyścić” i oprogramowania nie można aktualizować.