Bootloaderul Avr în întrebări și răspunsuri

Cum pot să mă asigur că nu există modificări în aplicație?

După resetare, încărcătorul rulează, de regulă, la aplicație. Dar cum poate fi sigur că aplicația este validă, este programul care ar trebui să înceapă să execute nu este deteriorat? Ce se întâmplă dacă încercarea anterioară de a actualiza programul sa prăbușit în mijlocul descărcării? În acest caz, există multe precauții posibile pe care le puteți lua. Iată câteva dintre ele:

Poate codul de încărcător să execute codul încorporat în aplicație?

Ei spun: "Nu, nu, și 100% cu siguranță nu."
Deși este posibil din punct de vedere tehnic, dar răspunsul este încă "nu". Încărcătorul dvs. va fi mult mai fiabil dacă are dependență zero de aplicație. Scopul principal al bootloader-ului este ștergerea și reprogramarea aplicației. Nu doriți să efectuați apeluri către secțiuni ale codului aplicației în timp ce ștergeți conținutul acesteia.
De asemenea, este o practică proastă de a stoca codul legat de bootloader în secțiunea RWW. Nu există dovezi sau metode complete de protecție împotriva ștergerii și reprogramării accidentale a acestei zone. O eroare totală a RWW și a încărcătorului de boot este potențial inutilă.

Poate codul aplicației să execute codul încorporat în bootloader?

Da, este destul de ușor de făcut. Mai ales dacă codul pentru partajare nu are acces la variabilele globale. Doar nu încercați să ajungeți la un cod comun creând încărcătorul și aplicația ca un singur fișier binar. Cel mai bine este să le construiți separat și să folosiți indicii pentru funcții comune de cod.

Există mai multe moduri de a seta tabelul de navigare. Este mai convenabil să o prezentați sub forma unui fișier de ansamblu mic separat:

Este posibil să aveți nevoie de un alt steag pentru a împiedica linkerul să încerce să vă arunce tabelul de conversie în cazurile în care acesta nu este în cerere. Acest lucru este posibil atunci când se utilizează -ffunction secțiuni compilator pavilion, împreună cu steaguri linker --gc-secțiuni și --relax. Prin urmare, dacă nu sunteți sigur, atunci în nici un caz nu vă doare să adăugați:

De ce variabilele globale nu sunt disponibile din funcțiile comune?

Deoarece aveți două fișiere binare complet diferite, fiecare va avea alocarea proprie de memorie. Pozițiile variabilelor globale în aplicație nu sunt în nici un fel legate de pozițiile variabilelor globale din
încărcător.
Să presupunem că funcția generală a încărcătorului, din greșeală, citește și scrie direct la variabila globală.
Atunci când încărcătorul a fost legat, spațiul variabilelor globale a fost codat în mod esențial în codul executabil. Când încărcătorul este executat, poziția sa este corectă și totul funcționează bine. Dar când se lansează o aplicație care solicită aceleași funcții, atunci pozițiile codate greu ale spațiului global sunt complet diferite. Se creează o situație incorectă, deoarece Când aplicația este executată, alocarea memoriei diferă de alocarea memoriei încărcătorului. Astfel, nu puteți accesa direct variabilele globale din funcțiile comune fără pericolul potențial de distrugere a datelor în aplicație.

Dacă dintr-un anumit motiv nu puteți trece parametrul la funcția generală, consultați întrebarea # 17 de mai jos.

Poate aplicația să utilizeze IRS încorporat în bootloader?

Apoi, trebuie să adăugați o rutină de întrerupere în aplicația dvs. Acest handler nu face nimic de la sine - efectuează un salt necondiționat la funcție - manipulatorul de întrerupere a boot-ului. De exemplu:

Cum să organizați accesul la date globale în cadrul operatorilor ISR obișnuiți?

Este posibil să economisiți spațiu în încărcător utilizând administratorii ISR?

Da, de multe ori puteți salva 100 sau mai mulți octeți ai încărcătorului. Acest lucru se aplică și în cazul aplicațiilor normale, însă o astfel de economie pentru încărcător este mai importantă decât pentru aplicație. Unele arhitecturi AVR au 40 sau mai multe întreruperi, fiecare din ele având 4 octeți în tabela vectorului de întreruperi. Nu puteți salva numai în mod semnificativ bani, dar, de asemenea, să redefinească vectorul neutilizat ca tranzițiile la funcțiile generale (discutate în număr întrebarea 14).

Prima intrare din tabela de întrerupere este vectorul de resetare. Încărcătoarele și aplicațiile folosesc adesea vectorul de resetare. Codul executabil nu începe niciodată cu începutul firmware-ului. Chiar dacă vectorul de resetare nu este în prezent necesar, poate fi necesar în viitor, de exemplu, după ce cineva adaugă o nouă variabilă PROGMEM. Prin urmare, în loc să ștergeți complet tabelul de întrerupere de la încărcător, este mai bine să o reduceți. Tabela minimă de întrerupere poate fi scrisă astfel:

Acest tabel conține numai vectorul de resetare care duce la funcția __init a mediului de execuție al lui C (acest lucru face vectorul de reset implicit). Presupunând că JMP poate fi înlocuit cu RJMP, avem un vector de întrerupere de 2 octeți. Adăugați acest fișier .S la linia ASRC a fișierului Makefile.

O modalitate mai corectă de a înlocui tabelul prestabilit al vectorilor este să utilizați un script de legătură specială. Mai întâi trebuie să aflați unde sunt scripturile linker AVR. Teoretic, scenariile linker ar trebui să fie denumite după numele arhitecturii AVR. Dar se pare că, uneori, nu este, prin urmare, găsiți script puteți redenumi dosarul în care este conținut (cel mai adesea C: \ WinAVR \ avr \ lib \ ldscripts pe Windows, și / usr / local / avr / lib / ldscripts pe Unix cum ar fi sistemul de operare) și recompilarea ulterioară. Linker-ul se va plânge „Nu pot deschide fișierul script linker ldscripts / avr3.x». Acest lucru vă spune numele corect al fișierului de script. Restaurați numele originale în directoare și copiați fișierul găsit în directorul proiectului. Apoi adăugați următoarea linie în Makefile în locația unde sunt atribuite steagurile linker:

Adăugați linia DISCARD și înlocuiți "vectorii" în numele secțiunii:

Articole similare