Arbetsbok för MD407 (Läsprov) Roger Johansson

Relevanta dokument
Arbetsbok för MD407. Göteborg i oktober 2017, Roger Johansson

Assemblerprogrammering del 1

LEU240 Mikrodatorsystem

Programmering i maskinspråk (Maskinassemblering)

Programmering i maskinspråk (Maskinassemblering)

Digital- och datorteknik

Code-Lite tutorial ( /RoJ)

Digital- och datorteknik

Digital- och datorteknik

Maskinorienterad programmering

BDM12 Användarbeskrivning. Introduktion

Maskinorienterad Programmering IT2, LP2-2016/2017

Dataminne I/O Stack 0x005D 0x3D SP low byte 0x005E 0x3E SP high byte

Inledning. Vad är ett datorprogram, egentligen? Olika språk. Problemlösning och algoritmer. 1DV433 Strukturerad programmering med C Mats Loock

Programräknaren visar alltid på nästa instruktion som skall utföras. Så fort en instruktion har hämtats så visar programräknaren på nästa instruktion.

Föreläsning 2. Operativsystem och programmering

Assemblerprogrammering, ARM-Cortex M4 del 3

Maskinorienterad programmering

F5: Högnivåprogrammering

Maskinorienterad programmering

Assemblerprogrammering del 2

F5: Högnivåprogrammering

Maskinorienterad programmering

Laboration nr 4 behandlar Assemblerprogrammering

SKAPA DET FÖRSTA PROJEKTET I mikrobasic PRO for AVR

F2: Motorola Arkitektur. Assembler vs. Maskinkod Exekvering av instruktioner i Instruktionsformat MOVE instruktionen

Så här skriver du ditt första program i C++

Assemblerprogrammering - fördjupning

CE_O3. Nios II. Inför lab nios2time

PC-teknik, 5 p LABORATION ASSEMBLERINTRODUKTION

Maskinorienterad Programmering LP2-2017/2018

GPIO - General Purpose Input Output

Maskinorienterad programmering

Maskinorienterad Programmering LP3-2017/2018

Föreläsning 3. Programmering, C och programmeringsmiljö

Assemblerprogrammering för ARM del 2

c a OP b Digitalteknik och Datorarkitektur 5hp ALU Design Principle 1 - Simplicity favors regularity add $15, $8, $11

Datorlaboration 0, Programmering i C++ (EDA623)

NetBeans 5.5. Avsikt. Projektfönster

General Purpose registers ALU I T H S V N Z C SREG. Antag att vi behöver skriva in talet 25 till register R18

Elektroteknik MF1016 föreläsning 9 MF1017 föreläsning 7 Mikrodatorteknik

Programmering av inbyggda system. Kodningskonventioner. Viktor Kämpe

Maskinorienterad programmering

Maskinorienterad programmering

NetBeans 7. Avsikt. Projektfönster

Kontrollskrivning Mikrodatorteknik CDT S2-704

Det finns en handledning till kortet på hemsidan. AVR STK500.

Assemblerprogrammering för ARM del 3

Programmering av inbyggda system 2014/2015

Programallokering. Programtyper. Att placera program i flashrespektive. Program i FLASH-minne. Program i RAM-minne

Programutveckling med Java Development Kit. (JDK 1.1.x) och Programmers File Editor (PFE 7.02)

Inledande programmering med C# (1DV402) Ditt första C#-program med Visual Studio

Eclipse. Avsikt. Nu ska ett fönster liknande figuren till höger synas.

Datorlaboration 0, Programmering i C++ (EDAF30)

CPU. Carry/Borrow IX. Programräknare

DBG11 Användarbeskrivning - Utgåva 2

Datorteknik. Tomas Nordström. Föreläsning 6. För utveckling av verksamhet, produkter och livskvalitet.

Assemblerprogrammering del 3

Tentamen med lösningsförslag

Besvara de elektroniska frågorna (se kurshemsidan). Läs kapitel i kursbok.

Övning1 Datorteknik, HH vt12 - Talsystem, logik, minne, instruktioner, assembler

Digital- och datorteknik

Fö 5+6 TSEA81. Real-time kernel + Real-time OS

Lösningar till tentamen i EIT070 Datorteknik

Datorteknik 2 (AVR 2)

Innehållsförteckning. 9 Större projekt Övningsuppgifter...32

Stack och subrutiner Programmeringskonventionen

Laboration 2 i Datorteknik- Assemblerprogrammering II

IS1200 Datorteknik. Övning CE_O4 Maskinnära programmering med C Förberedelser till hemlaboration 1

Labb i Datorsystemteknik och programvaruteknik Programmering av kalkylator i Visual Basic

Programmering i C++ Kompilering från kommandoraden

Datorteknik 1 (AVR 1)

Grundläggande datavetenskap, 4p

Verktyg och Utvecklingsmiljö. Föreläsning 2 Eclipse

DBG identifierar därefter sig genom utskrift av namn och version. Se även "Disposition av adressrum" nedan. Följande kommandon accepteras av DBG

Laboration 1 Introduktion till Visual Basic 6.0

Paneler - VCPXX.2. Programmeringsmanual för VCP-paneler. Revision 2

Objektorienterad programmering i Java I

Ulf Assarsson. Grundläggande C-programmering del 2 Pekare och Arrayer. Läromoment:

Programmering av. PADDY mini

Introduktion till programmering och Python Grundkurs i programmering med Python

Mål. Datorteknik. Innehåll. Innehåll (forts) Hur ser ett program ut? Hur skapas maskinkoden?

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

Till assemblersystemet Zuper 80 Assembler krävs en SPECTRAVIDEO 328/318+minst 16K ram extra.

LABORATION. Datorteknik Y

MIKRODATORTEKNIK 2012 INNEHÅLLSFÖRTECKNING

Laboration 3 HI1024, Programmering, grundkurs, 8.0 hp

Programmering B med Visual C

Emacs. Eric Elfving Institutionen för datavetenskap (IDA) 22 augusti 2016

Under hela detta avsnitt arbetar eleven självständigt med att bygga upp ett komplett applikationsprogram för att styra en liten borrmaskin.

Institutionen för elektro- och informationsteknologi, LTH

Datorteknik. Föreläsning 3. Assembler, stack och subrutiner, programmeringskonventionen. Institutionen för elektro- och informationsteknologi, LTH

Programbibliotek. Ur innehållet: Olika typer av bibliotek Kompilatorbibliotek C-bibliotek Run-time miljö Så skapar du ett nytt bibliotek

Digital- och datorteknik

DBG identifierar därefter sig genom utskrift av namn och version. Följande kommandon accepteras av DBG. Hantera brytpunkter i användarprogram

Laboration nr 3 behandlar

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Felsökning. Datatyper. Referenstyper. Metoder / funktioner

Grundläggande C-programmering del 2 Pekare och Arrayer. Ulf Assarsson

LABORATION. Datorteknik Y

Kompilera och exekvera Javakod

Transkript:

Arbetsbok för MD407 (Läsprov) Roger Johansson

Kopieringsförbud Detta verk är skyddat av upphovsrättslagen. Kopiering utöver lärares och studenters begränsade rätt enligt Bonus Copyright Access kopieringsavtal är förbjuden. För information om detta avtal hänvisas till Bonus Copyright Access. Roger Johansson och Göteborgs Mikrovaror (GMV), 2016, 2017, 2019 Internet: http://www.gbgmv.se Utöver denna bok finns omfattande material, bland annat i form av programvaror, datablad, exempelsamlingar och en Quick Guide, avsett att användas tillsammans med boken. Programvaror med utvecklingsverktyg och speciellt utvecklade simulatorer finns för Windows, MacOS och Linux.

Förord Denna arbetsbok har anpassats för självstudieverksamhet under en kurs i Maskinorienterad programmering, med omfattningen 7,5 c på högskolenivå. Arbetsboken ger en introduktion till enkortsdatorn MD407 uppbyggd kring den ARM-baserade enchipsdatorn ST32F407 tillsammans med laborationskort avsedda för MD407. Laborationsdatorn och de anpassade laborationskorten utvecklades på Chalmers under åren 2014-2017, och distribueras som Open Source under GPL. Göteborg i december 2018, Roger Johansson Läsprov - 3

