Förberedelse programmering STM32

From Chalmers Robotförening

Förord
Jag som gjort denna guide vill inte påstå mig ha en överlägset bra koll på allt det jag skriver om, utan snarare är jag en nybörjare själv som nyligen fått igång det jag skriver om. Men min förhoppning är att jag, till skillnad från mer erfarna medlemmar i föreningen, har just på grund av detta möjlighet att skriva en guide som riktar sig till den totala nybörjaren och jag kommer inte utgå från att du har erfarenhet av linux, mikrokontrollers eller C programmering. Guiden är tänkt att läsas från början till slut, och hoppa över de delar som inte berör dig.

Det är lätt att drunkna i information, samtidigt som man inte hittar svar på de allra mest basala frågor, när man vill lära sig något nytt. min erfarenhet är att man fastnar på ett litet problem, som t.ex. ett felmeddelande under en installation, och i letan om vad meddelandet säger så hittar man en uppsjö bra guider och forum som berör ämnet, men det slutar allt som oftast med att man länkas vidare i många steg, så att i slutet av kvällen har man 100 flikar öppna med halvlästa guider i webbläsaren. för att spara Din tid så kommer jag försöka att lägga in "allt" material du behöver på denna sida (exkl. saker du behöver ladda hem), så att minimalt antal avstickningar från denna guide behövs under hela förloppet. när länkar till annat material presenteras så är det dels en källhänvisning (cred till den person som skrev orginalguiden) eller en möjlighet att läsa mer om ämnet.

Har du frågor, fastnar du, får du problem, eller vill du bara tacka för hjälpen; hör av dig till en styrelse-medlem!

Innan du börjar

Detta behöver du:

  • Tid
  • Passion och nyfikenhet
  • Förmåga att läsa engelska
  • En dator med ~10GB ledigt på hårddisken
  • Ett usb-minne (enklast för installation av Ubuntu) ( fungerar även med t.ex. CD/DVD skiva)

Operativsystem

Vi rekommenderar att du programmerar i Ubuntu då det finns en bra så kallad tool-chain i Ubuntu som är gratis och inte har några inbyggda begränsningar. Det finns även alternativ för windows, så som Kiel eller IAR men det är ingen i föreningen som använt denna och kan hjälpa dig ifall du fastnar. Både Kiel och IAR är begränsade till att bara kunna använda 32kb flashminne i gratisversionen, så det kan vara bra att testa om du vill komma igång direkt, men det är ingen hållbar lösning.

Om du har Ubuntu installerat

Då är allt som det ska och du kan hoppa ner till Kompilera kod för ARM

Om du har Mac OS X

Kort version (tills det kommer en riktig variant): Du kan köra nästan samma guide som för Ubuntu till OSX. Du behöver ha XCode installerat för att få lite kompilatorer, samt att du behöver ha Macports eller Fink. Det som inte riktigt fungerar ännu är STM32Flash för att progammera med USB-uartbryggan. I annat fall kan man använda en ST-LINK/V2 (som också finns på STs utvecklingkort). Dessa kostar runt 100-200kr. För detta är OpenOCD rekommenderat.
Du kan även utan problem köra Ubuntu i Virtual Box. Annars är det bara att googla på Setting up STM32 for OS X Eclipse eller nåt och följa instruktioner. TODO: Fixa en genomtänkt guide.

Om du har Windows

Det finns 3 sätt att fixa Ubuntu på din dator:

Kompilera kod för ARM

Denna del går igenom hur du sätter upp kompilatorer och liknande för ARM. För att kunna göra detta behöver du primärt GCC (vilket bör finnas på din dator). Vid slutet av denna del kommer du att kunna bygga enkel exempelkod och ta fram en körbar fil. Denna del går igenom:

  • Sätta upp ARM-gcc (och andra verktyg)
  • Makefil
  • Lite om bibliotek

Denna guide är skriven av Benjamin Vedder på hans hemsida. Modifierad av Mikael Tulldahl.

Download and build GCC, GDB, OpenOcd and newlib

To set up the toolchain, a modified version of the summon-arm-toolchain script will be used. Firstly, a few packages have to be installed. Open a terminal(Ctrl + t) and paste the following command:

sudo apt-get install build-essential git flex bison libgmp3-dev libmpfr-dev libncurses5-dev libmpc-dev autoconf texinfo libtool libftdi-dev libusb-1.0-0-dev zlib1g zlib1g-dev python-yaml

Execute by pressing enter. This will build all the required tools, for which the summon-arm script can be used. For me it didn’t work right out of the box, so I modified the script a bit. You can download the modified version here

Unzip the files to some directory and make the file runnable with this command (make sure to replace PATH_TO_DOWNLOADED FILE with the actuall path, probably this works:"~/Downloads"):

