2012-02-16 12 views
5

Najpierw trochę tła. Gdy oprogramowanie układowe z jakiegokolwiek powodu ulegnie awarii (np. Przepełnienie stosu, uszkodzony wskaźnik funkcyjny ...) może się zdarzyć, że skacze gdzieś i rozpoczyna wykonywanie jakiegoś kodu. To prędzej czy później spowoduje reset watchdoga. MCU zresetuje się i wrócimy na właściwe tory. Chyba że ...Unikanie przypadkowego nadpisania oprogramowania układowego

Co powiesz na pytanie, kiedy mamy kod, który zapisuje do flashowania (np. Bootloader)? Teraz może się zdarzyć, że przypadkowo przejdziemy bezpośrednio do kodu zapisu flash - pomijając wszystkie kontrole. Zanim zadzwoni strażnik, skończy się uszkodzonym oprogramowaniem. Właśnie to mi się przydarzyło.

Teraz niektórzy mogą powiedzieć - naprawić błąd root, który spowodował, że nawet wskoczyliśmy do pisania kodu. Cóż, kiedy się rozwijasz, ciągle zmieniasz kod. Nawet jeśli w tej chwili nie ma takiego błędu, może być jutro. Poza tym żaden kod nie jest wolny od błędów - a przynajmniej nie mój.

Więc teraz robię coś w rodzaju sprawdzania krzyżowego. Mam zmienną o nazwie "wen", którą ustawiłem na wartość 0xa5 przed zwykłymi sprawdzeniami (np. Sprawdź, czy cel jest prawidłowy). Następnie tuż przed wykonaniem właściwego kasowania lub zapisu sprawdzam, czy 'wen' jest rzeczywiście ustawiony na 0xa5. W przeciwnym razie oznacza to, że jakoś przypadkowo wskoczyliśmy do kodu pisania. Po pomyślnym zapisaniu "wen" zostaje wyczyszczone. Zrobiłem to w C i zadziałało dobrze. Ale nadal istnieje niewielka teoretyczna szansa, że ​​doszłoby do korupcji, ponieważ istnieje kilka instrukcji od tej ostatecznej kontroli "wen" aż do zapisu do rejestru SPMCR.

Teraz chcę to poprawić, umieszczając tę ​​kontrolę w zestawie, między poleceniem write to SPMCR a instrukcją SPM.

__asm__ __volatile__ 
( 
    "lds __zero_reg__, %0\n\t" 
    "out %1, %2\n\t" 
    "ldi r25, %3\n\t" 
    "add __zero_reg__, r25\n\t" 
    "brne spm_fail\n\t" 
    "spm\n\t" 
    "rjmp spm_done\n\t" 
    "spm_fail: clr __zero_reg__\n\t" 
    "call __assert\n\t" 
    "spm_done:" 
    : 
    : "i" ((uint16_t)(&wen)), 
     "I" (_SFR_IO_ADDR(__SPM_REG)), 
     "r" ((uint8_t)(__BOOT_PAGE_ERASE)), 
     "M" ((uint8_t)(-ACK)), 
     "z" ((uint16_t)(adr)) 
    : "r25" 
); 

Nie próbowałem jeszcze kodu, zrobię to jutro. Czy widzisz jakieś problemy? W jaki sposób/rozwiążesz taki problem?

Odpowiedz

3

Jedną z technik, które widziałem, jest upewnienie się, że bajty bezpośrednio przed procedurami zapisu flash spowodują pewien czas oczekiwania watchdoga lub zresetować procesor. W ten sposób nie jest możliwe wykonanie losowych danych prowadzących do funkcji zapisu Flash i po prostu "wpadnięcie" w tę funkcję.

Przed resetem może być konieczne wykonanie NOP, aby zapewnić prawidłowe interpretowanie instrukcji.

Twoja technika sprawdzania, czy funkcja działa od początku, wygląda dobrze, zakładając, że wyczyścisz zmienną wen po wykonaniu zapisu.

+0