Arbetsbok för MD407 Innehåll: Kapitel 1 Programutveckling i assemblerspråk... 7 Inledning... 7 1.1 ETERM8 och programutvecklingen... 7 1.2 Simulatorfunktioner... 15 Kapitel 2 Strukturerad assemblerprogrammering... Fel! Bokmärket är inte definierat. Inledning... Fel! Bokmärket är inte definierat. 2.1 Reservation av minne för variabler... Fel! Bokmärket är inte definierat. 2.2 Kodning av tilldelningar... Fel! Bokmärket är inte definierat. 2.3 Instruktioner för aritmetikoperationer... Fel! Bokmärket är inte definierat. 2.4 Programflödeskontroll... Fel! Bokmärket är inte definierat. 2.5 Funktionsparametrar och returvärden... Fel! Bokmärket är inte definierat. 2.6 Kodgenerering för fält... Fel! Bokmärket är inte definierat. 2.7 Fält som parameter till funktion... Fel! Bokmärket är inte definierat. 2.8 Adressberäkning för flerdimensionella fält... Fel! Bokmärket är inte definierat. 2.9 Sammansatta typer (struct och union)... Fel! Bokmärket är inte definierat. 2.10 Pekare... Fel! Bokmärket är inte definierat. Kapitel 3 Introduktion till Codelite, GCC och debugger GDB... 23 Inledning... 23 3.1 Användning av GDB... 23 3.2 Programutveckling med Codelite... 29 3.3 Test och avlusning med Codelite... 36 Kapitel 4 General Purpose IO... Fel! Bokmärket är inte definierat. Inledning... Fel! Bokmärket är inte definierat. 4.1 General Purpose Input/Output - GPIO... Fel! Bokmärket är inte definierat. Kapitel 5 Synkronisering, alfanumerisk och grafisk display... Fel! Bokmärket är inte definierat. Inledning... Fel! Bokmärket är inte definierat. 5.1 Gränssnitt... Fel! Bokmärket är inte definierat. 5.2 Systemets cykelräknare - SysTick... Fel! Bokmärket är inte definierat. 5.3 Drivrutin för ASCII-display... Fel! Bokmärket är inte definierat. 5.4 Drivrutin för grafisk display... Fel! Bokmärket är inte definierat. 5.5 Synkronisering med grafisk display... Fel! Bokmärket är inte definierat. 4 - Läsprov

Kapitel 6 Undantag och avbrott... Fel! Bokmärket är inte definierat. Inledning... Fel! Bokmärket är inte definierat. 6.1 Undantagshantering i detalj... Fel! Bokmärket är inte definierat. 6.2 Centralenhetens register... Fel! Bokmärket är inte definierat. 6.3 Undantagsprioritet... Fel! Bokmärket är inte definierat. 6.4 Differentierad undantagshantering... Fel! Bokmärket är inte definierat. 6.5 Externa avbrott... Fel! Bokmärket är inte definierat. 6.6 NVIC Nested Vectored Interrupt Controller... Fel! Bokmärket är inte definierat. 6.7 Flera avbrottskällor... Fel! Bokmärket är inte definierat. Kapitel 7 Seriekommunikation... Fel! Bokmärket är inte definierat. Inledning... Fel! Bokmärket är inte definierat. 7.1 Seriell överföring... Fel! Bokmärket är inte definierat. 7.2 USART-kretsen i MD407... Fel! Bokmärket är inte definierat. 7.3 USART med avbrott... Fel! Bokmärket är inte definierat. 7.4 USART med avbrottstyrd buffrad in- och utmatning... Fel! Bokmärket är inte definierat. Kapitel 8 Programbibliotek... Fel! Bokmärket är inte definierat. Inledning... Fel! Bokmärket är inte definierat. 8.1 Kompilatorbibliotek... Fel! Bokmärket är inte definierat. 8.2 Standard C-bibliotek... Fel! Bokmärket är inte definierat. 8.3 Att skapa ett eget bibliotek... Fel! Bokmärket är inte definierat. 8.4 Länkning mot programarkiv... Fel! Bokmärket är inte definierat. Appendix A Länkarscript B S-format C ASCII (UTF-8) representation D GDB-kommandon Läsprov - 5

Arbetsbok för MD407 6 - Läsprov

Programutveckling i assemblerspråk Kapitel 1 Programutveckling i assemblerspråk Inledning Denna arbetsbok innehåller en lång rad övningar som bland annat syftar till att du ska lära dig behärska utveckling av maskinorienterade program i assemblerspråk och programspråket C. I boken behandlas laborationsdatorn MD407 som är uppbyggd kring microcontrollern ST32F407, med en ARM Cortex M4 processor. Arbetsboken har organiserats i kapitel som du arbetar dig igenom i tur och ordning. Du får lära dig att hantera verktyg för utveckling och test av datorprogram. Detta första avsnitt har ägnats helt åt en introduktion till hur du använder utvecklingssystemet ETERM8. Vi behandlar programutvecklingsprocessen, dvs implementering och test av programvara. 1.1 ETERM8 och programutvecklingen ETERM8 är avsett för programutveckling i assemblerspråk och har anpassats för undervisningsändamål. ETERM8 omfattar funktioner för: Textredigering, källtexten skrivs/redigeras med hjälp av en Editor, färgad syntax används för att hjälpa dig upptäcka enklare stavningsfel. Assemblering, källtexten översätts till en laddfil som innehåller programmets maskinkod och data. Test, laddfilen överförs till den inbyggda simulatorn eller till laborationsdatorn MD407 via ETERM8:s terminalfunktion. Programutveckling i assembler skiljer sig inte särskilt mycket från programutveckling i något högnivåspråk. Programmet skrivs i form av källtext, dvs. en textfil som innehåller instruktioner och direktiv till assemblatorn. Då programmet, eller en lämplig del av det, är färdigt måste det översättas till maskinkod innan programmet kan testas i en måldator eller simulator. Översättningen av programmet sker i flera steg med hjälp av olika verktyg. Processen illustreras i figur 1.1. FIGUR 1.1: ÖVERSÄTTNING AV ASSEMBLERPROGRAM TILL EXEKVERBAR KOD Läsprov - 7

Arbetsbok för MD407 Det första steget kallas assemblering (ung. sätta samman ) och utförs av assemblatorn. Assemblatorn översätter programmets källtext till objektkod, till skillnad från källtextens textformat är objektkoden i binärformat. En, eller eventuellt flera objektfiler, kombineras samman av länkaren till en exekverbar fil med elf-format (executable linkable format). Man kan också välja att låta länkaren skapa bibliotek med program som senare kan kombineras på nytt med ytterligare objektkod. För att skapa en exekverbar fil krävs också ett så kallat länkarskript, en textfil där man bland annat samlat information om var maskinkoden ska placeras i måldatorns minne, var i minnet utrymme reserverats för variabler etc. För att kunna överföra en exekverbar fil till laborationsdatorn måste den konverteras till en så kallad laddfil, med ett textbaserat format (s-records) detta görs med ett konverteringsprogram. I laddfilen finns programmet representerat på en form som kan överföras till laborationsdatorn och där tolkas som instruktioner och data. Då programmet, i form av laddfil, överförts till laborationsdatorn MD407, se figur 1.2, kan det exekveras (utföras) och man kan då kontrollera programmets funktion men man kan också använda ETERM8:s simulator för test av program. Till simulatorn kan programmet överföras på såväl S-format som elf-format. FIGUR 1.2: LABORATIONSDATOR MD407 Om du inte redan gjort det så starta nu ETERM8. Tänk också fortsättningsvis på att bilderna som visas i denna bok kommer att avvika mer eller mindre beroende på vilken plattform (Windows, MacOS eller Linux) du använder. På samma sätt kan utseendet avvika beroende på vilket tema, i operativsystemet, man använder. 8 - Läsprov

Programutveckling i assemblerspråk ETERM8 har initialt tre olika arbetsytor med olika flikar: Navigator - fliken Directories används för att ange ett arbetsbibliotek, under fliken Files visas alla filer i arbetsbiblioteket. Messages - i fliken Output visas meddelanden från assemblatorn, fliken Console rymmer ett terminalfönster som används för att kommunicera med laborationsdatorn MD407 via någon USB-port. Den tredje arbetsytan som initialt visar en startsida, används som redigeringsfönster för textfiler. Ytterligare flikar skapas av ETERM8:s debugger, vi återkommer med detaljer efterhand som dessa introduceras. Börja nu med att skapa ett arbetsbibliotek (här D:\mop\lab1) välj själv lämplig plats och namn. Anm. För ditt arbetsbibliotek bör du undvika sökvägar med svenska tecken eller "mellanslag" eftersom vissa programverktyg som ETERM använder inte hanterar dessa korrekt under Windows. Använd Navigator-Directories för att välja arbetsbiblioteket, välj (vänsterklicka) på arbetsbibliotekets namn, högerklicka därefter, en popup med namnet Set as working directory visas, klicka på denna. Växla därefter till fliken Files. Under Files sorteras filerna i arbetsbiblioteket i fyra olika grupper: Assembler source (ändelse.asm), dina källtexter Loadfile (ändelse.s19), laddfil med binär kod/data som överförs till laborationsdator eller simulator Listfile (ändelse.lst) adressinformation tillsammans med assemblerkod, kan ibland vara användbart vid test och felsökning. Filer som inte har någon speciell betydelse för ETERM8 sorteras in under Other files. Läsprov - 9

