LEU240 Mikrodatorsystem

Relevanta dokument
Digital- och datorteknik

Digital- och datorteknik

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

LEU240 Mikrodatorsystem Att placera program i FLASHrespektive

Att använda pekare i. C-kod

F5: Högnivåprogrammering

F5: Högnivåprogrammering

Digital- och datorteknik

Lösningar till tentamen i EIT070 Datorteknik

Fortsä'ning Pekare. Ulf Assarsson. Originalslides av Viktor Kämpe

Lathund. C för inbyggda system

Övning2 Datorteknik, HH vt12 - Programmering

Assemblerprogrammering del 1

7) Beskriv tre sätt att överföra parametrar mellan huvudprogram och subrutin.

Lathund. C för inbyggda system

Programmering i maskinspråk (Maskinassemblering)

CPU. Carry/Borrow IX. Programräknare

Kontrollskrivning Mikrodatorteknik CDT S2-704

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

CE_O3. Nios II. Inför lab nios2time

I denna laboration undersöker vi hur aritmetiska beräkningar utförs. Vi tittar på olika variabeltyper: 8-bitars, 16-bitars, 32-bitars och flyttal.

Assemblerprogrammets struktur; exempel

Programmering av inbyggda system. Kodningskonventioner. Viktor Kämpe

Datorteknik 2 (AVR 2)

Maskinorienterad Programmering 2010/11

Fortsä'ning Pekare. Ulf Assarsson. Originalslides av Viktor Kämpe

Digital- och datorteknik

Maskinorienterad programmering

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

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

Assemblerprogrammering för ARM del 2

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

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

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

#include <pic.h> #include <sys.h> char LEFT,RIGHT,MOTORHASTIGHET;

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

Institutionen för elektro- och informationsteknologi, LTH

Datorteknik. Föreläsning 2. Programmering i C och assembler MIPS instruktionsarkitektur. Institutionen för elektro- och informationsteknologi, LTH

Mål. Datorteknik. Innehåll. Vad händer med en add-instruktion? Vad händer med en add-instruktion. Instruktioner som bitmönster i minnet

Övningsuppgifter STYRNING - i Mikrodatorteknik för U2 2010

Laboration 2 i Datorteknik- Assemblerprogrammering II

Övningsuppgifterna i kapitel F avser FLIS-processorn, vars instruktioner och motsvarande koder definieras i INSTRUKTIONSLISTA FÖR FLISP.

Assemblerprogrammets. struktur; exempel

Assemblerprogrammering för HCS12

Tentamen med lösningsförslag

TSEA28 Datorteknik Y (och U)

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

Agenda. Arrayer deklaration, åtkomst Makron Flerdimensionella arrayer Initiering Strängar Funktioner och arrayer. Övningar nu och då

Maskinorienterad programmering

Maskinorienterad programmering

Institutionen för elektro- och informationsteknologi, LTH

Tentamen med lösningsförslag

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

Maskinorienterad programmering. Mekatronikingenjör åk 2/ lp 3. Lars-Eric Arebrink. Av institutionen utgiven. vid flera tillfällen.

EDA480/EDA485 - Maskinorienterad programmering, tentamen 2006-xx-xx 1(7)

TDIU01 - Programmering i C++, grundkurs

Enkla datatyper minne

DATORTEKNIK Laboration: 277 Tutorial för IAR Embedded Workbench och C-Spy mot MC68HC11 i Assembler och C

Stack och subrutiner Programmeringskonventionen

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

Lösningar till tentamen i EIT070 Datorteknik

Laboration 4: Knappstuds Drivrutiner för att eliminera störningar.

EDA Digital och Datorteknik

Minnen delas in i två huvudgrupper, permanenta och icke permanenta. Non-volatile and volatile.

Programexempel för FLEX

Extrauppgifter för CPU12

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

Laboration 3 i Digital- och Mikrodatorteknik. Utvecklingssystemet MPLAB IDE Grundläggande assemblerprogrammering för PIC

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

Datorteknik TSIU02 Lab 2 Morsesändare v0.7

Assemblerprogrammering

Programmering i maskinspråk (Maskinassemblering)

Digital- och datorteknik

Tentamen med lösningsförslag

