Stm32f4 gnu după configurarea mediului de compilare (partea 4)

În publicațiile anterioare am arătat de la care se poate împinge atunci când scrieți programe pentru STM32F4, setați mediul de compilare, am determinat fișierul aspect, pentru a obține un fișier model al programului în limbaj de asamblare, încercați să configurați GPIO microcontroler și LED-ul clipit.

Acum este momentul să înțelegeți compilația de programe compuse din mai multe fișiere, să dezasamblați modul de scriere a programelor pentru mai multe carduri de depanare, să învățați cum să faceți setările programului pentru o modificare convenabilă

Să începem cu cel mai simplu: mecanismul de compilare condiționată

  1. la concluzia 15 GPIO_D pentru STM32F4 Discovery
  2. la pinul 2 GPIO_H pentru Open407I-C

În asamblarea GNU AS există un mecanism de compilare condiționată.
Am gasit comanda .def - conform documentatiei ar trebui sa creeze o valoare, dar nu am putut sa o fac sa functioneze, asa ca am folosit directiva ".set".
Inițial, atribuim o valoare variabilei compilatorului (nu programe!), Am ales numele variabilei DEVBOARD:

Configurația acestor parametri în timpul compilării condiționate arată astfel:

În textul programului în sine, toate referințele "directe" la GPIOD (GPIOH) sunt acum modificate la GPIO_LED. Valoarea pentru RCC_AHB1ENR este înlocuită cu RCC_GPIO_EN și așa mai departe.
Avem următorul program:

Acum, gândiți-vă la programe relativ mari, care nu sunt susceptibile de a fi convenabile pentru a scrie într-un fișier, și care va consta din mai multe (poate chiar mai multe) dosare.
Ne uităm la un exemplu de program de „Flasher“ nostru: are o rutină care pune în aplicare o pauză între pornirea / LED-off, acum este doar un ciclu cu un număr fix de așteptări ciclice, dar în viitor, o rutină poate fi rescrisă pentru a utiliza cronometrul de sistem - iar acest subrutina este corect locul într-un alt dosar.
Includeți fișierele pot fi directive ".include" assembler:

