Difference between revisions of "Byggprocess ARM"

From Chalmers Robotförening
Line 43: Line 43:


=Makefil=
=Makefil=
Nu kan du kompilera ARM-kod, men du är inte riktigt hemma ännu. Du behöver fortfarande en makefil, för ditt projekt. En makefil är som en att-göra-lista för kompilatorn, som säger t.ex. vilka filer som ingår i projektet, hur kompilatorn ska optimera, vilka filer som ska genereras osv. Makefilen skriver du antingen själv eller så låter du en IDE (t.ex. Eclipse) ta hand om det. DEt finns för- och nackdelar med båda metoderna:
För att kunna kompilera kod behöver man en makefil för ditt projekt. En makefil är som en att-göra-lista för kompilatorn, som säger t.ex. vilka filer som ingår i projektet, hur kompilatorn ska optimera, vilka filer som ska genereras osv. Makefilen skriver du antingen själv eller så låter du en IDE (t.ex. Eclipse) ta hand om det. Det råder en del delade meningar om vilken metod som är bäst, men här är några för- och nackdelar med båda metoderna:
*Skriva själv
*Skriva själv
**+ Ditt projekt blir mer portabelt (du är t.ex. inte beroende av en IDE och det är enklare för andra att kompilera din kod).
**+ Ditt projekt blir mer portabelt (du är t.ex. inte beroende av en IDE och det är enklare för andra att kompilera din kod).
Line 62: Line 62:
Värt att nämna är att du kan använda Eclipse (eller annan IDE) även om du skriver din egen makefil. Summan av kardemumman är att automatgenerad makefile är mer automatisk, men tillåter för mindre insyn och friheter. Däremot kan det vara väldigt bra och lärorikt att kunna en del om byggprocessen.
Värt att nämna är att du kan använda Eclipse (eller annan IDE) även om du skriver din egen makefil. Summan av kardemumman är att automatgenerad makefile är mer automatisk, men tillåter för mindre insyn och friheter. Däremot kan det vara väldigt bra och lärorikt att kunna en del om byggprocessen.
==Skriva manuellt==
==Skriva manuellt==
Om du ska skriva en egen makefil så är det bra att ha en färdig makefil att utgå från.
Om du ska skriva en egen makefil så är det bra att ha en färdig makefil att utgå från. [[File:Makefile.txt]]
===Göra ett makefil-projekt Eclipse===
===Göra ett makefil-projekt Eclipse===
==IDE (Eclipse med ARM-plugin)==
==IDE (Eclipse med ARM-plugin)==

Revision as of 00:15, 6 January 2014

Denna sida går igenom hur det fungerar att bygga kod till ARM-processorer. Den går igenom saker såsom gcc, makefiler, kompileringsflaggor, länkning och annat under skalet på kompilatorn.

Sätta upp kompilator=

Innan man kan börja bygga kod måste man ha en byggmiljö. I artikeln Förberedelse programmering STM32 gås det igenom hur man sätter upp en byggmiljö för ARM (framförallt skaffar sig kompilator).

Byggprocessen

Detta är en kort beskrivning av byggprocessen och hur man anropar GCC. Det är inte helt nödvändigt att känna till vad som händer i alla steg, men det kan vara bra att känna till dem ändå. För mer utförlig information, se GCCs sida samt en sammanställning av alla options man kan skicka med. Eftersom det som används för ARM är en specialvariant av GCC så finns det några extra flaggor och några kanske inte fungerar. För att den kod som du skriver i C (eller något annat språk) ska kunna köras av processorn måste den översättas (kompileras) till ett språk som processorn förstår (maskinkod). Det finns enorma mängder inställningar och kompilatorflaggor, och det gäller att veta vilka som ska användas. Kort sagt går kompilatorn igenom upp till sex steg. De första tre stegen (Assemblator, C-kompilator och Länkare) är egentligen hopbakat och använder samma kommando-anrop (arm-none-eabi-gcc med massa flaggor och grejer efteråt). De tre sista stegen är optional, men kan vara bra att köra.

Assemblator(Assembler)

Ifall du har assemblerkod i ditt projekt (vilket du har, även om du inte skrivit det själv). Startup-filen är ofta skriven i assembler. Assemblatorn behöver veta vilka include-filer (h-filer), d.v.s. vilka bibliotek du använder ("-I"-flaggan), ifall du har några preprocessor-kommandon ("-D"-flaggan) osv. Exempel på preprocessor-kommandon kan vara vilken hastighet din externa kristall har eller vilken processorserie du använder.

C-kompilator (C compiler)

This is where the magic happens. Här görs din C-kod om till maskinkod. Även C-kompilatorn behöver känna till vilka includes du har och tar även preprocessor-kommandon. Vidare är optimering viktigt för C-kompilatorn. GCC stödjer 5 optimeringsnivåer (O0-3 samt s), där -O0 är ingen optimering, -O1 är lite optimering, -O2 är mer och -O3 är mest. Vidare är -Os storleksoptimering. Dessutom finns det en hel hög med andra optimeringsflaggor. Exakt vad som skiljer de olika optimerings-nivåerna åt är svart magisk magi, men finns dokumenterat här. Generellt sett rekommenderas Os och O2. C-kompilatorn vill också veta vilken standard du kör på. Den vanligaste är C99. GCC jobbar på att börja stödja C11 fullt ut, men nästan all kod idag förutsätter C99. Denna flagga är -std=gnu99. Använd inte C90, för det är gammalt och böpigt.

Länkaren (Linker)