Lathund. Pacific C för MS-DOS

Programmering av inbyggda system 2014/2015

Föreläsning 10. Pekare (Pointers)

Övning från förra gången: readword

Tillämpad digital signalbehandling Signalprocessorn Statiska moduler och buffrar

Ansvarig lärare: Olof Andersson, Telefon (besöker skrivsalen)

Föreläsning 2. Operativsystem och programmering

TSEA28 Datorteknik Y (och U)

Maskinorienterad programmering. Mekatronikingenjör åk 2/ lp 3. Lars-Eric Arebrink. Av institutionen utgiven. Lars-Eric Arebrink

Det finns många flaggor till g++,

TDIU01 - Programmering i C++, grundkurs

Digital- och datorteknik

Systemkonstruktion LABORATION REALTIDSPROGRAMMERING

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

Skizz till en enkel databas

Laboration 1 i Datorteknik. Utvecklingssystemet IAR Embedded Workbench Grundläggande assemblerprogrammering för ARM

TDDC76 - Programmering och Datastrukturer

Tentamen i EIT070 Datorteknik

Övningsuppgifter i Mikrodatorteknik 4p/5p

Hantering av textsträngar och talsträngar. William Sandqvist

Programmering av inbyggda system. Pekare och Arrayer. Viktor Kämpe

Exempel på tentamen 1

Arduinokurs. Kurstillfälle 4

Datorteknik Övningsuppgifter

Anteckningar 1: Grundläggande saker

Transkript:

Institutionen för data- och informationsteknik 2011-10-11 LEU240 Mikrodatorsystem Vi har tidigare i olika sammanhang sett att det är önskvärt att kunna använda ett högnivåspråk som C för att skriva program för vår mikrokontroller och därmed undvika den mer otympliga assemblerprogrammeringen. Låt oss se hur vi stegvis kan gå över från assemblerkod till C- kod. Vi skall studera ett mycket enkelt exempel som samtidigt innebär hantering av externa portar som ligger minnesmappade till fasta adresser och därför i C måste adresseras med hjälp av pekare till dessa adresser. Genomgången kommer inte att behandla hantering av interrupt i C. Vi kommer att återkomma till detta senare. Antag att vi vill använda labsystemet MC12 för att läsa inporten PORTB (adress $0600) på experimentkortet ML4 och skriva resultatet av läsningen till utporten PORTA (adress $0400) på samma kort. Vi vill göra läsningen och skrivningen kontinuerligt, dvs gång efter gång. I assembler skulle vi skriva Kod 1 ORG $1000 start: LDAA $0600 STAA $0400 BRA start Kod 1 och assemblera den via Eterm. ORG-direktivet anger den minnesadress där programstarten skall placeras och resten av programmet hamnar då på efterföljande adresser. Adressen $1000 är den lägsta adressen i MC12:s RAM-minne och är därför lämplig som startadress för programmet. Låt oss nu flytta över denna kod till utvecklingsmiljön XCC. I denna miljö kommer vi att länka in en startup-fil (_startup.s12) före vår programkod. Denna startup-fil är skriven i assembler och sätter upp processorns grundkonfiguration och initierar en enkel seriekommunikation så att vi kan låta en applikation skriva meddelanden till XCC:s terminalfönster. Vi återkommer till denna fil i annat sammanhang. Vi måste dock redan här känna till att denna fil efter initieringen avslutas med hopp till labeln _main och det måste då här innebära ett hopp till vår programkod. Denna label måste då ligga först i vår programkod så att programkoden CHALMERS TEKNISKA HÖGSKOLA Institutionen för data- och informationsteknik Sida 1 Avdelningen för datorteknik Besöksadress: Rännvägen 6 412 96 Göteborg

