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.

  1. 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.
  2. 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.
  3. 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.
  4. 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ć.

Do pobrania

O autorze