această soluție este foarte simplă și destul de eficientă, dar are una, la început aparent nesemnificativă, dezavantaj - un spațiu de nume comun pentru etichete.
În timp ce programul nu va fi de peste 150-300 de instrucțiuni - nu va avea probleme în „inventând“ nume de etichete, cum ar fi următoarele întârzierile de rutină poate începe cu eticheta „DELYA1:“, și în urma cu chiar un fel de combinație, dar nu este atât de pur și simplu: de îndată ce începeți să creați propria dvs. bibliotecă de subrutine și începeți să le folosiți în diferite combinații, atunci cu siguranță intersecțiile din numele etichetelor vor începe.
O soluție - o introducere în numele numele etichetei unui fișier prefix de cod sursă, de exemplu, pentru subrutină nostru de întârziere, puteți specifica următorul nume de etichetă „DELAY_ASM_DELAY:“, am încercat în acest fel din nou, deși nu fără rezerve - de fapt, în procesul de dezvoltare a unor module pot fi localizate în subdirectoare proiectul, și că nu a existat etichete de nume de intersecție ar trebui să includă nu numai numele fișierului, dar numele directorului „DIRECTORY_DELAY_ASM_DELAY:“ (de exemplu, un director numit „director“, în cele din urmă, în cazul în care avem încă nevoie de numele tag-ul, care este format din 2- 3 cuvinte pentru claritate - vom obține absolut monstroidalnye nume de etichetă: „DIRECTORY_DELAY_ASM_DELAY_LOOP_0x10000:“ ...

O altă modalitate este de a compila separat fișierele sursă ale programului.
De fapt, asamblatorul poate compila separat fisierele main.asm si delay.asm. și apoi în faza de construcție - aceste două componente compilate vor fi combinate în firmware-ul final.
Deoarece fiecare fișier .asm va fi compilat separat - la începutul fiecăruia trebuie să includeți instrucțiunile pentru setările de compilare și, dacă este necesar, să includeți un fișier de constante.
Pentru a spune compilatorului care etichetă din acest fișier poate fi folosit din exterior - se folosește directiva ".global".
Luați în considerare textul subrutinei atunci când este plasat într-un fișier separat pentru compilare separată:

Prin urmare, eticheta DELAY declarate ca .global va fi disponibil pentru a fi apelat de la alte software-uri de fișiere sursă, dar eticheta este accesibilă numai în fișierul delay.asm DELAY_loop și, de fapt, numele unei etichete poate fără efecte folosite în alte părți ale programului - intersecția nu va fi!

în textul programului principal în funcție de facto normele existente trebuie să includă directiva „.extern“, care indică spre o etichetă care este definită într-un alt fișier, și va fi legat de aspectul scenă, dar documentația GNU după cum se menționează că directiva este trecut pentru a asigura compatibilitatea, precum și orice Nu se găsesc în fișierul de compilare sursă, etichetele și constantele sunt considerate globale. Abordarea în opinia mea discutabil, valorile de etichete, totuși, externe și constante indică în mod clar mai bine.

după cum puteți vedea din lista de mai sus - nu se adaugă ".include" pentru fișierul inclus! Includerea va procesa linker-ul.

procesul de compilare și asamblare a proiectului ar trebui să arate astfel:

Acum puteți vedea în mod clar neplăcerile unei astfel de scheme pentru un anumit programator: trebuie să compilați fișiere individuale și apoi, la asamblare, să specificați fișierele compilate rezultate. Faceți acest lucru în modul manual, editați în mod constant fișierul make_project.bat, destul de o lecție de rutină, astfel încât acest proces trebuie mutat în "umerii puternici" ai altcuiva,
Un pic de experimentare pe "sâmbătă", am scris un nou fișier .bat care colectează proiectul în modul automat.
A trebuit să facem unele modificări în structura cataloagelor proiectului și în "acordul" privind denumirea fișierelor:

  1. codul sursă al programului este localizat în subdirectorul src / project:
    Stm32f4 gnu după configurarea mediului de compilare (partea 4)
  2. în subdirectorul fișierele compilate / pregătite pentru firmware sunt plasate, în subdirectorul compile / temp / sunt localizate fișierele de referință ale fișierelor compilate, un fișier de valori etc.
    Stm32f4 gnu după configurarea mediului de compilare (partea 4)
  3. toate fișierele din subdirectorul / src și având extensia .asm vor fi compilate. În acest caz, fișierele care vor fi incluse Directiva .include nu ar trebui să aibă .asm extensie - ca în acest caz, acestea vor fi compilate de două ori - prima dată în program, în care acestea includ Directiva .include. și separat prin extensie.
  4. calea tuturor fișierelor care sunt incluse în proiect cu comanda .include trebuie să înceapă cu specificarea directorului src /. de exemplu, pentru fișierul constante care se află în directorul src / directiva ar trebui să fie scrisă după cum urmează: include "src / const_file.inc"

Următorul script este plasat în

Dosarul proiectului ar trebui să fie plasat într-un dosar în care nu există spații în cale în calea sa. Literele rusești în nume de directoare sunt permise.
Astfel, calea de a alerga: D: / MoyProekt / gnuas / prima / - este admisibilă, dar D: / Proiectul meu / GNU / prima / - nu va permite (numele dosarului „Proiectul meu“ conține un spațiu)

În secțiunea .text a firmware-ului voi face o explicație:

O astfel de înregistrare indică linker-ului că secțiunile ar trebui plasate exact în ordinea în care sunt descrise.
Pentru vectorii de întrerupere am intrat în secțiunea .Vectori, această secțiune ar trebui să apară doar o dată în program (ceea ce este logic, deoarece tabelul de vectori din programele noastre este până acum doar unul).
Am Declarăm secțiune a programului în cazul în care textul va fi plasat: a .text și .asmcode - pe „idee“ secțiunea .text va fi garantată disponibile după tabelul de vector - în această secțiune am loc diverse rutine de serviciu (de exemplu, „capace“ de întrerupere) și Aici, în secțiunea .asmcode, scriu programul în sine.
Astfel, prin notarea secțiunii .Vectors în program, garantez plasarea ei la începutul programului, indiferent de modul în care fișierul este specificat în main.o
Ordinea plasării mai multor secțiuni .asmcode. relativ unele de altele, de regulă, deja nu joacă un rol (bine, pentru a fi complet cinstit, cu siguranță joacă, dar este doar pentru programe foarte mari, dar e prea devreme să te gândești la asta)
Secțiunea .rodata este o secțiune a constantelor în bliț, alocată separat pentru comoditate, explică de ce este necesar doar prin exemplu:

iar constanta este plasata intr-o sectiune separata a .rodata dupa sectiunea .asmcode
O mizerie. - Da! Dar, uneori, este foarte convenabil!

Sper ca ideile de bază care ma mișcat atunci când a devenit clar care formează secțiuni, iar acum este necesar să se facă modificări la proiectul „Flasher“ nostru, cu două fișiere de programe sursă pe secțiuni de denumire

Acum, în orice mod nu ne-am dat fișierele la aspectul - secțiunea .vectors va fi întotdeauna la începutul fișierului sursă, și secțiunea .asmcode după acesta ... dar care o parte a programului va merge imediat după indicii tabelul de întrerupere (main.asm sau delay.asm ) - va depinde de ordinea aspectului lor (care se ridica în picioare - unul și adidații mai devreme și plasați)

Ce altceva este necesar pentru fericirea completă? scris programe de asamblare pentru STM32F4?

P.S. aproape a uitat arhiva pentru a atașa blink4.zip