<source lang="bash"> cd PATH_TO_DOWNLOADED FILE unzip summon-arm-toolchain.zip cd summon-arm-toolchain chmod +x summon-arm-toolchain </source>

Build the toolchain with this command (Note this will take about 1 hour or so): <source lang="bash"> ./summon-arm-toolchain </source>

While this is building, you can make sure that the tools are in you path by opening another terminal(Ctrl + t) and typing (make sure to replace YOU_USER with your actuall user name):

<source lang="bash"> sudo su echo 'export PATH=/home/YOUR_USER/sat/bin:$PATH' > /etc/profile.d/arm_tools.sh exit </source>

This should make sure that you can run the tools from any directory without the need to specify the full path. For the path update to take effect you have to log out and log in again.

When the summon-arm script finishes, you should be able to build programs for the STM32F4 (and many other) microcontrollers and use hardware floating point support.

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:

  • 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.

Byggprocessen

Detta är en kort beskrivning av byggprocessen och hur man anropar GCC. För mer utförlig information, se officiella GCC-sidan 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 igen upp till sex steg. De första tre stegen (Assemblator, C-kompilator och Länkare) använder är egentligen hopbakat och använder samma kommando-anrop (arm-none-eabi-gcc med massa flaggor efteråt). De tre sista stegen är optional, men kan vara bra att köra.

Assemblator

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

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. I expanderat format kommer ditt kommando att se ut nånting såhä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_libs> \
-DHSE_VALUE=8000000UL \
-T<path_to_linkerscript> \
<source_files>\
<startup-file>\
-O

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>