anropas efter initieringen. Vi återkommer lite senare till varför labeln inleds med en understrykning (_). Samtidigt kommer länkarskriptet (default.lsc) som styr hur koden skall länkas ihop och var den skall placeras i minnet att ta hand om minnesallokeringen. Vi återkommer även till denna fil. Startup-filen kommer av länkaren att placeras med start på adress $1000 i minnet och vår kod kommer att placeras på nästföljande adress efter startupkoden. Vilka adresser vårt program placeras på är nu ointressant eftersom länkaren kommer att sköta om hoppet från startup-kod till vårt programavsnitt. Då detta nu sköts av länkarskriptet så skall vi i vår programkod Kod 1 ta bort ORG-direktivet samtidigt som vi ersätter start-labeln med labeln _main. Vi får Kod 2 define _main _main: LDAA $0600 STAA $0400 BRA _main Kod 2 segment bss Som synes har vi även infört ett define-direktiv. Detta för att labeln _main skall vara synlig i resten av projektet. Segmentdeklarationen för att skapa ett bss-segment för oinitierade variabler kan synas omotiverad men vi måste införa denna deklaration då länkaren förutsätter att det finns ett bss-segment. Detta sätts i normala fall upp av C-kompilatorn men här körs inte C-kompilatorn utan bara assemblatorn, då vi bara har en assemblerfil, och bss-segmentet kommer inte att sättas upp om vi inte anger det explicit. Låt oss nu börja att steg för steg överföra koden till C. Vi börjar med att införa ett huvudprogram, en main()-rutin. Då denna rutin kompileras så sker detta genom att C-koden först översätts till assembler och rutinens namn, här main, kommer att ersättas av en label med samma namn men föregången av en understrykning (_) för att särskilja den från lablar som kommer från assemblerkod som vi själva har skrivit. Det betyder att här kommer den till assembler översatta main-rutinen att inledas av labeln _main precis som i Kod 2 och den kommer då att anropas av startup-rutinen. Vi startar kodöversättningen med att införa huvudprogrammet och behålla vår assemblerkod och helt enkelt skriva vårt program som inline-assembler. Vi får Kod 3 asm(" LDAA 0x0600"); asm(" STAA 0x0400"); asm(" BRA _main"); Kod 3 Lägg märke till de dubbla understrykningarna i kommandot asm. Lägg också märke till att de assembleruttryck som saknar label måste inledas med ett mellanslag (eller ett tabsteg). Dessa uttryck måste precis som i vanlig assemblerkod vara intabbade för att inte tolkas som sida 2

lablar. Observera också att vi har utnyttjat rutinens namn som återhoppsadress i loopen samt att vi skriver hexadecimala tal via förstavelsen 0x och inte via $. Det senare gör vi för att förstavelsen 0x fungerar både i assembler och C medan förstavelsen $ bara fungerar i assembler. För att göra koden lite mer läsbar så kan vi börja med att deklarera portadresserna som konstanter med begripliga namn, Kod 4 #define ML4_PORTB 0x0600 #define ML4_PORTA 0x0400 Lägg märke till att assemblerdirektiven ML4_PORTB EQU 0x0600 ML4_PORTA EQU 0x0400 Inte fungerar i C, däremot fungerar #define-direktiven både i assembler och C varför det är lämpligt att alltid använda dess. asm(" LDAA %a",ml4_portb); asm(" STAA %a",ml4_porta); asm(" BRA _main"); Kod 4 Lägg märke till att konstanterna inte kan skrivas in direkt i inline-assemblerkoden utan måste läggas till som ett argument. Detta beror på att koden i inline-uttrycket kommer att överförs till assemblatorn som en textsträng och namnen skulle om de skrivits in direkt i assemblerkommandona då bli delar av textsträngen och inte tolkats som våra definierade konstanter, dvs som adresser. Nästa steg i förenklingen kan vara att samla alla deklarationer rörande HC12 i en h-fil som vi inkluderar. h-filen skulle här då ha ett innehåll enligt Kod 5 #define ML4_PORTB 0x0600 #define ML4_PORTA 0x0400 Kod 5 Låt oss kalla filen HC12.h. Vår programkod blir nu då Kod 6 sida 3

asm(" LDAA %a",ml4_portb); asm(" STAA %a",ml4_porta); asm(" BRA _main"); Kod 6 Delen..\ i include-kommandot betyder att filen inte ligger i den aktuella projektkatalogen utan ett steg uppåt i katalogstrukturen. Vi gör detta för för att filen enkelt skall kunna användas av alla projekt i aktuellt workspace. Vi går vidare och gör den första övergången till C genom att skriva evighetsloopen som en while-loop i C, Kod 7 asm(" LDAA %a",ml4_portb); asm(" STAA %a",ml4_porta); Kod 7 Förfarandet är välkänt från C och kräver väl knappast någon kommentar. Låt oss nu lämna inline-assembler och i stället skriva assemblerkoden som en subrutin i assembler, en rutin som vi anropar från main-funktionen. Vi behöver alltså dels en C-fil med huvudprogrammet enligt Kod 8 asm(" JSR start"); Kod 8 och dessutom en assemblerfil med subrutinen i Kod 9 sida 4

