Övning 5

50
William Sandqvist [email protected] Övning 5 Parallellport, Timer

Upload: jennifer-jenkins

Post on 03-Jan-2016

43 views

Category:

Documents


0 download

DESCRIPTION

Övning 5. Parallellport, Timer. Datorteknik övning 5. Repris: Minnesdisposition. Gles adressrymd Endast en liten del av minnet är utbyggt. (vanligt för inbyggda system). code motsvarar .text. Mellan adresserna 0x800 till 0xA20 finns I/O-kretsar – med allt det roliga på DE2-kortet. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Övning 5

William Sandqvist [email protected]

Övning 5

Parallellport, Timer

Page 2: Övning 5

William Sandqvist [email protected]

Datorteknik övning 5

Page 3: Övning 5

William Sandqvist [email protected]

Repris: Minnesdisposition

Gles adressrymd

Endast en liten del av minnet är utbyggt.

(vanligt för inbyggda system)

Mellan adresserna 0x800 till 0xA20 finns I/O-kretsar – med allt det roliga på DE2-kortet

code motsvarar.text

Page 4: Övning 5

William Sandqvist [email protected]

IO-adresserna är speciellaÄven om IO-enheternas register adresseras som vanligt minne så har dom ju helt andra egenskaper än vad vanligt minne har!

Om man skriver talet 17 till DE2-kortets toggle-switchar, så är det ingen magisk kraft som förflyttar dom till ett läge som motsvarar talet 17!

Om Du däremot ställer switcharna för hand så att det motsvarar talet 17 så kommer man att kunna läsa talet 17 på denna minnesadress.

I C-program bör man använda ordet volatile (flyktigt) om sådana minnesadresser. Då talar man om för kompilatorn att den inte kan räkna med att ett lagrat tal på en sådan minnesadress är det man får tillbaka om man senare läser adressen!

Page 5: Övning 5

volatile ?

William Sandqvist [email protected]

Eftersom I/O-enheter inte är riktiga minnen – det kan verka som om innehållet kan ändras ”av sig självt” – så kan man vid programmeringen av processorn behöva ”hjälpa” kompilatorn att

förstå detta genom att deklarera dem som volatile ( = flyktiga ) i sina C-program.

Har till exempel processorn ett cache-minne är det viktigt att man läser klock-kretsen direkt och inte några äldre ”cachade” tider!

Periferienheter, I/O, ansluts ofta till en CPU som om dom vore minneskretsar (fast med bara ett fåtal ”minnesceller”). Ex. en realtidsklock-krets – håller reda på tid och datum. Den styrs/avläses från 8 inbyggda register.

Page 6: Övning 5

William Sandqvist [email protected]

5.1 de2_pio_toggles18IO är mappade till minnesadresser. 0x850 … 0x85C

Page 7: Övning 5

William Sandqvist [email protected]

5.1 inmatning från ”toggles” Get_Data()

.equ toggles18, 0x850 # toggles18’s adress .text # Datasegmentet .align 2 .global Get_Data # label synligt utanför filenGet_Data: movia r8,toggles18 # adressen till toggles i R8 ldw r2,0(r8) # läs toggles till R2 movia r8,0x3ffff # mask med 18 ettor (movia) and r2,r2,r8 # maska bort oanvända bitar ret

int Get_Data( void );

Page 8: Övning 5

William Sandqvist [email protected]

5.1b Get_Data() i C

#define TOGGLES18 ( (unsigned int *) 0x850 )

int Get_Data( void ){ volatile unsigned int * toggles18 = TOGGLES18 ; unsigned int tmp = *toggles18; return( tmp & 0x3ffff );}

int Get_Data( void );

Page 9: Övning 5

William Sandqvist [email protected]

5.2 de2_pio_geenled9IO är mappade till minnesadresser. 0xA10 … 0xA1C

Page 10: Övning 5

William Sandqvist [email protected]

5.2 Utmatning till ”greenled” Green_Light()

.equ greenled9, 0xA10 # greenled9’s adress .text # Datasegmentet .align 2 .global Green_Light # label synligt utanför filenGreen_Light: andi r4,r4,0x1ff # 0:ställ oanvända bitar movia r8,greenled9 # adressen till greenled i R8 stw r4,0(r8) # skriv till LED ret

void Green_Light( int );

( stwio r4, 0(r8) om processorn har cacheminne )