Arbetsbok för MD407 SKAPA ETT ASSEMBLERPROGRAM Du skapar en ny källtextfil genom att välja File New från menyn. Därefter skriver du in namnet på den fil du vill skapa, skriv nu mom1.asm och klicka på Save. Om du inte anger något filnamnstillägg (eller anger ett annorlunda filnamnstillägg) lägger ETERM8 automatiskt till.asm. Nu skapas ett nytt fönster: ETERM s textredigeringsverktyg skapar ett nytt fönster där du kan redigera din källtext. UPPGIFT 1.1: TEXTREDIGERING Skriv nu in källtext enligt följande: Observera hur texteditorn färglägger din text ("färgad syntax"). Tecknet @ används för att ange att all påföljande text är kommentarer. Kommentarer ignoreras av assemblatorn, tecknet kan förekomma var som helst på en textrad och kommentarer färgas grå. Ett giltigt symbolnamn färgas grönt. Med "giltigt symbolnamn" menas alla kombinationer av teckensträngar där de ingående tecknen är tillåtna för en symbol. Detta innebär självfallet inte att symbolen är korrekt definierad eller refererad. Giltiga instruktioner, namn på ARM-register och assemblerdirektiv färgas blå Konstanter och operatorer färgas röda. Teckenkombinationen '0x' (noll-x) anger att påföljande talvärde ska tolkas på hexadecimal form. Notera speciellt hur instruktionen: LDT R1,=0x40020C00 färgas grön, dvs. tolkas som en symbol. Detta beror på att vi (avsiktligt) stavat instruktionen fel, rätt instruktion ska här vara LDR. Låt felet vara kvar, vi ska strax rätta till det. För att spara filen använder du nu File Save. Tänk på att korrekt färgad syntax inte nödvändigtvis innebär att ditt assemblerprogram är korrekt, det är snarare till för att göra dig uppmärksam på enklare stavfel, syntaxfel etc. Därför kan det hända att du får felmeddelanden även om du stavat såväl instruktioner som operander riktigt. 10 - Läsprov

Programutveckling i assemblerspråk ASSEMBLERING Du assemblerar källtexten genom att: 1. Växla till fliken Files i Navigator fönstret. 2. Öppna Assembler source 3. Välj (vänsterklicka) på filnamnet mom1.asm högerklicka därefter, en popup knapp visas... 4. välj Assemble File alternativt: Från Menyn väljer du Tools Assemble, ett dialogfönster låter dig nu välja den fil du vill assemblera. Utskrifter från assemblatorn visas i sektionen Messages under fliken Output. UPPGIFT 1.2: ASSEMBLERING 1. Assemblera nu filen mom1.asm Assemblatorn kommer att klaga på den felstavade instruktionen. Efter filnamnet, med fullständig sökväg (som kan se annorlunda ut i ditt exempel) skrivs radnummer, därefter typ av fel. Utskriften "Error: bad instruction 'ldt R1,=0x40020C00'" berättar vad vi redan misstänkte, dvs. att instruktionens namn är felstavat. Felutskrift från assemblator 2. Dubbelklicka nu (vänster knapp) på felutskriften. Markören i marginalen pekar ut raden i källtextfilen som genererat felet. 3. Rätta felet (ändra den felaktiga instruktionen till LDR) och assemblera på nytt. Meddelandet No Errors ska nu visas i Output-fliken. Läsprov - 11

Arbetsbok för MD407 Låt oss uppehålla oss vid det program vi skrivit och assemblerat. Detta innehåller såväl kommentarer som instruktioner och assemblerdirektiv. Vi har också definierat flera olika symboler. Programmet beskrivs av följande flödesplaner som steg för steg visar hur "specifikationen" längst till vänster översätts till ett (nästan) komplett assemblerprogram, längst till höger. FIGUR 1.3: FRÅN SPECIFIKATION TILL ASSEMBLERPROGRAM Det färdiga assemblerprogrammet dokumenteras också med förklarande kommentarer: @ alla tecken efter @ betraktas som kommentarer @ mom1.asm @ start: LDR R0,=0x55555555 @ sätt upp port D som utport LDR R1,=0x40020C00 STR R0,[R1] LDR R1,=0x40020C14 @ utport skapar en pekare till port D i R1 LDR R2,=0x40021010 @ inport skapar en pekare till port E i R2 main: LDR R0,[R2] @ laddar 32 bitar från port E i R0 STR R0,[R1] @ skriver innehållet i R0 till port E B main @ absolut programflödesändring (B=branch) Vi ska nu titta närmre på några av de instruktioner vi använt i vårt inledande programexempel. LADDA EN KONSTANT I REGISTER Eftersom alla load-instruktioner är kodade med 16 bitar finns det ingen instruktion där en full 32-bitars adress kan kodas in i instruktionen. I stället tillhandahålls ett PC-relativt adresseringssätt. För att förenkla kodningen tillhandahåller assemblatorn så kallade pseudoinstruktioner som skapar rätt maskinkod. För att ladda en 32-bitars konstant i ett register har vi: ADR Address to register Adderar en konstant till värdet i PC och skriver resultatet till ett generellt register. Syntax: ADD Rd,PC,#<const> @ Generisk form ADR Rd,<label> @ Pseudo instruktion LDR Rd,=<label> @ Alternativ (GNU as) Observera att bara de två sista accepteras av assemblatorn. Rd Destination, generellt register R0-R7. <label> Adressen till en instruktion eller data. Assemblern bestämmer ett värde för offseten så att denna är rättad till WORD-adresser <const> Positiv konstant 0-1020. Endast multiplar av 4 är tillåtna, kodas därför med 8 bitar. EXEMPEL 1.1 Följande instruktioner: start: ADR R1,label LDR R2,=label label: utför exakt samma sak, dvs. placerar adressen label i register R1 och R2. Man kan också ange absoluta adresser som numeriska värden: LDR R1,=0x40020C00 placerar värdet 0x40020C00 i register R1. 12 - Läsprov