Här händer mer magi. Länkaren tar dina .o-filer (som kommer ut från Assemblatorn och C-kompilatorn), klistar ihop dom och lägger rätt kod på rätt ställe i minnet (t.ex. om någonting ska direkt till RAM, om någonting ska till extern FLASH osv) samt hur mycket som finns tillgängligt utifrån ett länkarscript. Länkarscriptet ska du inte skriva själv, för det är väldigt krångligt. Använd istället ett färdigt. Du lägger till länkarscriptet med "-T"-flaggan. Länkaren tar även hand om startfilen (den första kod som körs när processorn startar). Den filen behöver bara skickas med till kompilatorn. En flagga som är väldigt bra att använda är "Remove unused sections" ("-Xlinker --gc-sections"). Den tar bort all kod som inte används i ditt program, vilket gör att du alltid kan inkludera hela biblioteket utan att ditt program blir gigantiskt. Ut ur länkaren kommer en .elf-fil. Elf-filen är hela programmet och används t.ex. för debugging och vissa programmeringsmetoder. Den är också indata till de kommande kompilatorstegen.

Ditt fullständiga kommando kommer att vara en LÅNG harrang av text, men du kommer aldrig att se hela kommandot på en gång (såvida du inte vill själv) oavsett om du skriver egen makefil eller använder Eclipse. Exempel på de kompilatorflaggor som bör skickas med är:

arm-none-eabi-gcc -std=gnu99 -g -O2 -Wall -Tstm32_flash.ld -mlittle-endian -mthumb -mthumb-interwork -nostartfiles -mcpu=cortex-m3 \
-I<path_to_includes> \
-DHSE_VALUE=8000000UL \
-T<path_to_linkerscript> \

Flash image (objcopy)

I nästa steg kompileras elf-filen till en fil som man ofta använder för att ladda in i processorn. Det finns ett par olika filformat, men gemensamt för dem är att det är närmare den data som ska hamna i microcontrollers minne i slutändan. Exempel på några vanliga format är .bin (binary) och .hex (intel hex). Kommandon som kan köras är: <source lang="bash"> arm-none-eabi-objcopy -O ihex proj_name.elf #trollar ut en .hex-fil arm-none-eabi-objcopy -O bin proj_name.elf #trollar ut en .bin-fil </source>

Listfil (objdump)

Skapar en list-fil som innehåller t.ex. opkoder tillsammans med assemblerkoden och vart dina funktioner börjar osv. Den kan vara bra att ha vid avancerad felsökning och om man vill vara säker på att processorn gör precis som du tror att den ska göra. Det kan också vara lärorikt att se vad som genereras av C-kod. Kommandot är: <source lang="bash"> arm-none-eabi-objdump -h -S proj_name.elf #trollar ut en listfil med assemblerkod och funktionssymboler </source>

Programstorlek (size)

Skriver ut den kompilerade storleken av ditt program, samt hur mycket som ligger i vilket minne. Väldigt värdefullt att ha, särskilt om man har en liten processor, eller ifall man vill spara på RAM. Kommandot och resultatet är: <source lang="bash"> arm-none-eabi-size --format=berkeley IntroARM.elf

  text	   data	    bss	    dec	    hex	filename
  9440	     20	    336	   9796	   2644	IntroARM.elf

Finished building: IntroARM.siz </source> Text är det som går in i ditt flash, data och bss är det som hamnar i RAM och dec är det totala. Alla storlekar är i byte.

Makefil

För att kunna kompilera kod behöver man en makefil för ditt projekt. En makefil är som en att-göra-lista för kompilatorn, som säger t.ex. vilka filer som ingår i projektet, hur kompilatorn ska optimera, vilka filer som ska genereras osv. Makefilen skriver du antingen själv eller så låter du en IDE (t.ex. Eclipse) ta hand om det. Det råder en del delade meningar om vilken metod som är bäst, men här är några för- och nackdelar med båda metoderna:

  • Skriva själv
    • + Ditt projekt blir mer portabelt (du är t.ex. inte beroende av en IDE och det är enklare för andra att kompilera din kod).
    • + DU kan använda vilken texteditor eller IDE som helst (nästan), och behöver inte förlita dig på en viss IDE.
    • + Du får mer kontroll över byggprocessen och kan göra mer avancerade saker
    • - Det är kan vara krångligare än att låta en IDE ta hand om det och du får inte lika bra stöd från IDEn.
    • - Det kan vara en stor tröskel att komma över att börja köra makefiler
    • - Du måste ändra mer manuellt när du gör ett nytt projekt
    • - Du måste komma ihåg att lägga till nya filer i din makefil
  • Låta en IDE generera makefil (i detta exempel är det Eclipse som gäller)
    • + Det är enklare att komma igång med
    • + Du kan tweaka ditt projekt och din byggprocess med ett grafiskt gränssnitt
    • + Din IDE kan ge dig mycket bättre stöd om den får generera makefilen själv
    • - Du är mer beroende av en viss IDE
    • - Även om det mesta går att göra via Eclipses grafiska gränssnitt kan en del avancerade saker vara svåra att göra (som hade varit enklare med en egenskriven makefil).

Värt att nämna är att du kan använda Eclipse (eller annan IDE) även om du skriver din egen makefil. Summan av kardemumman är att automatgenerad makefile är mer automatisk, men tillåter för mindre insyn och friheter. Däremot kan det vara väldigt bra och lärorikt att kunna en del om byggprocessen.

Skriva manuellt

Om du ska skriva en egen makefil så är det bra att ha en färdig makefil att utgå från. File:Makefile.txt

Göra ett makefil-projekt Eclipse

IDE (Eclipse med ARM-plugin)

Flyttalsprocessor

I en del processor (de med cortex-m4-kärna) finns det en flyttalsprocessor som är väldigt snabb på att beräkna flyttal. Exempel är STM32F4xx som sitter på STM32F4Discovery. För att göra detta krävs det vissa specialinställningar för kompilatorflaggorna. man kan inte köra Os, då funkar den dåligt.

Kompilatorflaggor