USE "..\HC12.h" define start entry start start: LDAA ML4_PORTB STAA ML4_PORTA Kod 9 exit start define-direktivet behövs för att labeln start skall vara synlig globalt. entry- och exit-direktiven används av debuggern och inte nödvändiga för själva programmet. Observera att samma h-fil med definitioner kan användas i både C och assembler, detta tack vara att vi använder #define-direktiv som är tillåtna i både C och assembler och inte assembler-skrivsättet med EQU som inte fungerar i C. Lägg märke till att i assembler inkluderas h-filen via USE-direktiv och inte via #includedirektiv. Lägg också märke till att vi har återinfört labeln start som anropslabel för vårt subrutinanrop. Låt oss gå ytterligare ett steg genom att skriva subrutinanropet med C-syntax, Kod 10 start(); Kod 10 Som vi minns från tidigare så kommer funktionsnamnet start på den anropade funktionen att översättas till en label som inleds med en understrykning (_) då koden kompileras till assembler, dvs den blir _start vilket gör att vi måste ändra labelnamnet i subrutinen genom att inleda labeln med understrykningen, Kod 11 sida 5

USE "..\HC12.h" define _start entry _start _start: LDAA ML4_PORTB STAA ML4_PORTA exit _start Kod 11 Vi går nu över helt till C genom att införa pekare för att adressera de fysiska adresserna till våra portar. Samtidigt tar vi bort subrutinen då vårt huvudprogram nu ändå blir bara en rad långt. Vi bygger alltså vidare på Kod 7. Vi får Kod 12 *((unsigned char *)(0x0400))= =*((unsigned char *)(0x0600)); Kod 12 Raden med pekarna är medvetet delad i två delar för att öka läsbarheten. Även här kan vi naturligtvis använda våra konstantdeklarationer för adresserna som används i pekarna, Kod 13 *((unsigned char *)(ML4_PORTA))= =*((unsigned char *)(ML4_PORTB)); Kod 13 Vi ser att dessa pekarkommandon är ganska komplicerade och långa. Då vi använder dem så är risken mycket stor att vi skriver fel och blandar ihop alla asterisker och parenteser. Låt oss därför deklarera makron som kan ersätta våra pekare. De portar vi hanterar har 8 bitar så vår pekare skall vara av typen char. Då vi i de flesta fall skall hantera ett bitmönster och inte ett sida 6

8 bitars tal med tecken så är datatypen unsigned char lämplig eftersom vi på detta sätt undviker att talet (bitmönstret) teckenkompletteras på ett felaktigt sätt. Vi får Kod 14 #define REG8(x) *((unsigned char *)(x)) REG8(ML4_PORTA)=REG8(ML4_PORTB); Kod 14 Även här är det lämpligt att samla våra makrodeklarationer i en h-fil som kan användas av alla projekt, dvs vi lägger h-filen en katalognivå upp. Eftersom det också kan förekomma att vi adresserar 16 och eventuellt 32 bitars objekt så kan vi här också deklarera REG16 och REG32 med hjälp av datatyperna unsigned short respektive unsigned long. Det är i alla lägen lämpligare att använda short och long i stället för int då short alltid är 16 bitar och long alltid är 32 bitar medan int kan vara 16 eller 32 bitar beroende på utvecklingsmiljö. Vi får Kod 15 #include../hc12.h #include../reg_macro.h REG8(ML4_PORTA)=REG8(ML4_PORTB) Kod 15 Där h-filen reg_macro.h då har innehållet enligt Kod 16 #define REG8(x) *((unsigned char *)(x)) #define REG16(x) *((unsigned short *)(x)) #define REG32(x) *((unsigned long *)(x)) Kod 16 I och med detta avslutar vi övergången från assembler till C. sida 7