Programutveckling i assemblerspråk LADDA EN VARIABEL FRÅN KONSTANT ADRESS LDR Load literal En basadress bestäms genom att en konstant adderas till innehållet i PC. Därefter kopieras ett WORD, från denna adress, till destinationsregistret Syntax: LDR Rt,<label> LDR Rt,[PC,imm] Rt Destination, generellt register R0-R7. <label> Symbolisk adress till data som kopieras till Rt.. imm Positiv konstant 0-1020. Endast multiplar av 4 är tillåtna, kodas därför med 8 bitar. Avståndet mellan referensen (LDR) och definitionen (label) får alltså vara maximalt 1020 bytes, och symbolen label måste finnas på en adress som är jämnt delbar med 4, så kallat rättningsvillkor ( alignment ) eftersom instruktionen kodas på följande sätt: LDR Rd,<label> 0 1 0 0 1 Rd PC-rel offset Registret Rd kan vara R0-R7 och offseten kodas med 8 bitar. Genom att placera två implicita nollor efter offseten utökas det maximala avståndet mellan referensen men kräver samtidigt att label placerats på en fysisk adress i minnet som är jämnt delbar med 4, så kallat word aligned. EXEMPEL 1.2 Assemblerdirektivet.WORD används för att generera en 32-bitars konstant i minnet. För att försäkra oss om att rättningsvillkoret är uppfyllt kan vi placera direktivet.align omedelbart framför symboldefinitionen label..align label:.word 0x11223344 Assemblatorn kommer då att garantera att rättningsvillkoret är uppfyllt genom att eventuellt fylla ut med enstaka bytes så att label hamnar på en tillåten adress. Instruktionen: LDR R0,label kan nu användas för att ladda konstanten (11223344) 16 till register R0. LADDA EN VARIABEL FRÅN EN EVALUERAD ADRESS Då man refererar innehållet på en adress upprepade gånger är det lämpligt att först placera adressen i ett register. Därefter kan man enkelt komma åt innehållet med register-indirekt adresseringssätt. LDR Load immediate En basadress bestäms genom att en konstant offset adderas till innehållet i ett basregister. Därefter kopieras ett WORD, från denna adress, till destinationsregistret. Om konstanten är 0 kan den utelämnas. Syntax: LDR Rt,[Rn,+/-#imm5] LDR Rt,[Rn] Rt Destination, generellt register R0-R7. Rn Basregister för adressberäkningen. +/- Anger positiv eller negativ offset. Om tecken utelämnas tolkas detta som positiv offset. imm5 Positiv konstant 0-124. Endast multiplar av 4 är tillåtna, kodas därför med 5 bitar. Läsprov - 13

Arbetsbok för MD407 EXEMPEL 1.3 Den första instruktionen laddar adressen till en IO-port till register R2. LDR R2,=0x40021010 Nästa instruktion laddar 32 bitar från denna adress: LDR R0,[R2] Man kan läsa påföljande adresser (med 4 bytes intervall) genom att lägga till en offset, exempelvis laddar nu följande instruktion 32 bitar från adress (40021014) 16: LDR R0,[R2,#4] SKRIVA TILL MINNET Data skrivs till minnet med store-instruktionen, STR. En skrivning måste alltid ske indirekt via ett register. Den vanligaste varianten är: STR Store immediate En basadress bestäms genom att en konstant offset adderas till innehållet i ett basregister. Därefter kopieras ett WORD, från källregistret till denna adress. Om konstanten är 0 kan den utelämnas. Syntax: STR Rt,[Rn,+/-#imm5] STR Rt,[Rn] Rt Källa, generellt register R0-R7. Rn Basregister för adressberäkningen. +/- Anger positiv eller negativ offset. Om tecken utelämnas tolkas detta som positiv offset. imm5 Positiv konstant 0-124. Endast multiplar av 4 är tillåtna, kodas därför med 5 bitar. EXEMPEL 1.4 Instruktionsföljden: LDR R1,=0x40021010 STR R0,[R1] skriver innehållet i register R0 till adress (40021010) 16 PROCESSORNS REGISTER I figur 1.4 visas processorns registeruppsättning och en kort beskrivning ges i tabell 1.1. FIGUR 1.4: ARM-PROCESSORNS REGISTER 14 - Läsprov

Programutveckling i assemblerspråk Samtliga register är 32 bitar breda. Generella register för heltal, flyttalsregister, programräknare, två fysiska stackpekare för att kunna skapa separation mellan olika programdelar, ett så kallat länkregister för snabb lagring av återhoppsadress vid subrutinanrop samt ett antal speciella register för status och kontroll. Registeruppsättning Namn Beskrivning R0-R12 Generella register används för aritmetiska, logiska, skift-operationer etc. SP Aktiv stackpekares värde (MSP eller PSP), skillnader mellan stackpekarna behandlas i kapitel 6, till dess kan du utgå från att SP=MSP LR Länk-register, här sparas återhoppsadressen vid subrutinanrop PC Programräknare PSR Processor Status Register innehåller olika statusbitar från heltalsoperationer i de generella registren. FPSR Floating Point Status Register innehåller olika statusbitar från flyttalsoperationer, behandlas i kapitel 7 MSP Master Stack Pointer PSP Process Stack Pointer PRIMASK Speciella register, behandlas i kapitel 6 FAULTMASK BASEPRI CONTROL S0-S31 Generella flyttalsregister, behandlas i kapitel 8 TABELL 1.1: ÖVERSIKTLIG BESKRIVNING AV PROCESSORNS REGISTER 1.2 Simulatorfunktioner Med ETERM:s debugger och MD407-simulator kan du simulera instruktionsutförandet i laborationsdatorn MD407. Du kan också övervaka och manuellt ändra såväl register som minnesinnehåll. PROCESSORNS ANVÄNDARREGISTER Simulatorns registersektion visar registeruppsättningen hos MD407. Eftersom vi återkommer till flyttalsregistren S0-S31 och de speciella registren (PSR, FPSR osv.) senare i denna arbetsbok är det nu i första hand de två första kolumnerna du kommer att använda. FIGUR 1.5: SIMULATORNS REGISTERSEKTION Du kan ändra registrens innehåll manuellt genom att klicka på fönstret för det register du vill ändra och skriva in ett nytt värde, värdet anges på hexadecimal form. Då du ändrat ett registerinnehåll måste du också trycka Enter, för att ändringarna ska registreras i simulatorn. Läsprov - 15

Arbetsbok för MD407 SIMULERING AV PROGRAMEXEKVERING Med debuggerns hjälp kan du få en första inblick i hur assemblerinstruktioner fungerar. Du kan utföra ett assemblerprogram instruktionsvis och i lugn och ro studera effekterna. Glöm inte att spara dina källtextfiler, många moment utgår från att återanvända kod. Under detta moment kommer vi att introducera användningen av debuggern. Först visar vi hur du kan ladda program till simulatorn och utföra programmet instruktionsvis. Du kommer också att se hur man kan koppla kringenheter till simulatorn. STARTA DEBUGGERN Vi ska nu prova programmet mom1.asm. Simulatorn kan startas på olika sätt, 1. I fliken Navigator Files, välj gruppen Loadfile(.s19) 2. Högerklicka på mom1.s19, en popup med två alternativ visas: Open file - om du vill granska laddfilen med en editor Debug in simulator - för att starta simulatorn med denna laddfil alternativt: Välj från menyn Tools Start debugger en dialog låter dig nu välja laddfil. 1. Välj från menyn Tools Start debugger 2. Välj i dialogrutan: mom1.s19 Debuggern har två flikar: CPU/disassembly, MD407-simulatorns olika ARM-register, en bild av det disassemblerade minnesinnehållet dvs. programmet och debuggerns kontrollfunktioner. Memory: MD407-simulatorns minne Eftersom programmet utför in- och ut- matning måste vi dock göra vissa förberedelser innan vi provar programmet. Till simulatorn finns också en fristående del som kallas IO-simulator (Input/Output-simulator). Dess uppgift är att simulera olika omgivningar till laborationsdatorn, dvs. de enheter som inmatning sker från och utmatning sker till. Eftersom IO-simulatorn innehåller olika typer av kringenheter och dessa kan kopplas till olika anslutningar hos MD407 och vi måste göra dessa inställningar manuellt. 16 - Läsprov

Programutveckling i assemblerspråk Välj nu Setup IO-devices: Följande dialogruta öppnas: Till vänster, IO-ports, visas de anslutningar (portar) hos MD407 som kan användas i simulatorn. I mitten, IO-devices, visas de kringenheter som kan anslutas. Till höger visas en bild av den valda kringenheten. För att prova vårt första program, mom1, kopplar vi nu en 8 bitars strömställare (8 bit dipswitch) till den minst signifikanta byten av port E (GPIOE pin 0-7). Märk porten och kringenheten: Klicka därefter på Connect. Strömställarmodulen öppnas. Den är försedd med 8 st. enpoliga knappar som kan ställas i läge on eller off genom att man klickar på dem. Initialt står knapparna i läge off, vilket innebär att motsvarande logiknivå är 0. Genom att klicka en gång ändras läget till on, logiknivån är då 1, klicka en gång till på knappen för att få den att återgå till off, osv. I fönstret skrivs också den aktuella anslutningen ut, i detta fall PE0-7. Fortsätt nu med att ansluta en diodramp (8 segment Bargraph) till den minst signifikanta byten hos port D, GPIOD pin 0-7. Diodrampsmodulen öppnas, den innehåller 8 st. dioder som kopplats till porten. Klicka slutligen OK för att behålla anslutningarna. Läsprov - 17

Arbetsbok för MD407 TEST AV PROGRAM Då vi nu anslutit enheter för såväl in- som utmatning börjar vi bli redo att testa vårt program. Följande knappar används för att kontrollera programexekveringen: Step instruction: Utför en maskininstruktion, kallas också trace, exakt en maskininstruktion utförs. Next instruction: Utför nästa instruktion, skillnaden mot Step instruction är att en tillfällig brytpunkt placeras på nästa adress i det sekventiella programflödet. Detta innebär exempelvis att hela subrutiner kan utföras utan att man behöver stega igenom varje instruktion i subrutinen. Step out: Utför instruktioner till en programflödesändring Step 5 ins/sec: Stega automatiskt, 5 instruktioner per sekund Run, stop at breakpoint: Utför programmet snabbt, respektera brytpunkter Run, ignore breakpoints: Utför programmet snabbt, ignorera brytpunkter Observera nu hur debuggern har märkt den instruktion som står i tur att utföras med en gul bakgrund. Klicka på Step instruction för att utföra denna instruktion. Instruktionen utförs, nästa instruktion märks med gul bakgrund. Notera effekten av instruktionen, register R0 har fått nytt värde. Fortsätt stega tills instruktionen på adress 2000000A märks med gul bakgrund. Notera hur värdet i processorns register R1 och R2 ändrats i registersektionen. Adressen till GPIOD:s indataregister finns nu i R2, adressen till GPIOE:'s utdataregister finns i R1. Ställ nu in värdet 1 på strömställarmodulen genom att klicka på den minst signifikanta biten. Utför nu även nästa instruktion för att läsa ett värde från inporten: LDR R0,[R2,#0] Observera hur register R0 laddas med strömställarmodulens värde Fortsätt nu och utför nästa instruktion: STR R0,[R1,#0] Värdet i register R0 skrivs till ljusdiodrampen. 18 - Läsprov

Programutveckling i assemblerspråk Då du testat ett programs funktion genom att utföra det instruktionsvis kan du också utföra det med något Run-kommandot. Här finns det tre olika varianter, det första alternativet tillåter dig följa programexekveringen i detalj eftersom debuggern uppdaterar vyn mellan varje instruktion. Det båda andra alternativen används för att utföra programmet så snabbt som möjligt, endast programräknaren i registerfönstret uppdateras, det första alternativet, med en gul böjd pil, kontrollerar om det finns brytpunkter i programmet, det andra alternativet ignorerar brytpunkter. BRYTPUNKTER En brytpunkt är ett ställe där programexekveringen avbryts. Brytpunkter är bara meningsfyllda då du använder Run. Du hanterar brytpunktstabellen via debuggerns verktygslist. Brytpunkten kan vara permanent och läggs då in i en brytpunktstabell. Varje gång programmet ska utföra instruktionen på denna adress kommer simulatorn att avbryta exekveringen. Brytpunkten kan också vara tillfällig, programmet exekveras tills denna adress uppträder nästa gång. Brytpunkten tas därefter automatiskt bort av simulatorn. Slutligen finns två speciella brytpunktsfunktioner: Break on IO, då denna aktiverats stoppas programexekveringen då programmet gör någon in- eller utmatning, respektive Break on IRQ, vilken gör att programexekveringen stoppas vid upptakten av avbrottshantering. BRYTPUNKTSTABELLEN I brytpunkstabellen kan du lägga in upp till 20 samtidiga brytpunkter i ditt program. För att bestämma vilka adresser som kan vara lämpliga för brytpunkter kan du granska exempelvis listfilen från ditt program. Brytpunkter kan sättas ut på olika sätt: identifiera instruktionen i simulatorn och högerklicka på dess rad i programfönstret: Go to.. sätter en tillfällig brytpunkt och startar programexekveringen SetBreakpoint sätter en permanent brytpunkt här. I programfönstret märks raderna enligt följande: En aktiv brytpunkt illustreras av röd bakgrund. En inaktiv brytpunkt illustreras av blå bakgrund. Den gula bakgrunden anger vilken instruktion som kommer att utföras näst. Om den instruktion som står i tur att utföras har en brytpunkt visas denna med gul text mot svart bakgrund. Läsprov - 19

Arbetsbok för MD407 Du kan också öppna dialogen för brytpunktstabellen och hantera brytpunkter härifrån: För att lägga till en ny brytpunkt skriver du in adressen i fönstret längst ned till vänster och klickar på Add, exempelvis: För att ta bort en brytpunkt klickar du först på dess nummer i brytpunktstabellen och därefter Remove. Du kan tillfälligt inaktivera en brytpunkt genom att märka av enabled-boxen. SIMULATORNS HANTERING AV MINNET Användningen av adressrummet i en MD407 beskrivs i figur 1.6 FIGUR 1.6: ADRESSRUMMETS ANVÄNDNING 20 - Läsprov

Adressrymden hos MD407-simulatorn används på följande sätt. 0x0800 0000-0x080F FFFF 1 MB Flash 0x2000 0000-0x2001 BFFF 112 kb SRAM 0x4000 0000-0x5FFF FFFF 512 MB Periferikretsar 0xE000 0000-0xFFFF FFFF 512 MB ARM systemregister Adresser utanför dessa block används ej. Programutveckling i assemblerspråk Under fliken Memory kan minnesinnehållet studeras och i vissa fall ändras. Minnesinnehåll visas i block om 128 bytes. Du kan ändra visningsintervallet med hjälp av rullningslisten till höger. Med Lower limit och Upper limit kan du avgränsa det minnesutrymme du vill studera. Du kan också ange en startadress för blocket som ska visas (Display base). Eftar att ha skrivit in en ny adress måste du trycka ned Enter-tangenten för att ändringarna ska få effekt. Du kan också välja om du vill att minnet ska visas som word (32 bitar), halfword (16 bitar) eller byte (8 bitar). READ WRITE MEMORY (RWM) Följande figur visar adressutrymmet 2000 0000 16-2000 007F 16, detta minne är av SRAM-typ, dvs. läs och skrivbart minne. Det skrivbara minnet kan ändras genom att skriva in ett nytt (hexadecimalt) värde. Ändringsbara minnesinnehåll har en vit bakgrund. Minnet kan också visas med 16-bitars format (halfword) eller 8 bitar (byte). READ ONLY MEMORY (FLASH) En annan typ är de minnesareor som är reserverade som ROM-typ (läsbart minne). För denna kategorin minne har fönstren för minnesinnehåll grå bakgrund. Innehållet kan då inte ändras. Läsprov - 21

Arbetsbok för MD407 I ett verkligt system kan sådana minnen normalt sett inte skrivas, (en speciell programmeringsrutin krävs) men i simulatorn vill vi i bland kunna initiera detta minne. Av denna anledning finns knappen Allow changes in RO-memory. Då den är aktiv behandlas ROM som skrivbart minne av simulatorn. PERIFERIKRETSAR OCH SYSTEMREGISTER Adressrymder med periferikretsar och systemregister visas med röd färg mot vit bakgrund. Observera att bara en mycket liten del av dessa adressrymder används. De funktioner som är implementerade i simulatorn beskrivs efter hand. ICKE ANVÄNT MINNE Den sista kategorin i adressrymden är helt enkelt odefinierade block. I simulatorn illustreras dessa med frågetecken mot grå bakgrund. 22 - Läsprov

Introduktion till Codelite, GCC och debugger GDB Kapitel 3 Introduktion till Codelite, GCC och debugger GDB Inledning I de inledande kapitlen har vi använt ett enkelt och grundläggande verktyg för programutveckling i assemblerspråk. Med ETERM8:s enkla debugger tillsammans med MD407- simulatorn har vi sett hur man kan studera registerinnehåll, minnesinnehåll och även följa instruktionsexekveringen i laborationsdatorn. Detta kallas i bland machine level debugging. I detta kapitel introducerar vi betydligt kraftfullare verktyg och utvidgar programutvecklingen till att omfatta även C-program. Kapitlet är viktigt för dina förutsättningar att utföra de uppgifter som ges i resten av arbetsboken. Vi börjar med att ge exempel på hur du kan använda GDB, GNU Debugger, som är avsedd för test, felsökning och felavhjälpning i program. Med GDB tar vi steget upp till source level debugging (SLD) vilket gör att vi kan följa programexekvering och ändringar i processorns register, ändringar i minnesinnehåll etc. utgående från vår källtext. Vi använder samma simulator som tidigare, men gränssnitten är annorlunda. I kapitlet visar vi hur du kommer i gång med GDB och använder några enkla grundläggande kommandon. Det här är dock bara en väldigt liten del av vad du kan göra med GDB men det är bara avsett som en introduktion till SLD och för att du ska förstå fortsättningen Efter detta visar vi hur du kan använda ett komplett utvecklingssystem för test, felsökning och felavhjälpning i C-program. Ramverket för detta (IDE, Integrated Development Environment) heter Codelite och använder såväl GCC, GNU C Compiler, som GDB. Eftersom ett sådant ramverk sköter kommunikationen med GDB är det tillräckligt om du provat på de enkla kommandon hos GDB som du använder här. 2.1 Användning av GDB I programmet SimServer finns samma simulator som du arbetade med i kapitel 1 och 2. Skillnaden är att du nu inte har ETERM8:s debugger som gränssnitt, utan GDB. GDB och SimServer kommunicerar via sockets, kortfattat en metod för processkommunikation i operativsystemet. Utan att gå in på detaljer innebär detta att två program startas med förutsättningen att dom kan utväxla data via en port. Porten anges, i båda programmen i formatet värddator:unikt ID. Om man vill upprätta processkommunikation i samma maskin blir alltid värddatornamnet localhost. Programmet SimServer lyssnar på porten med ID 1234. Den fullständiga kanalen för kommunikation med SimServer blir därför localhost:1234. FIGUR 2.1 Läsprov - 23

Arbetsbok för MD407 UPPGIFT 2.1 Använd ETERM8 och förbered följande enkla program för att undersöka GDB och SimServer. @ gdbtest1.asm start: MOV R0,#0 main: ADD R0,R0,#1 B main Redigera en källtext, gdbtest1.asm med programmet och spara denna. Assemblera och rätta eventuella fel. Du behöver gdbtest1.elf senare. SNABB START MED GDB OCH SIMSERVER Starta SimServer Simulatorn startar och väntar nu på att GDB ska börja kommunicera via porten 1234. Starta GDB Ett konsollfönster med GDB öppnas: GDB identifierar sig och skriver ut sin prompter (gdb) vilket betyder att man kan börja arbeta med debuggern. GRUNDLÄGGANDE KOMMANDON Det första man bör göra är att ändra arbetsbibliotek till det ställe där man har sina filer. I vårt fall där vi tidigare skapade gdbtest1.asm, arbetsbiblioteket: D:\mop\lab1, vi ger därför kommandot: (gdb) cd d:\mop\lab1 GDB svarar: Nu anger man den fil man vill arbeta med. I vårt fall är det objektfilen gdbtest1.elf. I GDB ger vi därför kommandot: (gdb) file gdbtest1.elf GDB svarar: Detta betyder att GDB läst in objektfilen, med symbolinformationen. 24 - Läsprov

Introduktion till Codelite, GCC och debugger GDB För att koppla ihop GDB med vår MD407-simulator SimServer, ger du kommandot: (gdb) target extended-remote localhost:1234 GDB svarar: Med load-kommandot, laddas nu kod och data till SimServer: (gdb) load GDB svarar: Du kan nu låta SimServer göra nödvändiga förberedelser för debugging med kommandot: (gdb) monitor restart Med list-kommandot kan du studera programmets källtext, exempelvis med (gdb) list 1 GDB svarar: Ett annat användbart kommando är info, för att studera processorns registerinnehåll: (gdb) info registers GDB svarar: Är man bara intresserad av ett enstaka registers innehåll anger man det, exempelvis: (gdb) info register r0 GDB svarar: Läsprov - 25

Arbetsbok för MD407 INSTRUKTIONSVIS EXEKVERING För att initiera simulatorn för programexekvering ger du kommandot: (gdb) monitor restart För att utföra en maskininstruktion används kommandot stepi (step instruction): (gdb) stepi GDB låter SimServer utföra en assemblerintruktion och svarar med att skriva ut nästa instruktion, dvs. den som nu står i tur att utföras: Genom att ge argument (antal instruktioner) till stepi kan vi få GDB att utföra flera instruktioner i ett kommando, exempelvis kan vi stega ytterligare 5 instruktioner med kommandot: (gdb) stepi 5 Återigen svarar GDB med att skriva ut den instruktion som står i tur att utföras. Kontrollera ni hur register R0 påverkats av de utförda instruktionerna genom att ge kommandot: (gdb) info register r0 PROGRAMEXEKVERING UPPGIFT 2.2 Använd ETERM8 och förbered nu nästa program för att undersökas med GDB och SimServer. Observera att detta är samma program som i mom1.asm. @ gdbtest2.asm start: LDR R0,=0x55555555 LDR R1,=0x40020C00 @ konfig port D STR R0,[R1] LDR LDR main: LDR STR B R1,=0x40020C14 @ utport GPIO D R2,=0x40021010 @ inport GPIO E R0,[R2] R0,[R1] main Redigera en källtext, gdbtest2.asm med programmet och spara denna. Assemblera och rätta eventuella fel. 26 - Läsprov

Introduktion till Codelite, GCC och debugger GDB Vi övergår nu till programmet i gdbtest2.asm, ge ett nytt file-kommando till GDB: (gdb) file gdbtest2.elf Denna gång kommer GDB att fråga om du verkligen vill byta fil och dess symboltabell, svara 'y' på frågorna: Den nya filen måste också laddas till SimServer: (gdb) load (gdb) monitor restart Prova nu några alternativa list-kommandon, vi har exempelvis två symboler definierade, start och main, ge kommandot: (gdb) list start studera utskriften från GDB, ge därefter kommandot: (gdb) list main Vill du veta mer om list-kommandot, ge GDB kommandot (gdb) help list KOPPLA IO-ENHETER TILL SIMSERVER I SimServer: (Server IO Setup) Koppla en diodramp till port D0-7 Och en strömställare till port E0-7. Klicka OK för att stänga dialogen. Ställ nu in värdet 0x5A på strömställaren. Starta därefter programmet med c- (continue) kommandot: (gdb) c Läsprov - 27

Arbetsbok för MD407 Programmet exekveras nu oavbrutet, du kan verifiera det genom att ändra strömställarens lägen och observera IO-enheterna, strömställarens inställda värde ska kopieras till diodrampen. Du har inte fått någon ny prompter från GDB, du kan därför inte ge några nya kommandon under tiden programmet exekveras av GDB. För att få GDB att avbryta simulatorn ger du kommandot <ctrl-c>: Anm: I detta fall råkade programmet stannas på rad 10, men det kan stoppa på vilken rad som helst i programslingan. Prova med att starta (c = continue): (gdb) c och stoppa ( <ctrl-c> ) programmet några gånger. BRYTPUNKTER För att slippa stega sig fram instruktionsvis till en bestämd punkt i programmet kan man först sätta ut brytpunkter och därefter använda c-kommandot. Vi ska nu starta om progammet och ger därför på nytt kommandon: (gdb) load (gdb) monitor restart Vill vi veta adresserna till instruktionerna i 'main' ger vi kommandot: (gdb) disassemble main GDB svarar nu: Observera att från adress 0x20000010 och framåt finns det instruktioner vi inte känner till från vårt program. Allt är i sin ordning, det är i själva verket data som tolkas som instruktioner av disassemblatorn. Vi kan nu enkelt sätta en bryytpunkt, exempelvis på STR-instruktionen: (gdb) break *0x2000000C GDB svarar: För att få en översikt av brytpunktstabellen ger du kommandot (gdb) info break 28 - Läsprov

Introduktion till Codelite, GCC och debugger GDB GDB svarar: Starta programmet och exekvera fram till brytpunkt med c-kommandot, vid brytpunkten svarar GDB: Med detta har vi gett en introduktion till test och felavhjälpning med källtextinformation. Fortsätt nu på egen hand att bekanta dig med GDB, använd exempelvis program du skrev i kapitel 2. 2.2 Programutveckling med Codelite Vi övergår nu till att beskriva hur du använder Codelite. Vi ger först en översikt av programutvecklingsprocessen, de steg och verktyg som används. Vi beskriver hur en applikation generellt byggs upp och hur den så småningom hamnar i datorns minne för att exekveras. Därefter ger vi ett konkret exempel på hur du skapar, kompilerar-länkar (kallas också "bygger") din applikation för att slutligen kunna testa den. I samband med detta visas hur utgår från en färdig mall som är speciellt anpassad för laborationsdatorn MD407. Slutligen visar vi hur du använder CodeLite tillsammans med debuggern GDB och SimServer för att testa och felsöka i dina program. ÖVERSIKT, VERKTYG OCH UTVECKLINGSPROCESSEN Följande figur ger en översiktlig bild av programutvecklingsprocessen: FIGUR 2.2: PROGRAMUTVECKLINGSPROCESSEN De olika verktygen finns för olika typer av processorer, följande tabell ger namnen på verktygskedjan för ARM. Verktyg Generiskt namn Namn i verktygskedjan för ARM C-kompilator gcc arm-none-eabi-gcc Assemblator as arm-none-eabi- as Länkare ld arm-none-eabi- ld Binärfil konverterare opjcopy arm-none-eabi-opjcopy Dissassembler objdump arm-none-eabi-objdump TABELL 2.1: GCC VERKTYGSKEDJA FÖR ARM Läsprov - 29

Arbetsbok för MD407 SKAPA ETT NYTT WORKSPACE Skapa nu ett nytt Workspace, där du senare lägger till programmeringsprojekt av olika slag. Det är lämpligt att du förbereder ett nytt arbetsbibliotek för detta. Välj Workspace New Workspace från menyn. Välj projekttyp C++ och klicka OK. Tänk då också på att även här undvika mellanslag och specialtecken i sökvägen till arbetsbiblioteket för att undvika senare problem med verktygskedjan. Klicka OK då du valt lämpligt bibliotek. I CodeLites Workspace View kommer nu ditt nya Workspace fram. Här kan du senare succesivt skapa och lägga till nya programprojekt för olika typer av uppgifter, applikationer. Innan vi går vidare med att skapa projekt ska vi titta lite grand på den omgivning våra program ska exekveras. Vi behöver reda ut hur applikationen byggs upp. APPLIKATIONENS UPPBYGGNAD Programkod och data indelas i olika sektioner, följande figur beskriver hur minnesdispositionen för ett komplett program, under exekvering, kan se ut. Figuren förstås bäst mot bakgrund av hur ett program översätts, sparas, laddas till primärminnet och exekveras. Run-Time, existerar endast då programmet exekveras Image, skapas av kompilator/länkare laddas till minnet omedelbart före exekvering stack heap icke initierade data (bss) initierade data (data, rodata) programkod (text) Initial stackpekare Start för dynamisk minnesallokering prefix Programmets startpunkt FIGUR 2.3: MINNESANVÄNDNING FÖR PROGRAM UNDER EXEKVERING 30 - Läsprov

Introduktion till Codelite, GCC och debugger GDB Applikationen består av en oföränderlig del, Image, bestående av programkod och data. Den föränderliga delen kallar vi Run-Time, Såväl programkod som data placeras i namngivna sektioner som kan ha godtyckliga namn. I figuren används exempelvis sektionerna bss, data, rodata och text. Dessa namn används också av GCC vid översättningen. prefix Prefixet, det som också, startupkod, placeras först. Prefixet ingår ofta i den så kallade runtimemiljön som installeras tillsammans med kompilatorn. Ofta kan det finnas olika sådana miljöer och de kallas typiskt crt, (c-run-time). programkod Här placeras all programkod. Den får inte vara självmodifierande, dvs sektionen förutsätts vara read-only. Kompilatorn gör en "bild" av maskinkod som laddas i minnet. Av tradition namnges denna sektion text. initierade data Deklarationer som int a = 2; char array[] = {"String of Text"}; kan användas för att deklarera initierade globala variabler. Innehållet är definierat från start, men kan komma att ändras under exekvering. Kompilatorn måste göra en "bild" även av detta segment för att dessa initialvärden ska kunna laddas till minnet före exekvering. GCC använder regelmässigt två olika segment data och rodata (read-only data) för initierade globala variabler. oinitierade data Deklarationer som: int a; char array[34]; osv, används för att deklarera icke initierade globala variabler. Eftersom variablerna inte har något definierat innehåll från start behöver kompilatorn bara hålla reda på var, i minnet dessa hamnar. Det behövs alltså ingen "bild". Oinitierade variabler placeras därför i ett särskilt segment. Av tradition kallas detta bss, block started by symbol, även namnet COMMON förekommer. stack Stacken används av program under exekvering. Storleken hos stacken bestäms som regel av operativsystemet. heap Heapen benämns ofta det minnesutrymme som reserverats för dynamisk minneshantering. malloc(), free() är exempel på funktioner i standard C-biblioteket som vi ska återkomma till i kapitel 8. Låt oss sammanfatta detta. Vid kompilering av en källtextfil skapas en objektmodul med följande information/innehåll: text-sektion innehållande en "bild" av programkoden. data-sektion innehållande en "bild" av initierade data som kan komma att ändras under programexekvering. rodata-sektion innehållande en bild av initierade data som inte kan ändras under programexekvering. Storleken av bss-sektionen. Symboltabell innehållande alla globala symbolers relativa adresser (offset till sektionens början) i respektive sektion. Observera att alla symboler är relokerbara, dvs absoluta adresser i minnet har ännu ej bestämts. Läsprov - 31

Arbetsbok för MD407 Då programmet ska exekveras utförs följande: 1. Prefix adderas till text-sektionen. 2. Minnesbehov för sektionerna text, data, rodata och bss bestäms. 3. Segmenten relokeras med hjälp av symboltabellen. 4. Minnesbehov för stack och heap bestäms (av operativsystemet). 5. Totala minnesbehovet är nu känt och tillräckligt primärminne kan reserveras för programmet. 6. Programmets initierade segment ("bilder") kopieras till sin respektive plats i primärminnet. 7. Stackpekare initieras och programmet startas (i prefix). Observera speciellt hur förfarandet förutsätter att denna procedur upprepas inför varje exekvering av programmet. Då man arbetar i en kors-utvecklingsmiljö, som med GCC för ARM, har man som regel inget operativsystem som utför detta utan bara en enkel debugger i målsystemet. Detta innebär att moment som normalt utförs enligt någon strategi bestämd av operativsystemet, nu måste utföras manuellt. Följande punkter är speciellt viktigt att iaktta: Stackpekare måste initieras Det finns ingen verklig dynamisk minneshantering tillgänglig Programmet måste laddas, från utvecklingssystem till måldatorsystem mellan varje exekvering, oavsett om det har ändrats eller ej. Detta gäller dock bara om programmet har ett data-segment, eftersom den ursprungliga initieringen kan ha ändrats under en tidigare exekvering av programmet. MINNESANVÄNDNING MD407, APPLIKATION I RWM I figur 2.4 visas hur RWM disponeras i MD407. Vi har valt att placera applikationsprogrammet med start på minnets första adress, 20000000, och uppåt. Applikationens segment placeras i den ordning figuren anger och detta styrs med länkarskriptet (md407-ram.x), (se appendix för detaljer). Övre delen av minnet, är reserverat för MD407:s inbyggda monitor/debugger. Hos MD407 används alltså maximalt 112kB av applikationsprogrammet medan resterande 16 kb har reserverats. FIGUR 2.4: ANVÄNDNING AW RWM I MD407 32 - Läsprov

Introduktion till Codelite, GCC och debugger GDB SKAPA ETT NYTT PROJEKT Du kan skapa ett nytt projekt genom att högerklicka på namnet för ditt Workspace, en popupmeny ger dig då ett antal alternativ, Välj Create New Project En "trollkarl" hjälper dig nu, välj User templates md407-startup. Klicka på Next, namnge därefter projektet. Skriv in projektets namn (här basic_io) och klicka på Next. Nu visas ett sista dialogfönster med projektets verktygsinställningar, klicka på Finish. Två filer kopieras nu till det nya projektbiblioteket: ett enkelt länkarscript och en C-fil där du kan redigera ditt nya program. Det kan vara lämpligt att döpa om filen startup.c till något applikationspecifikt (högerklicka på filnamnet), vi gör dock inte det här. I stället beskriver vi den givna koden i startup.c. Läsprov - 33

Arbetsbok för MD407 SKAPA EN APPLIKATION Vi ska nu skapa en enkel applikation. Den är uppdelad i två delar: En startup-sekvens där alla initieringar som ska göras före anropet av applikationsprogrammet (main) görs, system init, och själva applikationsprogrammet. FIGUR 2.5: ENKEL APPLIKATION MED IN- OCH UTMATNING Då vi använder GCC får vi också tillgång till utvidgningar till programspråket, språktillägg, som är speciellt avsedda att underlätta maskinorienterad programmering. Vi ska nu se tre olika språktillägg, utöver C-språket, som möjliggör arbete direkt med den underliggande hårdvaran: Inline assemblerkod Nakna funktioner Fasta (reserverade) register Medan fördelarna med sådana här språktillägg är uppenbara ska man samtidigt komma ihåg att programmet kan komma att bli mindre portabelt, dvs. möjligheterna att kompilera källtexterna i andra miljöer än GCC kan påverkas. I detta avsnitt behandlar vi inline assemblerkod och nakna funktioner, vi återkommer till reserverade register i ett kommande avsnitt. INLINE ASSEMBLERKOD Det finns ett antal olika ARM-instruktioner (exempelvis. MRS, MSR, SEV, SVC) som helt enkelt inte kan uttryckas i C. Samtidigt är dessa instruktioner nödvändiga om vi exempelvis vill programmera undantagshantering (beskrivs i kapitel 6) för att kunna använda processorns avbrottsmekanismer. Ett uppenbart sätt att hantera detta är att konstruera funktioner (subrutiner) som kräver användning av sådana instruktioner, direkt som assemblerkod, assemblera dessa och länka tillsammans med övrig kod som vi då skrivit i C. Vi måste då tänka på att vi följer de konventioner som gäller för kodgenereringen för att kunna skicka parametrar till funktioner och returvärden i från dessa. Som ett alternativ till att skriva separata assemblerfiler kan vi använda inline assemblerkod. Detta kan dels spara moment i programutvecklingen men ocså ge en bättre överskådlighet av funktioner som annars tenderas att stuvas undan som "svårbegriplig" kod. EXEMPEL 2.1: "IN LINE" ASSEMBLERKOD Följande konstruktion: asm volatile(" NOP "); sätter in en NOP-instruktion i programmet. Om du vill följa strikt C99-standard ska ordet asm skrivas med dubbla understreck: asm volatile(" NOP "); 34 - Läsprov

Introduktion till Codelite, GCC och debugger GDB Ytterligare ett sätt att använda inline-konstruktioner visas i följande exempel på en minimal startup-funktion för ett C-program. EXEMPEL 2.2: MINIMAL STARTUP FÖR MD407 Minimal startupfunktion, i funktionen ges först stackpekaren ett lämpligt värde, därefter anropas själva applikationsprogrammets funktion main. Avslutningsvis placeras en B-instruktion som gör att programexekveringen fortsätter här i all oändlighet om mainfunktionen skulle avslutas. void startup ( void ) { asm volatile( " LDR R0,=0x2001C000\n" " MOV SP,R0\n" " BL main\n" " B. \n" ) ; } Här har vi kompilerat exemplet ovan till assemblerkod och dessutom klippt bort åtskillig text för att se den genererade koden som då blir: startup: push {r7,lr} add r7,sp,#0 LDR R0,=0x2001C000 MOV SP,R0 BL main B. mov sp,r7 pop {r7,pc} Vi ser att kompilatorn lagt ut två inledande instruktioner (prolog) innan vår instruktionssekvens, därefter två avslutande instruktioner (epilog). För en normal funktion hade detta varit välbetänkt men i vårt fall är det helt överflödigt. Vi vill ju att vår startup-funktion bara ska innehålla våra egna instruktioner. För sådana här fall använder man ett så kallat attribut ("naked") som talar om för GCC att vi inte vill ha prolog/epilog i vår funktion: void startup(void) attribute ((naked)); Man kan också styra i vilken sektion man vill att funktionen ska placeras. I detta fall vill vi att funktionen startup placeras först, framför all annan kod i applikationen. Eftersom vi tidigare definierat en speciell sektion ("start_section") för just detta kan vi nu placera vår startup på rätt ställe med attributet section: attribute ((section (".start_section")) Vår färdiga applikationsmall blir därför: attribute ((naked)) attribute ((section(".start_section")) ) void startup ( void ) { asm volatile( " LDR R0,=0x2001C000\n" " MOV SP,R0\n" " BL main\n" " B. \n" ) ; } int main(int argc, char **argv) { } Läsprov - 35

Arbetsbok för MD407 Vi fortsätter nu med main-funktionen. Denna kan implementeras på följande sätt enligt flödesplanen (jämför programmet med mom1.asm i kapitel 1): void app_init ( void ) { * ( (unsigned long *) 0x40020C00) = 0x00005555; } void main(void) { unsigned char c; app_init(); while(1){ c = (unsigned char) *(( unsigned short *) 0x40021010) ; * ( (unsigned char *) 0x40020C14) = c; } } 2.3 Test och avlusning med Codelite UPPGIFT 2.3 Redigera den enkla applikationen tillsammans med startup-proceduren i projektets källtextfil, startup.c. Bygg projektet (basic_io), rätta eventuella fel, om allt är rätt hittills ska filen startup.elf skapas i projektets underbibliotek Debug. Nu ska det vara klart att börja testa programmet, starta SimServer. I CodeLite, välj fliken med källtextfilen startup.c, placera markören på den första raden med exekverbar kod i main-funktionen, tryck F9 (se även menyalternativ under Debugger). Starta nu programmet och exekvera det fram till brytpunkten (F5). Observera hur CodeLite märker ut nästa exekveringspunkt i programmet med en grön pil i marginalen. I SimServer, kopplar du nu upp en DIL-switch till port PE0-7 och en Bargraph till port PD0-7. Använd menyn Debugger, eller verktygsfältets ikoner för att stega igenom programmet, kontrollera att det fungerar som det ska. 36 - Läsprov

Nu ska nu kunna redigera, kompilera en källext och därefter starta GDB från Codelite för att testa ditt program. Momenten är grundläggande för fortsättningen. Du kan nu också passa på att göra några praktiska inställningar för GDB i Codelite, välj: Settings GDB Settings... Introduktion till Codelite, GCC och debugger GDB Här kan det vara praktiskt att välja Automatically set breakpoint at main, så slipper du själv sätta ut den första brytpunkten i programmet: En annan praktisk inställning, under Settings Preferences är att låta Codelite märka upp exekveringspunkten i programmet på ett tydligare sätt, här har vi till exempel angett att Codelite ska visa aktuell rad mot en röd bakgrund för att vi lättare ska kunna identifiera den. Som ett kompement till att styra GDB med snabbvalstangenter kan man använda verktygslisten (toolbar). Välj View Show Toolbar för att visa verktygslisten om den inte redan syns. Med undermenyn View Toolbars väljer du sedan de verktygsliter du vill ha synliga. Kontrollera att Debug Toolbar, finns med bland dessa. Verktygslist för GDB i CodeLite: I redigeringsläge används ikonen för att starta GDB. Då debuggern startats används samma ikon för att återstarta exekvering av programmet. Detta motsvarar c- (continue) kommandot Avsluta GDB och återgå till redigeringsläge, detta motsvarar quit-kommandot Avbryt exekverande program, används då programmet startats med c-kommandot. Skickar <ctrlc> till GDB för att stoppa det exekverade programmet Återstarta program, observera att denna funktion inte används vid kors-utveckling eftersom CodeLite då försöker starta programmet direkt. Skulle du av misstag använda denna funktion med ARM-versionen måste du starta om GDB. Visa aktuell rad, efter att ha avbrutit ett exekverande program kan det hända att markören för exekveringspunkten inte visas i textredigeringsfönstret. Använd denna funktion för att åtgärda detta. Utför nästa sats i programmet, om nästa sats är ett funktionsanrop kommer GDB att stega in i funktionen Utför nästa rad i programmet, om raden exempelvis innehåller ett funktionsanrop kommer hela funktionen att utföras och nästa rad i källtexten blir den nya exekveringspunkten. Exekvera färdigt aktuell funktion Läsprov - 37

Arbetsbok för MD407 Då du startat GDB skapar Codelite ett separat fönster 'Debugger' med en rad olika flikar. Dissassemble: Då programmet stannats vid en brytpunkten kan du också växla till dissassembleringsfliken: Anm: I dissassemble-fönstret översätter CodeLite tecknet <TAB> med \t i stället för tabulaturen. Detta kan vara förvirrande i början. I fönstret till vänster ser du en dissassemblering av programmet där exekveringspunkten är uppmärkt. Du kan låta GDB utföra en assemblerinstruktion i taget (motsvarar stepi) med kommandot Next Instruction (Ctrl-F10). Locals: här får du en översikt av de lokala variablerna och deras innehåll. Du kan också ändra ett värde genom att högerklicka på raden med variabeln. Watches: Används för att övervaka variabler med permanent lagringsplats i minnet. Lägg till den variabel du vill övervaka genom att klicka på det gröna '+'-tecknet i övre vänstra hörnet och därefter skriva in variabelns namn. Memory: Används för att övervaka sammanhängande minnes innehåll. Tänk på att adressen ska skrivas med prefix '0x' om den anges på hexadecimal form. 38 - Läsprov