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

Bootloader + przerwania + AVR-GCC -juz dziala !

erfro 31 Lip 2009 13:10 3759 23
  • #1 6842294
    erfro
    Poziom 15  
    Mam prośbę, prosze o podpowiedź w nastepującej kwesti:

    Mam jakis program główny oraz pisze teraz booloadera w jednym projekcie (kompilowane jednoczesnie). Bootloader tylko na potrzeby tego jednego programu. W jakims osobnym pliku np. Boot.c pisze funkcje np
    void firmware (void) BOOTLOADER_SECTION;
    a jak w tym projekcie dopisac teraz przerwanie od UART1 np: ISR(USART1_RX_vect) aby wektor byl umieszczony w sekcji .bootloader
    Dodam ze w programie głównym uzywam juz tego przerwania ISR(USART1_RX_vect), a nie wiem jak rozdzielic te dwa przerwania (konflikt tych samych nazw) oraz zeby linker umiescil ten drugi wektor ale od adresu poczatku bootloadera??
    Projekt pisany w AVR-GCC 4.13 + ATmega128
  • #2 6843574
    MarcinKawka
    Poziom 12  
    Musisz zrobić dwie rzeczy:
    1. Poinformować linker że ma tak składać kod aby wektory przerwań wylądowały na początku sekcji bootloadera. Robi się to skryptem linkera załączanym przez -T przy linkowaniu.

    2. Sprawić by atmega przy przerwaniach nie szukała wektorów na samym początku. Do tego służy instrukcja na samym początku main'a()
    
    asm volatile("	ldi r16, (1<<0)\n\t"
    		"out 0x035, r16\n\t"
    		"ldi r16, (1<<1)\n\t"
    		"out 0x35,r16 \n\t"::);
    

    Niestety już nie pamietam co ta wstawka robi, korzystałem z niej dwa lata temu i pamietam że działała ale oczywiście zapomniałem okomentować kod ;/
  • #3 6844013
    BoskiDialer
    Poziom 34  
    Najłatwiej kod bootloadera pisać jako osobny projekt - wtedy nie pojawiają się żadne konflikty, a docelowo i tak podczas aktualizowania nie wysyła sie już bootloadera.

    MarcinKawka: Twój kod wykonuje dwa odwołania do MCUCR w celu zmiany lokalizacji tablicy wektorów przerwań. Wstawka zawiera błąd, ponieważ nie informuje kompilatora o zniszczeniu zawartości rejestru r16.

    Na początku bootloadera należy przesunąć tablicę wektorów przerwań na sekcję bootloadera:
    /* Enable change of interrupt vectors */
    MCUCR = (1<<IVCE);
    /* Move interrupts to boot flash section */
    MCUCR = (1<<IVSEL);

    Pod koniec natomiast należy przesunąć tablicę wektorów przerwań do obszaru programu:
    MCUCR = (1<<IVCE);
    MCUCR = 0;
  • #4 6845775
    mirekk36
    Poziom 42  
    erfro --> w tym temacie:

    https://www.elektroda.pl/rtvforum/topic1343484.html

    masz podane śliczne przykłady samych bootloaderów - wprawdzie nie używają przerwań do UARTA - ale można się i bez nich obejść spokojnie aby zaprogramować procka

    popatrz sobie jak się to rozwija w tym temacie powyżej i jakie fajne modyfikacje wprowadza kolega master_pablo - dzięki nim jedna z ostatnich wersji powinna działać na dowolnym procku AVR - świetna sprawa - polecam
  • #5 6850956
    erfro
    Poziom 15  
    Problem polega na tym ze musze uzyc przerwan od UARTa bo plik z nowym firmwarem bedzie wyslany jednym strumieniem, wiec w czasie programowania strony w RWW program musi magazynowac nowe dane do bufora.
    Odnosnie jednoczesnej kompilacji programu glownego i bootloadera to przemyslalem ze macie racje. Mimo ze byloby mi tak wygodniej pisac wszystko w jednym projekcie, to jednak kompilator sumowalby wszystkie zasoby pamieci zadeklarowanych w bootloaderze i programie glownym, a to jest w tym przypadku niekorzystne.
    Dlatego napisze tego bootloadera jako osobny projekt.
    Powiedzcie mi tylko, wowczas pisze go normalnie jak kazdy inny, ale uzywajac atrybutow BOOTLOADER SECTION czy nie?. Bo jesli tak, to sprawa przerwania znowu pozostaje otwarta, jak przesunac adres przerwania do sekcji boot.
    Jesli jednak nie to jak przesunac calosc programu podczas kompilacji/linkowania do sekcji bootloadera?
  • #6 6851077
    BoskiDialer
    Poziom 34  
    erfro napisał:
    Powiedzcie mi tylko, wowczas pisze go normalnie jak kazdy inny, ale uzywajac atrybutow BOOTLOADER SECTION czy nie?. Bo jesli tak, to sprawa przerwania znowu pozostaje otwarta, jak przesunac adres przerwania do sekcji boot.
    Jesli jednak nie to jak przesunac calosc programu podczas kompilacji/linkowania do sekcji bootloadera?

    Jedyna różnica jaka się pojawia, to przekazanie do linkera adresu pod jakim ma zostać umieszczony program (wycinek z mojego Makefile: "$(CC) -Wl,-Ttext,0x1e00 -o $(MF).elf $(MF).o $(OBJECTS)"). Kod wynikowy musi być zrzucony do pliku hex, gdyż do pliku bin nie jest wstawiane wypełnienie przesuwające pierwszą instrukcję na żądany adres.

    Zobacz też:
    [AVR][C] - własny bootloader
    AVR Boot Loader - który ładnie i szybko działa
  • #7 6851162
    erfro
    Poziom 15  
    ok, przetrenuje to.
    Ja co prawda nie tworze makefile bo avr-gcc 4.13 juz to robi automatycznie, ale moge dodac we wlasciwosciach Project/Memory Setting ustawienie sekcji Ttext na odpowiednio przesuniety adres, dobrze mysle ??
  • #8 6851181
    mirekk36
    Poziom 42  
    erfro napisał:
    Problem polega na tym ze musze uzyc przerwan od UARTa bo plik z nowym firmwarem bedzie wyslany jednym strumieniem, wiec w czasie programowania strony w RWW program musi magazynowac nowe dane do bufora.


    nie upieram się ani nie przekonuję cię na siłę, że musisz zrezygnować z przerwań w bootloaderze ;) .... ale jakbyś się chociaż raz przyjrzał jednemu z tych bootloaderów w polecanych linkach to zobaczyłbyś, że pomimo to iż nie są używane przerwania od UART to tak samo w trakcie programowania dane magazynowane są do bufora ;) - no ale jak wolisz
  • #9 6851281
    erfro
    Poziom 15  
    wlasnie je przegladam, tak ze za chwile bede wiedzial juz cos wiecej.
    Te bootloadery ktore przegladalem do tej pory wspolpracowaly z dedykowanym programem ladujacym z PC gdzie co okreslona porcje bajtoe(strone zapisu) generowana byla pauza ok 100ms ! , tak ze bootloader mogl czekac. Ale zaraz przejrze te proponowane wyzej.
    Ja natomiast upgrade bede robil po gprs (dane z uarta) i beda slane jednym strumieniem, nie ma mowy o XON/XOF i dlatego pomylalem o przerwaniu i buforowaniu kolejnych bajtow podczas zapisu strony (4ms)
    Byc moze to nie jest potrzebne, przyjrze sie temu.

    Jeszcze jedno pytanie, pliki z upgrade'm slecie w HAX (i konwersja w locie) czy BIN ??
  • #10 6854907
    erfro
    Poziom 15  
    mirekk36 ->
    przejrzalem te bootloadery i niestety nie jest to to czego potrzebuje. Fakt w trakcie zapisu strony (ktora jest de facto robiona w tle, ale jest to sprzxetowa cecha AVR) jest zapisywanie danych do bufora. Problem polega na tym ze dane wysylane sa paczkami (stronami) i program PCtowy czeka na znak"+" przed wyslaniem kolejnej paczki. Nowy soft jest ladowany do bufora w pewnych odstepach czasu, poniewaz wystepuje interakcja pomiedzy bootloaderem (zapis strony i wyslanie +) a programem PC.
    U mni enatomiast bede wysylal caly plik z firmware ok 64kB jednym ciagiem i musze zastosowac przerwania bo nie mam zadnej interakcji, musze to buforowac.
    Tak wiec koledzy/kolezanki jak ustawic przerwanie ISR(UART1_RX_vect) na sekcje bootloadera ?? Mozna to zrobic atrybutem BOOTLOADER SECTION ??
  • #11 6855094
    mirekk36
    Poziom 42  
    ;) sorki, że się uśmiecham - no ale może ja czegoś nie wiem - albo może ty nie wiesz , bo:

    1. skąd weźmiesz taki bufor 64kB na przesłanie firmware jednym ciągiem ??? (no chyba, że zastosujesz zewnątrzną pamięć do procka - czy tak zamierzasz zrobić? )

    jeśli zewn. pamięć - no to rozumiem - wtedy rzeczywiście przydałoby się skorzystać z przerwań a i bootloader będzie troszkę większy. Ja nie włączałem tych przerwań - ale zdaje się, że jest ten mechanizm opisany w PDF'ie dokłanie w sekcji o Bootloaderze.
  • #12 6855175
    erfro
    Poziom 15  
    mirekk36 ->
    no to juz Ci tlumacze,
    nie potrzebuje takiego buforu 64kB (128kB), a to dlatego ze dane przesylane beda z predkoscia 9600bps, co daje ok 1ms/bajt. Jedna strona w ATmega128 to 128 slow (256 bajtow.) Dane bede magazynowal w dwupoziomowym buforze 2x256 bajtow. Po zmagazynowaniu pierwszego poziomu zrobie zapis strony (ok 4-5ms w tle oczywiscie), a kolejne bajty beda magazynowane w drugim poziomie, podczas operacji wypelniania bufora itp. Tak ze odbior danych bedzie robiony w tle. Chodzi o to ze nie moge zgubic zadnego znaku podczas operacji przygotowania strony do zapisu (testy _busy).
    Pamietaj, ze bufor stronicowy pamieci flash ni emoze byc zapisywany jesli w tle zachodzi programowanie pamieci, ktore trwa tych kilka ms. Wiec w tym przypadku zbubulbym kikla bajtow, gdybym nie buforowal odbioru znakow, a moge to zrobic tylko poprzez przerwanie.
    Rozumiesz teraz? Jesli masz jakies watpliwosci, to sprobuje to wytlumaczyc lepiej.
  • #13 6855208
    BoskiDialer
    Poziom 34  
    erfro: no i w czym problem? Przeniesienie wektorów przerwań do sekcji bootloadera masz w trzecim poście aktualnego tematu, załączenie przerwań przez sei(). Robisz jeden bufor FIFO o długości 1KB (można mniej) w oparciu o tablicę i dwa kursory, w przerwaniu od usartu zapisujesz bajt do buforu FIFO a w pętli głównej sprawdzasz, jeśli w buforze jest cała strona to zapisujesz do pamięci flash - nawet nie trzeba się męczyć z wielopoziomowym buforem.
  • #14 6855258
    erfro
    Poziom 15  
    BoskiDialer ->
    dokladnie robie tak jak piszesz, ja tylko koledze opisywalem na czym to polega.
    Problem jest innego typu, jak przenies wektory przerwan do BLS to wiem (3 post tak jak pisales), nie wiem tylko jak poinformowc kompilator zeby wektor od UART_RX umiescil w sekcji .bootloader

    bo procedurke do obslugi bootloadera pisze np tak:

    void BOOTLOADER_SECTION Bootloader(void) {

    }
    wtedy kod wynikowy umieszczny jest w miejscu pod 0x1E000 (takie ustawienie w skrypcie linkera dla sekcji .bootloader)

    a zeby umiescic wektor przerwania rowniez w sekcji .bootloader to moge zrobic tak:?

    BOOTLOADER_SECTION ISR(UART1_RX_vect) {

    }

    bo normalnie umiescilby mi w sekcji .text czyli od adresu 0x003C

    i tego wlasnie nie wiem,
    wiec prosze Cie moze wyjasnilbys mi to?
  • #15 6855349
    BoskiDialer
    Poziom 34  
    Nie robisz kompletnie nic oprócz wskazania linkerowi pod jakim adresem ma być zlokalizowany kod wynikowy. Tablica wektorów przerwań która pierwotnie była pod adresem 0 znajdzie się pod adresem przekazanym linkerowi - -Wl,-Ttext,0x1e00 spowoduje, że cała sekcja .text (razem z tablicą wektorów) zostanie przeniesiona pod adres bootloadera - właśnie z tego względu trzeba wskazać procesorowi że tablica wektorów jest pod innym adresem - aby nie używał tablicy wektorów od właściwego programu.
  • #16 6855396
    erfro
    Poziom 15  
    Acha, czyli
    przekazuje linkerowi - -Wl,-Ttext,0x1e00,
    wtedy wlasciwa funkcja bootloadera jest funkcja main() a przerwanie pisze normalnie. Z tym sie zdadzam, jesli dobrze zrozumialem.

    Powiedz mi tylko po co w AVR-gcc jest zdefinowane BOOTLOADER_SECTION ?
    czy wtedy moge uzywac tych wszystkich funkcji z biblioteki boot.h ??
  • #17 6855447
    BoskiDialer
    Poziom 34  
    Z funkcji z boot.h można korzystać i bez BOOTLOADER_SECTION. Nie wiem konkretnie po co to jest. Używając google znalazłem przykłady w których funkcja do programowania pamięci flash jest przesunięta do sekcji bootloadera aby nie została skasowana razem z przeprogramowywaną częścią pamięci - czyli to właściwy program inicjuje zapis. Można w ten sposób skorzystać z RWW. Jakkolwiek zawsze można wejść do bootloadera wykonując skok pod adres bootloadera.

    Linkerowi przekazujesz samo -Wl,-Ttext,0x1e00. Myślnik poprzedzający to separator zdań składowych w mojej wypowiedzi.
  • #18 6855536
    erfro
    Poziom 15  
    Ja robilem testy i ustawilem atrybut BOOTLOADER_SECTION do funkcji ktora byla odpowiedzialna za ladowanie programu. Funkcja ta byla umieszczona w jednym projekcie z programem wlasciwym tak ze po poinformowaniu linkera ze .bootloader jest od 0x1E000 ladnie ladowala od tego adresu. Sluzy to wiec do tego, jak chcesz pisac bootloadera w jednym projekcie. Zastanawialem sie wiec czy moge to zrobic z ISR(vector) aby poprzedzic ta funkcje przerwania tym BOOTLOADER_SECTION i pisac w jednym projekcie, wtedy nie trzeaby bylo tworzyc nowego projektu dla bootloadera z przesunieciem Ttext na 0x1E000 jak pisalismy wyzej. (chodzi o przesuniecie przerwania do wektora BLS)
    Problem to tylko taki ze kod wynikowy tak napisanego programu zawiera rowniez bootloadera, ktory przy zdalnej aktualizacji i tak trzebaby bylo usuwac, chyba ze aktualizowalby rowniez sam siebie, co jest mozliwe.
  • #19 6905319
    erfro
    Poziom 15  
    Bootloadera napisalem jako osobny projekt. Wszystko dziala idealnie. Skompilowalem go z ustawieniem .text 0xF000.

    Mam teraz pytanie, jak ustawic avr-gcc zeby do biezacego (jakiegos tam) projektu linker dolaczyl mi plik Boot.hex (ktory zaczyna sie od adresu jak wiadomo 0xF000). Do tej pory skladalem wyjsciowego hexa w innym programie i wgrywalem do procka, ale wolalbym to robic automatycznie.
    Np. pisze sobie nowy projekt i chcialbym zeby zawsze linker dolaczyl mi Boot.hex Adresy sie nie beda nachodzic bo projekt nie ma takiej objetosci zeby zamazac Boot.hex
  • #20 6905511
    BoskiDialer
    Poziom 34  
    erfro: Nie łatwiej wgrać bootloader i za jego pomocą wgrać pierwszy firmware? Nie trzeba jednego z drugim łączyć przed wgraniem. Właściwy program nie musi posiadać kodu bootloadera przez którego jest wgrywany - bootloader zapisuje (zazwyczaj) maksymalnie całą pamięć flash aż do początku obszaru bootloadera pomijając wszystko co jest dalej. Ogólnie z początku na procesor wgrywasz kod bootloadera a dalej zapominasz o nim, tylko używasz programu do załadowania właściwego kodu przez bootloader.
  • #21 6928271
    erfro
    Poziom 15  
    No nie do konca,
    bo za pierwszysm razem do sterownika chcialem wgrac program glowny i bootloader za pomoca programatora. Program glowny i bootloader pisane sa jako osobne projekty, ale zeby wgrac to za jednym razem musze je polaczyc. Problem w tym ze nie moge wgrac tylko bootloader bo do wgrania firmware potrzebuje sesji gprs a to robi program glowny. Bootloader laduje nowy firmware ale jak juz caly program dziala ktory otwiera sesje gprs.
    Tak wiec teraz lacze program glowny z bootem i wgrywam programatorem spi. Ale w przyszlosci moge chciec wgrac tylko sam firmware i juz boot nie jest potrzebny.
    Dlatego tylko dla tego pierwszego przypadku chcialem w latwy sposob dac linkerowi instrukcjie zeby polaczyl program glowny z bootem zebym ni emusial kombinowac.
  • #22 7041335
    erfro
    Poziom 15  
    Ponawiam prosbe,
    podpowie mi ktos jak pod AVR-GCC dołączyc do aktualnie bildowanego projektu jakis plik.hex ktory jest de-facto bootloaderem. Jak dac znac linkerowi zeby dolaczyl ten plik, ale zeby nie mieszac w make tylko z poziomu projektu z interfejsu Project Options
  • #23 7041371
    BoskiDialer
    Poziom 34  
    Nie wiem czy jest możliwość połączenia dwóch projektów na etapie kompilacji lub linkera, jednak pliki hex posiadają w każdej linii adres pod który należy zapisać daną linię danych. Po wygenerowaniu dwóch plików hex możesz je ze sobą po prostu połączyć, przy czym musisz usunąć linię ":00000001FF" z tego który jest pierwszy.

    Możesz tez wykonać coś takiego:
    grep -vh :00000001FF plik1.hex plik2.hex > nowy.hex
    echo :00000001FF >> nowy.hex
  • #24 7041676
    erfro
    Poziom 15  
    Ja je wlasnie recznie łącze (recznie tzn z uzyciem innego programu) ale myslalem zeby sobie ulatwic prace i polaczyc w AVR-GCC zeby bylo szybciej :-)
    Jakby ktos mial jakis pomysl to byłoby mi bardzo milo
REKLAMA