Page 11: Övning 5

William Sandqvist [email protected]

5.2 b C-kod Green_Light()

#define GREENLED9 ( (unsigned int *)0xa10 )

void Green_Light(int lightbits){ volatile unsigned int * greenled9 = GREENLED9; unsigned int temp = lightbits & 0x1ff; * greenled = temp; return;}

void Green_Light( int );

Page 12: Övning 5

William Sandqvist [email protected]

de2_pio_redled18IO är mappade till minnesadresser. 0x810 … 0x81C

Page 13: Övning 5

William Sandqvist [email protected]

5.3 SjusegmentdisplayerIO är mappade till minnesadresserna 0xA00 och 0x9F0

Page 14: Övning 5

William Sandqvist [email protected]

5.3 Segmentöversikt

Page 15: Övning 5

William Sandqvist [email protected]

5.3 Teckenöversikt

Page 16: Övning 5

William Sandqvist [email protected]

Kan Du nu gissa varför simulatorn redovisar att alla oanvända register innehåller ”deadbeef” (dökött)?

nörd-humor …

Page 17: Övning 5

William Sandqvist [email protected]

5.3 Siffran ”0”

Page 18: Övning 5

William Sandqvist [email protected]

5.3 Siffran ”1”

Page 19: Övning 5

William Sandqvist [email protected]

5.3a omvandling hex7seg()

.data

.align 2 # ev. praktiskt att börja på adress delbar med 4TABLE: # gör en tabell som anger tända och släckta segmentnoll: .byte 0b00111111 ett: .byte 0b00000110 tvaa: .byte 0b01011011 tre: .byte 0b01001111fyra: .byte 0b01100110fem: .byte 0b01101101sex: .byte 0b01111101sju: .byte 0b00000111atta: .byte 0b01111111nio: .byte 0b01100111A: .byte 0b01110111b: .byte 0b01111100c: .byte 0b01011000d: .byte 0b01011110E: .byte 0b01111001F: .byte 0b01110001

ASM-funktion som omvandlar en hex-siffra till motsvarande 7-bitskod (för utmatning på 7-segmentdisplay).

Tabellen gäller aktivt hög lysdiodsdisplay

- För den elektronikintresserade …

Page 20: Övning 5

William Sandqvist [email protected]

5.3a omvandling hex7seg()

.text

.align 2

.global hex7seghex7seg: movia r2, TABLE # nu pekar r2 på 0(TABLE) andi r8, r4, 0xF # maska fram 4 LSBits add r2, r2, r8 # nu pekar r2 på ”byte-offset”(TABLE) ldb r2, 0(r2) # nu innehåller r2 koden! # andi r2, r2, 0x7F # onödigt ety LDB gör SignExtend av 0 ret # men det här blev ju lätt!

Page 21: Övning 5

William Sandqvist [email protected]

5.3b omvandling hex7seg()

int tabell[] = { 0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0e };

int hex7seg( int hex){ register int tmp = hex & 0xf; return tabell[ tmp ];}

C-funktion som omvandlar en hex-siffra till motsvarande 7-bitskod (för utmatning på 7-segmentdisplay).

Tabellen gäller aktivt låg lysdiodsdisplay

- För den elektronikintresserade …

Page 22: Övning 5

William Sandqvist [email protected]

5.4 Utmatning 4 st 7-segment siffrorvoid PutLow7SegDisp( int );

.equ hex_low28,0x9f0 # adressen till hex_low28 .text # Datasegmentet .align 2 .global PutLow7SegmDisp # label synligt i andra filerPutLow7SegmDisp: movia r8,hex_low28 # adressen till hex_low i R8 stw r4,0(r8) # skriv till 4 st 7-segm siffror ret

Page 23: Övning 5

William Sandqvist [email protected]

Simulatorn har inga 7-segmentdisplayer?

Ett hjälpmedel kan vara att låta utskriften i console-fönstret efterlikna 7-segmentdisplayen!

Programmet: put_hexsim(in_value)är skrivet för att uppföra sig exakt som displayen kommer att göra vid laborationen.

– Fungerar det med simulatorn, är chansen stor att ditt program även fungerar vid laborationen!

Page 24: Övning 5

William Sandqvist [email protected]

5.5 toggles 4 7-Segment display

Page 25: Övning 5

William Sandqvist [email protected]