Tak, wen jest wyczyszczone po pomyślnym zapisaniu. To wywołanie __assert faktycznie wyzwala resetowanie watchdoga (dodatkowo rejestruje pewne informacje o tym, co go wyzwoliło). Cieszę się, że ludzie używają takich metod :) – Stefan

2

Nie jestem pewien, dlaczego musisz mieć możliwość zapisu do flashowania w bootloaderze. Nasz program ładujący działa, ponieważ może aktualizować program aplikacji przez port szeregowy. Eliminujemy więc możliwość nieumyślnych zapisów, upewniając się, że program ładujący nie zawiera kodu piszącego do flashowania. Ten kod jest pobierany jest nagłówkiem w tym samym pakiecie, który zawiera obraz do zapisania. Obraz pokładowy zawiera sumę kontrolną zapisanego programowania i weryfikuje ją przed uruchomieniem.

Jeśli piszesz rzeczy, które są generowane wewnętrznie, to chciałbym spojrzeć na powiązane ze sprzętem blokady. Zezwalaj na zapisy tylko wtedy, gdy wcześniej ustawiłeś określony dyskretny pin wyjściowy na ON. Aby odpowiedzieć na pytanie "co, jeśli IP przeskoczy kontrolę"? możesz to zrobić na 2 części. Najpierw ustaw kilka krytycznych zmiennych dla algorytmu. (adres do zapisania na przykład - zachowaj, że zainicjalizowano pamięć nieważną, i ustaw ją poprawnie w oddzielnym wywołaniu przed zapisaniem, następnie wykonaj funkcję sprawdzania blokady HW, wykonaj jeden z kroków włączania, lub w odpowiedzi na timer, coś, co jest mało prawdopodobne, aby trafić w prawidłowej kolejności, jeśli masz nieuczciwe IP.

Jeśli twój adres IP naprawdę może skakać gdziekolwiek, może być niemożliwe, aby zapobiec przypadkowemu zapisowi. Najlepsze, na co możesz mieć nadzieję, to to, że zapewniasz jedyną dostępną ścieżkę, a także wszystko, co jest potrzebne do pomyślnego napisania.

+0

Robię to samo (aktualizacja przez UART). Istnieje kod zapisu w aplikacji i bootloaderze. Mogą więc wzajemnie się aktualizować, a także przechować pewną konfigurację w pamięci flash. Nie wiem, co masz uC, ale ten, który mam, nie może wykonać kodu z pamięci RAM, więc przesłanie kodu do pisania nie jest opcją. Właściwie używam podobnej procedury, jak opisano w przypadku blokady HW. To właśnie próbowałem wyjaśnić, kiedy ustawiłem pytanie ... wygląda na to, że zrobiłem złą robotę :) – Stefan

+0

@Stefan: uważaj z aktualizowaniem programu ładującego z aplikacji. Co dzieje się z utratą mocy między kasowaniem a zapisem? Ups, twój bootloader zniknął, a ty zamurowałeś swoje urządzenie. Jeden z projektów Freescale HCS08, program ładujący faktycznie ustawia rejestry CPU, aby zabezpieczyć je przed nadpisaniem, a aplikacja nie może zapisywać na tych stronach w pamięci flash. Bądź bezpieczny. – tomlogic

+0

@tomlogic: Mam 2 kody do wpisania - w aplikacji iw bootloaderze - i mogą się wzajemnie aktualizować. Domyślnie uC budzi się w kodzie aplikacji. Jeśli nie zaktualizuję bootloadera, nadal budzę aplikację i mogę spróbować ponownie. A bootloader wykorzystuje sztuczkę. Zapisuje kod aplikacji od najwyższej strony do najniższej. Zanim zapisze pierwszą (która jest rzeczywiście najwyższą) stronę, zapisuje "skok do bootloadera" na stronę 0. Teraz jedyną troską jest to, że nie powinno się nie napisać ostatniej strony (strona 0). Tak więc szanse są bardzo małe, aby zakończyć się nieodwracalnym flash. – Stefan

Powiązane problemy