logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[AVR][C] - własny bootloader

mirekk36 19 Paź 2008 14:12 6107 8
  • #1 5646961
    mirekk36
    Poziom 42  
    Witam,

    Chciałbym napisać sobie własny prościutki mały bootloader, który zapisywałby tylko pamięć Flash (bez eeprom). Oparty o wczytywanie danych przez RS232. Oczywiście chciałbym to napisać w C. Program miałby działać ze stałą prędkością np 9600.

    ale na razie mam teoretyczne pytanie czy dobrze rozumuję jak do tego podejść i czy już na tym etapie nie popełniam jakichś kardynalnych błędów, które mi to utrudnią bądź uniemożliwią.

    1. Wiem, że program bootloadera trzeba skompilować do odpowiedniego obszaru pamięci (można tego dokonać zdaje się za pomocą __attribute)

    2. program posiada funkcje odczytu i zapisu z/do RS232 ale nie działające na przerwaniach tylko oczekujące na znak.

    3. Po restarcie sprawdzam czy jakiś tam pin ma wartość 0 co ma oznaczać, że powinien zadziałać bootloader (oczywiście z uwzględnieniem drgańs tyków)

    4. jeśli nie to odpalam program od adresu 0 (czyli normalną zawartość Flash) a jeśli tak to:

    5. wczytuję z RS232 zawartość bufora strony do zapisania w pamięci Flash, sprawdzam czy to przypadkiem nie ostatnia już strona, dokonuję jego zapisu SPM, wysyłam ew potwierdzenie do RS232 że gotowe i powtarzam ten cykl aż do otrzymania ostatniej strony.

    6. po wszystkim robię skok - jmp 0

    Oczywiście pominąłem tu, że można byłoby jeszcze rozbudować to o jakąś kontrolę prawidłowości przesyłanych danych. Pomijam też tutaj sprawę oprogramowania drugiej strony np na PC - bo z tym to już sobie najspokojniej w świecie poradzę.

    Czy taki bootloader (narazie teoretyczny) będzie w stanie bez problemu zadziałać wg was ? czy to się uda? .....

    czy też o czymś w tym ogólnym algorytmie nie pomyślałem ?

    .... na koniec dodam, że bardzo zależy mi na zrobieniu takiego bootloadera dla małego procka jak ATtiny2313

    może jakieś sugestie? podpowiedzi? albo ciekawe źródła informacji w necie na które mi nie udało się trafić? - proszę
  • Pomocny post
    #2 5647887
    krzemowy
    Poziom 19  
    Hm... jak pisałem bootloader do swojej centralki to nie używałem __attribute do przesunięcia przestrzeni adresowej tylko zmieniłem w ustawieniach AVR Studio zakres dostępnej przestrzeni pamięci programu na zakres przewidziany dla bootloadera(różnie dla różnych procków). Było o tym pisane na forum, o ile dobrze pamiętam(proszę mnie poprawić jeżeli bredzę) zaatakowanie samej funkcji main() atrybutem powoduje przesunięcie tylko i wyłącznie jej samej w zadany obszar, a pozostałe funkcje kompilator i linker wkłada tam gdzie mu pasuje(tzn. poczynając od początku obszaru pamięci programu zadeklarowanego w ustawieniach makefile - jeżeli się korzysta z AVR Studio i avr-gcc to makefile jest tworzony na podstawie konfiguracji projektu w AVR Studio). Można tak zamieszać w ustawieniach linkera że całość programu ląduje w przestrzeni programu przewidzianej dla bootloadera ale mnie to przerosło ;)
    Reszta założeń wg mnie dobra, jeżeli idzie o sam zapis programu do pamięci to oparłem się na przykładzie z helpa avr-gcc i zadziałało od razu. Też używam prędkości 9600 bodów, tyle że po drodze mam jeszcze FIFO bazujące na przykładzie podanym przez upanie żeby nie mieć problemu z traceniem odbieranych danych w momencie zapisu flashu. Sprawę skomplikowałem sobie upierając się na wysyłanie danych w formacie Intel HEX ale udało się to zrobić i ładnie to działa tyle że cały bootloader nie jest mały ;) Zabiera coś około 3 kB pamięci.
  • Pomocny post
    #3 5648012
    BoskiDialer
    Poziom 34  
    Bootloader jeśli jest prosty, potrafi też zajmować o wiele mniej. U mnie w jednym z projektów procesor podrzędny jest przeprogramowywany przez procesor główny, protokół jest więc bardzo prosty (zakładam, że błędy transmisji nie występują), sam bootloader zajmuje 358 bajtów (załącznik: źródła, 5 plików, m8).

    Co do pierwszego postu:
    ad 1/ Przy linkowaniu podaje się pod jakim adresem całość ma zostać umieszczona - nadpisuje się początek sekcji text.
    ad 2/ tiny2313 nie ma możliwości przełączenia początku tablicy wektorów przerwań do sekcji bootloadera. Dla przykładu m8 i większe mają możliwość przeniesienia wektorów do bootloadera (bity IVSEL i IVCE w rejestrze GICR). W tych większych bootloader może korzystać z przerwań bez żadnych problemów.
    ad 3/ Warunki załączenia bootloadera są dowolne, sprawdzane w bootloaderze. Ja bym się nawet nie zajmował eliminowaniem drgań styków, gdyż to są dodatkowe cenne bajty a chodzi tylko o jednorazowe sprawdzenie stanu. Przycisk może być naciśnięty przed a puszczony po bootloaderze, więc eliminacja drgań jest zbędna.
    ad 6/ Chciało by się napisać "jmp 0" - już się na tym wyłożyłem. Linker aktualizuje później wszystkie takie skoki, przez co "jmp 0" będzie skokiem do pierwszej instrukcji modułu. Można podać instrukcję w bajtach a można też skorzystać z instrukcji ijmp przy wyzerowanym wskaźniku Z (patrz załącznik).
    Załączniki:
  • #4 5648127
    mirekk36
    Poziom 42  
    Dziękuję bardzo za takie ciekawe odpowiedzi, a szczególnie koledze BoskiDialer za dołączenie swojego bootloadera. Będzie mi to bardzo ale to bardzo pomocne przy napisaniu swojej wersji. Na elektrodzie wprawdzie sporo jest tematów związanych z bootloaderem ale nigdzie nie natknąłem się na jakiś przykład, żeby wiedzieć jak zacząć tym bardziej, że ja dopiero raczkuję w C

    Dodano po 2 [godziny] 7 [minuty]:

    BoskiDialer -> widzę, że jesteś niezłym magikiem bo twoje makefile jest w ogóle nie podobne do tego generowanego przez AVRStudio. Ale spróbowałem tak z ręki skompilować ten twój bootloader:

    make bootloader

    i niestety dostaję błąd:
    makefile:28: *** missing separator. Stop

    hmmm przy mojej obecnej wiedzy n/t makefile i kombinacji parameto-ptaszków jak dla mnie ;) nie jestem w stanie sobie w ogóle poradzić.

    no chyba, że źle próbuję to skompilować może trzeba jeszcze jakieś parametry dodatkowe podać? czy jak?

    (z kolei przy próbach zahaszowania linijki 28 w tym makefile - coś ruszyło dalej ale też wywaliło błędy, m.inn take:

    bootloader.c: error: 'URSEL' undeclared (first use in this function)

    ) .... jeśli chciałoby ci się jeszcze to sprawdzić u siebie to byłbym wdzięczny
  • #5 5649088
    zumek
    Poziom 39  
    BoskiDialer napisał:
    ... sam bootloader zajmuje 358 bajtów (załącznik: źródła, 5 plików, m8).

    A po co Ci tablica wektorów , jeśli nie korzystasz z przerwań :?:
    Po jej wywaleniu , kod skurczył się do 264 B.

    Piotrek
  • Pomocny post
    #6 5649463
    Dr.Vee
    VIP Zasłużony dla elektroda
    mirekk36 napisał:
    BoskiDialer -> widzę, że jesteś niezłym magikiem bo twoje makefile jest w ogóle nie podobne do tego generowanego przez AVRStudio. Ale spróbowałem tak z ręki skompilować ten twój bootloader:

    make bootloader

    i niestety dostaję błąd:
    makefile:28: *** missing separator. Stop


    Czy magik to nie wiem, ale ten Makefile nie zadziała. Na początku linii 28 masz spacje zamiast tabulacji, a make bardzo tego nie lubi ;)

    W załączeniu Makefile z pomniejszymi poprawkami.

    zumek napisał:
    A po co Ci tablica wektorów , jeśli nie korzystasz z przerwań :?:
    Po jej wywaleniu , kod skurczył się do 264 B.


    A jak sie wywali wszystko (-nostartfiles -nodefaultlibs) to zostaje tylko 248 bajtów ;) Jeśli się przed skokiem do bootloadera wyzeruje r1 i ustawi stack pointer, to śmiało można tak zrobić.

    Pozdrawiam,
    Dr.Vee
  • Pomocny post
    #7 5649512
    BoskiDialer
    Poziom 34  
    mirekk36 napisał:
    widzę, że jesteś niezłym magikiem bo twoje makefile jest w ogóle nie podobne do tego generowanego przez AVRStudio.
    Ponieważ nie korzystam z AVRStudio.
    mirekk36 napisał:
    Ale spróbowałem tak z ręki skompilować ten twój bootloader:

    make bootloader
    zazwyczaj kompiluje się przez samo "make", tutaj przez "make all"
    mirekk36 napisał:
    i niestety dostaję błąd:
    makefile:28: *** missing separator. Stop
    Faktycznie pojawiła się tam spacja, jednak jej nie zauważyłem, gdyż u mnie make się niczego nie czepiał. Nie powinno jej tam być.
    zumek napisał:
    A po co Ci tablica wektorów, jeśli nie korzystasz z przerwań? Po jej wywaleniu, kod skurczył się do 264 B.
    Nie chciało mi się już szukać oszczędności. I tak bootloader zajmuje obszar 512 bajtów, chociaż gdyby go jeszcze zoptymalizować (łącznie z wyrzuceniem tablicy wektorów), to zmieścił by się w 256 bajtach.
  • #8 5649645
    mirekk36
    Poziom 42  
    Teraz wszystko zadziałało jak powinno - wielkie dzięki.

    Ale jakby ktoś mi jeszcze w tej nawałnicy jak dla mnie nowych informacji zdadził tajemnicę (to już tak z czystej ciekawości) jak można wywalić z tego projektu tablicę wektorów to byłbym b.wdzięczny , znowu coś więcej by mi się rozjaśniło. Czy należy to gdzieś wyłączyć "grzebiąc" w io.h ???

    przy okazji jeszcze jedno pytanko:

    Dr.Vee napisał:
    Cytat:
    "A jak sie wywali wszystko (-nostartfiles -nodefaultlibs) to zostaje tylko 248 bajtów Jeśli się przed skokiem do bootloadera wyzeruje r1 i ustawi stack pointer, to śmiało można tak zrobić. "


    1. gdzie takie parametry jak te powyżej w nawiasach - się podaje w makefile?
    2. napisałeś, że "przed skokiem do bootloadera" a nie chodziło może o to, że "przed wyjściem z bootloadera" ?? gdy już chcemy odpalić właściwy program?


    .... no i jeszcze jedno na koniec - może ktoś coś mi podpowie odnośnie zastosowania bootloadera dla Attiny2313 (taki miałem pomysł) ale patrzę sobie w PDF'a i jakoś nie mogę tam zobaczyć jednak w mapce pamięci miejsca na bootloader i fusebitów z tym związanych ;) więc może dla ATtiny2313 to nie jest w ogóle możliwe???
  • Pomocny post
    #9 5649693
    Dr.Vee
    VIP Zasłużony dla elektroda
    Witam,

    Opcje te można dodać podczas "linkowania" programu, czyli np:
    $(MF).elf: $(MF).o $(OBJECTS)
            $(CC) -Wl,-Ttext,0x1e00 -nostartfiles -nodefaultlibs -o $(MF).elf $(MF).o $(OBJECTS)
    
    .

    W większych AVRach możesz ustawić wektor resetu na bootloader, i wtedy musi być tam osobna inicjalizacja stosu, rejestru R1 itd.

    W przypadku attiny2313 nie ma możliwości zmiany wektora resetu, więc program główny będzie musiał sam "skoczyć do bootloadera". Jeśli wykonasz to po inicjalizacji SREG i R1, to bootloader może być ogołocony z tej inicjalizacji.

    Aha, po programowaniu do aplikacji najlepiej "skakać" przez timeout watchdoga.

    Pozdrawiam,
    Dr.Vee
REKLAMA