5.5 toggles 4 7-Segment displaymain: # main kör evighetsloop – returnerar ej

call GetData # hämta värde från toggles, R2

mov r16,r2 # spara värdet i R16 mov r4,r2 # kopiera värdet till R4

call hex7seg # kodomvandling 1:a siffran (C-funktion) mov r17,r2 # spara resultat i R17

srli r4,r16,4 # skifta fram andra hex-siffran call hex7seg # kodomvandling 2:a siffran slli r8,r2,7 # skifta fram till nästa 7 bitar or r17,r17,r8 # lägg till 7 skiftade bitar

# fortsättning följer ...

Page 26: Övning 5

William Sandqvist [email protected]

srli r4,r16,8 # skifta fram tredje hex-siffrancall hex7seg # kodomvandling 3:e siffranslli r8,r2,14 # skifta fram till nästa 7 bitaror r17,r17,r8 # lägg till de skiftade 7 bitarna

srli r4,r16,12 # skifta fram fjärde hex-siffrancall hex7seg # kodomvandling 4:e siffran slli r8,r2,21 # skifta fram till nästa 7 bitaror r17,r17,r8 # lägg till de skiftade 7 bitarna

mov r4,r17 # kopiera till R4, parametercall PutLow7SegmDisp # skriv på displayen

br main # main är evighets-loop

5.5 toggles 4 7-Seg forts.

Page 27: Övning 5

William Sandqvist [email protected]

call hex7seg

+

Page 28: Övning 5

William Sandqvist [email protected]

call hex7seg

>> 4

<< 7

+

Page 29: Övning 5

William Sandqvist [email protected]

call hex7seg

>> 8

<< 14

+

Page 30: Övning 5

William Sandqvist [email protected]

call hex7seg

<< 21

+

>> 12

Klart!

Page 31: Övning 5

William Sandqvist [email protected]

int main( void ){ unsigned int temp; while( 1 ) { temp = Get_Data(); Red_Light( temp ); fixandshow( temp ); }}

5.5 b C-kod 4 7-Segment

void fixandshow( unsigned int bitstoshow ){ unsigned int hexresult; hexresult = hex7seg( bitstoshow ); hexresult = hexresult | hex7seg( bitstoshow >> 4 ) << 7); hexresult = hexresult | hex7seg( bitstoshow >> 8 ) << 14); hexresult = hexresult | hex7seg( bitstoshow >> 12 ) << 21); PutLow7SegDisp( hexresult ) }

Page 32: Övning 5

William Sandqvist [email protected]

5.6 Nios II Timer

Page 33: Övning 5

William Sandqvist [email protected]

timer_1IO är mappade till minnesadresser. 0x920 … 0x934

Page 34: Övning 5

William Sandqvist [email protected]

5.7 Delay-rutin med timerDelay:

starta timer

Loop:

läs timer-status registret undersök timeout biten

inget ”timeout” loopa igen om det var ”timeout” nollställ timeout biten gör retur från subrutinen

Huvudprogram:

klock-tick huvudprogrammet skriver ut tiden huvudprogrammet anropar delay

huvudprogrammet går i en evighetsslinga

Page 35: Övning 5

William Sandqvist [email protected]

5.7 Problem med ”enkel” delay

Page 36: Övning 5

William Sandqvist [email protected]

5.7 Lösning: continuous mode

• Timern startar om sig själv vid timeout

• Om programmet hinner läsa och 0-ställa timeout biten (inom nedräkningstiden) blir tidmätningen perfekt

• Det är med bit 1 i control –registret (0x924) som man väljer continuous mode

Page 37: Övning 5

William Sandqvist [email protected]

5.7 Körning continuous mode

Perfekt tidmätning.

Page 38: Övning 5

William Sandqvist [email protected]

5.6 inittimer()

Att räkna ner från 49999 till timeout (0) tar 1 ms (50 Mhz klocka). Detta tal skall skrivas till de två periodregistren.

Continuous biten måste ”1” ställas.

Start biten måste ”1” ställas.

Page 39: Övning 5

William Sandqvist [email protected]

5.6 periodh periodlAtt räkna ner från 49999 till timeout (0) tar 1 ms (50 Mhz klocka).

Detta tal skall skrivas till de två 16-bitars period-registren.

4999910 = 0000C34F16

peridh = 0x0000periodl =0xC34F

Page 40: Övning 5

William Sandqvist [email protected]