Storlek (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.

Flytta programmet från dator till STM32

Detta kan göras på flera sätt. Antingen använder man en STM32-programmerare eller så använder man den inbyggda bootloadern. (Det finns säkert fler sätt, såsom att använda 2 strömbrytare och mycket tid)

ST-LINK

ST-LINK är STs officiella programmerare. Den finns i två versioner, V1 och V2. Primärt använder vi V2, eftersom den är bättre och enklare att prata med. Dessutom finns det en sådan inbyggt på nästan alla STs utvecklingskort, såsom STM32F4Discovery som finns att köpa på t.ex. Elfa, men det spelar nästan ingen roll vilken version (F0,F1, ... ,F4). Det finns även i Lokalen att använda (ej låna med hem!). Det enda kortet man bör undvika är STM32VLDiscovery eftersom den innehåller ST-LINK/V1, som är svårare att prata med, men fortfarande möjligt. På Discovery-kortet sitter det dels en så kallad "programmerare" (ST-LINK/V2) och dels en STM32. vi ska använda programmeraren för att programmera om vår stm32'a. Ta bort de två jumpers som är markerade "ST-LINK DISCOVERY" för att programmera genom SWD porten. Annars kommer stm32'an på discovery-kortet att programmeras.

För att ladda över programmet behöver man ett program på datorn för att prata med programmeraren. Det finns ett flertal olika program.

QSTLink2

Denna guide är skriven av Benjamin Vedder på hans hemsida. Modifierad av Mikael Tulldahl.

In order to upload the binary files to the STM32F4 Discovery board I have been using a program called QSTLink2. I have modified the program a bit and added a button to upload the last uploaded file (which is pretty convenient) and fixed a few bugs in the cli interface. You can download the modified version here.

You have to build QSTLink2 from source in order to use it. First, install some dependencies:

<source lang="bash"> sudo apt-get install qt4-qmake libqt4-dev libqt4-gui libqt4-xml qt4-designer qtcreator libusb-0.1-4 libusb-1.0-0-dev </source>

Now unzip QSTLink2 to some directory and cd to it from a terminal. Then type:

<source lang="bash"> qmake-qt4 make sudo make install sudo reload udev </source>

Plug in your Discovery board. You should now be able to start QSTLink2 by entering in a terminal:

<source lang="bash"> ./qstlink2 </source>

Connect the Discovery board with the mini usb and upload the binary file which is generated in the build directory of the sample project when running make (you're looking for a .bin file).

OpenOCD

OpenOCD (Open On-chip debugger, OOCD) är ett open-source-projekt som är en generell programmerar-mjukvara för allt möjligt, såsom ARM-processorer, flash-minnen, FPGA osv. Det ska finnas versioner för alla OS. Det är möjligt att OpenOCD kommer med i summon-arm-scriptet, men det kan vara en gammal version. Kolla här ifall du har den senaste versionen (du kollar vilken version du har installerad genom att köra "openocd -v" i terminalen). Om så inte är fallet, ladda hem och bygg den. Innan du bygger bör du köra följande kommando från mappen dit du unzippat OpenOCD: <source lang="bash"> ./configure --enable-maintainer-mode \ --disable-option-checking \ --disable-werror \ --enable-dummy \ --enable-ft2232_libftdi \ --enable-usb_blaster_libftdi \ --enable-ep93xx \ --enable-at91rm9200 \ --enable-presto_libftdi \ --enable-usbprog \ --enable-jlink \ --enable-vsllink \ --enable-rlink \ --enable-arm-jtag-ew\ --enable-stlink </source> Primärt är det maintainer-mode och stlink du vill ha, men det är lika bra att installera allt. Sedan bygger du programmet som vanligt (från samma mapp): <source lang="bash"> make sudo make install sudo reload udev </source> Du kan kontrollera att det är korrekt version du har installerad genom att skriva "openocd -v" i en terminal. För att ladda över ditt program kopplar in din programmerare och kör följande kommando:

openocd -f interface/stlink-v2.cfg -c "set WORKAREASIZE 0x2000" -f target/stm32f1x_stlink.cfg -c "program <path_to_your_.elf-file> verify reset"

där interface anger vilken programmerare du har, target säger vilken processor som ska programmeras (stm32f1x_stlink.cfg för STM32F1, stm32f4x_stlink.cfg för STM32F4 osv), och <path_to_your_.elf-file> pekar ut den .elf-fil som genereras när du kompilerar ditt program (borde ligga i release-mappen). Det är möjligt att man inte behöver sätta WORKAREASIZE längre efter att undertecknad (sternå) gnällde på det. Ifall den är för stor (i förhållande till RAM-storleken på din krets) så går det inte att programmera program som är för stora.

När du laddar över programmet bör det se ut någonting såhär:

openocd -f interface/stlink-v2.cfg -c "set WORKAREASIZE 0x2000" -f target/stm32f1x_stlink.cfg -c "program /Users/Sterna/Dropbox/eclipse/ARM/IntroArm/Release/IntroARM.elf verify reset"
Open On-Chip Debugger 0.7.0-rc1 (2013-04-25-15:10)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.sourceforge.net/doc/doxygen/bugs.html
0x2000
Info : This adapter doesn't support configurable speed
Info : STLINK v2 JTAG v14 API v2 SWIM v0 VID 0x0483 PID 0x3748
Info : Target voltage: 2.893868
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x080014b8 msp: 0x20001000
** Programming Started **
auto erase enabled
Info : device id = 0x10016420
Info : flash size = 128kbytes
Info : Padding image section 0 with 2404 bytes
wrote 8192 bytes from file /Users/Sterna/Dropbox/eclipse/ARM/IntroArm/Release/IntroARM.elf in 0.587122s (13.626 KiB/s)
** Programming Finished **
** Verify Started **
verified 5408 bytes in 0.123319s (42.826 KiB/s)
** Verified OK **
** Resetting Target **
shutdown command invoked

Du kan även använda OpenOCD för att debugga din microcontroller också. Mer information om detta finns i benjamins guide. Vidare kan du även programmera andra microcontrollers med OpenOCD och ST-LINK. Har du tur finns det inbyggt stöd, annars får du lägga in en egen .cfg-fil för det.

Bootloader

Detta metod används på introARM. Inbyggt i alla STM32-processorer finns en bootloader (ett litet program som tillåter att processorn programmerar in sitt program själv) som kan prata över en del olika kommunikationskanaler (t.ex. USB, UART eller CAN). Den processor som sitter på IntroARM stödjer endast UART. Detta kräver ett program på datorn samt en USB-UART-brygga (för det är väl ingen som fortfarande har serieport på datorn?). Ett exempel är en CP2102 eller CP2104 som ingår i IntroARM men även finns att köpa på föreningen. Ett simpelt program som man kan använda är stm32flash. Det ska fungera till alla OS, men har primärt testats på Linux. Det är möjligt att det krävs en lite moddat variant som kommer att släppas här.

Debugga

Det är sällan man skriver en kod som fungerar på direkten. Då är det oftast bättre att använda ett debugging-verktyg än att slumpmässigt börja ändra i sin kod. För att fixa igång detta följer du Benjamin Vedders Guide.

IDE är trevligt

Man kan tröttna snabbt på att knacka ihop kod i en ordbehandlar, skriva make i terminalen för att sedan använda st-link eller boot-loader för att skicka över programmet. då kan man kolla på en Integrated Developement Environment, IDE. Eclipse är en sådan IDE, den hjälper dig väldigt mycket när du skriver kod, och den kan även integrera kompilatorn, så att du trycker på en knapp i GUIn för att kompilera istället för att skriva make i en terminal. Till Eclipse finns även ett ARM-plugin som är rekommenderat.