5.6 inittimer()

.equ timer, 0x920 .text .align 2 .global inittimer # synlig i andra filerinittimer: movia r8,timer # basadressen till timern movia r9,0xC34F # R9 = 0xC34F stw r0,12(r8) # periodh = 0x0000 stw r9,8(r8) # periodl = R9 (=0xC34F) movi r9,0b0110 # R9 = 0b0110 (continuous=1 start=1) stw r9,4(r8) # skriv till control ret

void inittimer( void );

Page 41: Övning 5

William Sandqvist [email protected]

5.6 inittimer()

.equ timer, 0x920 .text .align 2 .global inittimer # synlig i andra filerinittimer: movia r8,timer # basadressen till timern movia r9,49999 # R9 = 49999 srli r10,r9,16 # 16 höga bitar kvar stw r10,12(r8) # periodh 16 höga bitar andi r9,r9,0xFFFF # behåll 16 låga bitar stw r9,8(r8) # periodl 16 låga bitar movi r9,0b0110 # R9 = 0b0110 (continuous=1 start=1) stw r9,4(r8) # skriv till control ret

void inittimer( void );

Generell metod att sätta periodregistren till godtyckligt värde:

Page 42: Övning 5

William Sandqvist [email protected]

5.6 C-kod inittimer()

#define TIMER1 ( (unsigned int *) 0x920 )#define PERIOD (49999)void inittimer( void ){ volatile unsigned int * Timer1Base = TIMER1; Timer1Base[2] = ( PERIOD & 0xFFFF ); Timer1Base[3] = PERIOD >> 16; Timer1Base[1] = 0x6; /* Start + Continuous */ Timer1Base[0] = 0; }

void inittimer( void );

Page 43: Övning 5

Kvittera efter timeout, 0-ställ timeoutbiten, genom att skriva vad som helst till control registret!

William Sandqvist [email protected]

5.6 checktimer()

.global checktimerchecktimer: movi r2, -1 # defaultvärde till R2 movia r8, Timer1Base # R8 pekar på timerkretsen ldwio r9,0(r8) # status till R9 andi r9, r9, 1 # Bara TimeOut-biten i R9 beq r9,r0,NoTimeOut # hoppa om ingen timeout stwio r0,0(r8) # nollställ TimeOut-biten movi r2,17 # 0-ställ returvärdetNoTimeOut: ret # retur med 0 eller -1

int checktimer( void );

Page 44: Övning 5

William Sandqvist [email protected]

int checktimer( void ){ volatile unsigned int * Timer1Base = TIMER1; if (Timer1Base[0] & 1) == 0) return (-1); else { Timer1Base[0] = 0; return (0); }}

int checktimer( void );

5.6 C-kod checktimer()

Page 45: Övning 5

William Sandqvist [email protected]

5.6 delayt()

.global delaytdelayt: ble r4,r0,done # klart om R4< 0, negativt push r31 # skydda returadressen ”sub i sub”wait: call checktimer # loopa tills 0-retur blt r2,r0,wait subi r4,r4,1 # minska med 1 (millisekund) bgt r4,r0,wait # fortsätt så länge R4 > 0 pop r31done: ret

void delayt( unsigned int millisek);

Page 46: Övning 5

William Sandqvist [email protected]

void delayt( unsigned int millisek){ unsigned int i; for(i = millisek; i>0; i--) { while( checktimer() ) /* do nothing */ ; {}

5.6 C-kod delayt()void delayt( unsigned int millisek);

Page 47: Övning 5

William Sandqvist [email protected]

5.7 de2_pio_keys4

Page 48: Övning 5

William Sandqvist [email protected]

5.7 Get_button()

.equ keys4,0x840

.text

.align 2

.global Get_ButtonGet_Button: movia r8,keys4 # nu pekar R8 på Knapp-enheten ldwio r2,0(r8) # läs data andi r2,r2,0xF # nollställ bit 31 ... 04 ret

unsigned int Get_Button( void );

Page 49: Övning 5

William Sandqvist [email protected]

5.7 C-kod Get_button()

#define KEYS4 ( (unsigned int *) 0x840unsigned int Get_Button( void ){ volatile unsigned int * keys4 = KEYS4; unsigned int temp = * keys4; return( temp & 0xf );}

unsigned int Get_Button( void );

Page 50: Övning 5

William Sandqvist [email protected]

Registeranvändning