1
Harvard-Architektur
●
Getrennter Programm-/Datenspeicher
●
Datenspeicher:
●
SRAM
●
EEPROM
●
Programmspeicher:
●
Flash
●
Getrennter Programm-/Datenspeicher
●
Datenspeicher:
●
SRAM
●
EEPROM
●
Programmspeicher:
●
Flash
2
Datenspeicher
Registerfile
●
Arbeitsregister,
●
Steuerregister/Ports Sram (static Ram)
●
1kByte bei ATmega8
●
4kByte bei ATmega128
●
Ram für statische Variable, (Literale), Texte, Stack EEPROM
●
512 Byte
●
langsamer Zugriff, insbes. Beim Schreiben
Registerfile
●
Arbeitsregister,
●
Steuerregister/Ports Sram (static Ram)
●
1kByte bei ATmega8
●
4kByte bei ATmega128
●
Ram für statische Variable, (Literale), Texte, Stack EEPROM
●
512 Byte
●
langsamer Zugriff, insbes. Beim Schreiben
3
Adresse
Register
I/O
SRAM
$0000-$001F (32 Byte)
$0020-$005F (64 Byte)
$0060-$045F (1024 Byte)
$0000-$045F (1120 Byte)
SRam und Adressbereiche
Arbeitsregister
General Purpose Working Registers
R0 0x00 Eingeschränkt, kein Laden von Direktwerten
R1 0x01 (Literalen)
R2 0x02
…
R13 0x0D R14 0x0E R15 0x0F
R16 0x10 Uneingeschränkt
R17 0x11
…
R26 0x1A X-register Low Byte Als 16-bit Adressregister nutzbar R27 0x1B X-register High Byte
R28 0x1C Y-register Low Byte R29 0x1D Y-register High Byte R30 0x1E Z-register Low Byte R31 0x1F Z-register High Byte
R0 0x00 Eingeschränkt, kein Laden von Direktwerten
R1 0x01 (Literalen)
R2 0x02
…
R13 0x0D R14 0x0E R15 0x0F
R16 0x10 Uneingeschränkt
R17 0x11
…
R26 0x1A X-register Low Byte Als 16-bit Adressregister nutzbar R27 0x1B X-register High Byte
R28 0x1C Y-register Low Byte R29 0x1D Y-register High Byte R30 0x1E Z-register Low Byte R31 0x1F Z-register High Byte
4
Register Summary
Address Name Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 Page
0x3F (0x5F) SREG I T H S V N Z C 11
0x3E (0x5E) SPH – – – – – SP10 SP9 SP8 13
0x3D(0x5D) SPL SP7 SP6 SP5 SP4 SP3 SP2 SP1 SP0 13
0x3C(0x5C) Reserved
0x3B(0x5B) GICR INT1 – – – – – IVSEL IVCE 49,67
0x3A(0x5A) GIFR INTF1 INTF0 INTF0 – – – – – 68
0x39(0x59) TIMSK OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 – TOIE0 72,102,122
0x38(0x58) TIFR OCF2 TOV2 ICF1 OCF1A OCF1B TOV1 – TOV0 73,103,123
0x37(0x57) SPMCR SPMIE RWWSB – RWWSRE BLBSET PGWRT PGERS SPMEN 213
0x36(0x56) TWCR TWINT TWEA TWSTA TWSTO TWWC TWEN – TWIE 171
0x35(0x55) MCUCR SE SM2 SM1 SM0 ISC11 ISC10 ISC01 ISC00 33,66
0x34(0x54) MCUCSR – – – – WDRF BORF EXTRF PORF 41
0x33(0x53) TCCR0 – – – – – CS02 CS01 CS00 72
0x32(0x52) TCNT0 Timer/Counter0 (8 Bits) 72
0x31(0x51) OSCCAL Oscillator Calibration Register 31
0x30(0x50) SFIOR – – – – ACME PUD PSR2 PSR10 58, 75, 123,193
0x2F(0x4F) TCCR1A COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10 97
0x2E(0x4E) TCCR1B ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10 100
0x2D(0x4D) TCNT1H Timer/Counter1 – Counter Register High byte 101
0x2C(0x4C) TCNT1L Timer/Counter1 – Counter Register Low byte 101
0x2B(0x4B) OCR1AH Timer/Counter1 – Output Compare Register A High byte 101
0x2A(0x4A) OCR1AL Timer/Counter1 – Output Compare Register A Low byte 101
0x29(0x49) OCR1BH Timer/Counter1 – Output Compare Register B High byte 101
0x28(0x48) OCR1BL Timer/Counter1 – Output Compare Register B Low byte 101
0x27(0x47) ICR1H Timer/Counter1 – Input Capture Register High byte 102
0x26(0x46) ICR1L Timer/Counter1 – Input Capture Register Low byte 102
0x25(0x45) TCCR2 FOC2 WGM20 COM21 COM20 WGM21 CS22 CS21 CS20 117
0x24(0x44) TCNT2 Timer/Counter2 (8 Bits) 119
0x23(0x43) OCR2 Timer/Counter2 Output Compare Register 119
0x22(0x42) ASSR – – – – AS2 TCN2UB OCR2UB TCR2UB 119
0x21(0x41) WDTCR – – – WDCE WDE WDP2 WDP1 WDP0 43
Register Summary
Address Name Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 Page
0x3F (0x5F) SREG I T H S V N Z C 11
0x3E (0x5E) SPH – – – – – SP10 SP9 SP8 13
0x3D(0x5D) SPL SP7 SP6 SP5 SP4 SP3 SP2 SP1 SP0 13
0x3C(0x5C) Reserved
0x3B(0x5B) GICR INT1 – – – – – IVSEL IVCE 49,67
0x3A(0x5A) GIFR INTF1 INTF0 INTF0 – – – – – 68
0x39(0x59) TIMSK OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 – TOIE0 72,102,122
0x38(0x58) TIFR OCF2 TOV2 ICF1 OCF1A OCF1B TOV1 – TOV0 73,103,123
0x37(0x57) SPMCR SPMIE RWWSB – RWWSRE BLBSET PGWRT PGERS SPMEN 213
0x36(0x56) TWCR TWINT TWEA TWSTA TWSTO TWWC TWEN – TWIE 171
0x35(0x55) MCUCR SE SM2 SM1 SM0 ISC11 ISC10 ISC01 ISC00 33,66
0x34(0x54) MCUCSR – – – – WDRF BORF EXTRF PORF 41
0x33(0x53) TCCR0 – – – – – CS02 CS01 CS00 72
0x32(0x52) TCNT0 Timer/Counter0 (8 Bits) 72
0x31(0x51) OSCCAL Oscillator Calibration Register 31
0x30(0x50) SFIOR – – – – ACME PUD PSR2 PSR10 58, 75, 123,193
0x2F(0x4F) TCCR1A COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10 97
0x2E(0x4E) TCCR1B ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10 100
0x2D(0x4D) TCNT1H Timer/Counter1 – Counter Register High byte 101
0x2C(0x4C) TCNT1L Timer/Counter1 – Counter Register Low byte 101
0x2B(0x4B) OCR1AH Timer/Counter1 – Output Compare Register A High byte 101
0x2A(0x4A) OCR1AL Timer/Counter1 – Output Compare Register A Low byte 101
0x29(0x49) OCR1BH Timer/Counter1 – Output Compare Register B High byte 101
0x28(0x48) OCR1BL Timer/Counter1 – Output Compare Register B Low byte 101
0x27(0x47) ICR1H Timer/Counter1 – Input Capture Register High byte 102
0x26(0x46) ICR1L Timer/Counter1 – Input Capture Register Low byte 102
0x25(0x45) TCCR2 FOC2 WGM20 COM21 COM20 WGM21 CS22 CS21 CS20 117
0x24(0x44) TCNT2 Timer/Counter2 (8 Bits) 119
0x23(0x43) OCR2 Timer/Counter2 Output Compare Register 119
0x22(0x42) ASSR – – – – AS2 TCN2UB OCR2UB TCR2UB 119
0x21(0x41) WDTCR – – – WDCE WDE WDP2 WDP1 WDP0 5 43
Ram-Adresse I/O-Controll-
Register (von in/out verwendet)
SpecialFunctionRegister
(SFR)
0x20(0x40) UBRRH URSEL – – – UBRR[11:8] 156
UCSRC URSEL UMSEL UPM1 UPM0 USBS UCSZ1 UCSZ0 UCPOL 153
0x1F(0x3F) EEARH – – – – – – – EEAR8 20
0x1E(0x3E) EEARL EEAR7 EEAR6 EEAR5 EEAR4 EEAR3 EEAR2 EEAR1 EEAR0 20
0x1D(0x3D) EEDR EEPROM Data Register 20
0x1C(0x3C) EECR – – – – EERIE EEMWE EEWE EERE 20
0x1B(0x3B) Reserved 0x1A(0x3A) Reserved 0x19(0x39) Reserved
0x18(0x38) PORTB PORTB7 PORTB6 PORTB5 PORTB4 PORTB3 PORTB2 PORTB1 PORTB0 65
0x17(0x37) DDRB DDB7 DDB6 DDB5 DDB4 DDB3 DDB2 DDB1 DDB0 65
0x16(0x36) PINB PINB7 PINB6 PINB5 PINB4 PINB3 PINB2 PINB1 PINB0 65
0x15(0x35) PORTC – PORTC6 PORTC5 PORTC4 PORTC3 PORTC2 PORTC1 PORTC0 65
0x14(0x34) DDRC – DDC6 DDC5 DDC4 DDC3 DDC2 DDC1 DDC0 65
0x13(0x33) PINC – PINC6 PINC5 PINC4 PINC3 PINC2 PINC1 PINC0 65
0x12(0x32) PORTD PORTD7 PORTD6 PORTD5 PORTD4 PORTD3 PORTD2 PORTD1 PORTD0 65
0x11(0x31) DDRD DDD7 DDD6 DDD5 DDD4 DDD3 DDD2 DDD1 DDD0 65
0x10(0x30) PIND PIND7 PIND6 PIND5 PIND4 PIND3 PIND2 PIND1 PIND0 65
0x0F(0x2F) SPDR SPI Data Register 131
0x0E(0x2E) SPSR SPIF WCOL – – – – – SPI2X 131
0x0D(0x2D) SPCR SPIE SPE DORD MSTR CPOL CPHA SPR1 SPR0 129
0x0C(0x2C) UDR USART I/O Data Register 153
0x0B(0x2B) UCSRA RXC TXC UDRE FE DOR PE U2X MPCM 154
0x0A(0x2A) UCSRB RXCIE TXCIE UDRIE RXEN TXEN UCSZ2 RXB8 TXB8 155
0x09(0x29) UBRRL USART Baud Rate Register Low byte 158
0x08(0x28) ACSR ACD ACBG ACO ACI ACIE ACIC ACIS1 ACIS0 194
0x07(0x27) ADMUX REFS1 REFS0 ADLAR – MUX3 MUX2 MUX1 MUX0 205
0x06(0x26) ADCSRA ADEN ADSC ADFR ADIF ADIE ADPS2 ADPS1 ADPS0 207
0x05(0x25) ADCH ADC Data Register High byte 208
0x04(0x24) ADCL ADC Data Register Low byte 208
0x03(0x23) TWDR Two-wire Serial Interface Data Register 173
0x02(0x22) TWAR TWA6 TWA5 TWA4 TWA3 TWA2 TWA1 TWA0 TWGCE 17
0x01(0x21) TWSR TWS7 TWS6 TWS5 TWS4 TWS3 – TWPS1 TWPS0 170
0x00(0x20) TWBR TWBRTwo-wire Serial Interface Bit Rate Register 171
0x20(0x40) UBRRH URSEL – – – UBRR[11:8] 156
UCSRC URSEL UMSEL UPM1 UPM0 USBS UCSZ1 UCSZ0 UCPOL 153
0x1F(0x3F) EEARH – – – – – – – EEAR8 20
0x1E(0x3E) EEARL EEAR7 EEAR6 EEAR5 EEAR4 EEAR3 EEAR2 EEAR1 EEAR0 20
0x1D(0x3D) EEDR EEPROM Data Register 20
0x1C(0x3C) EECR – – – – EERIE EEMWE EEWE EERE 20
0x1B(0x3B) Reserved 0x1A(0x3A) Reserved 0x19(0x39) Reserved
0x18(0x38) PORTB PORTB7 PORTB6 PORTB5 PORTB4 PORTB3 PORTB2 PORTB1 PORTB0 65
0x17(0x37) DDRB DDB7 DDB6 DDB5 DDB4 DDB3 DDB2 DDB1 DDB0 65
0x16(0x36) PINB PINB7 PINB6 PINB5 PINB4 PINB3 PINB2 PINB1 PINB0 65
0x15(0x35) PORTC – PORTC6 PORTC5 PORTC4 PORTC3 PORTC2 PORTC1 PORTC0 65
0x14(0x34) DDRC – DDC6 DDC5 DDC4 DDC3 DDC2 DDC1 DDC0 65
0x13(0x33) PINC – PINC6 PINC5 PINC4 PINC3 PINC2 PINC1 PINC0 65
0x12(0x32) PORTD PORTD7 PORTD6 PORTD5 PORTD4 PORTD3 PORTD2 PORTD1 PORTD0 65
0x11(0x31) DDRD DDD7 DDD6 DDD5 DDD4 DDD3 DDD2 DDD1 DDD0 65
0x10(0x30) PIND PIND7 PIND6 PIND5 PIND4 PIND3 PIND2 PIND1 PIND0 65
0x0F(0x2F) SPDR SPI Data Register 131
0x0E(0x2E) SPSR SPIF WCOL – – – – – SPI2X 131
0x0D(0x2D) SPCR SPIE SPE DORD MSTR CPOL CPHA SPR1 SPR0 129
0x0C(0x2C) UDR USART I/O Data Register 153
0x0B(0x2B) UCSRA RXC TXC UDRE FE DOR PE U2X MPCM 154
0x0A(0x2A) UCSRB RXCIE TXCIE UDRIE RXEN TXEN UCSZ2 RXB8 TXB8 155
0x09(0x29) UBRRL USART Baud Rate Register Low byte 158
0x08(0x28) ACSR ACD ACBG ACO ACI ACIE ACIC ACIS1 ACIS0 194
0x07(0x27) ADMUX REFS1 REFS0 ADLAR – MUX3 MUX2 MUX1 MUX0 205
0x06(0x26) ADCSRA ADEN ADSC ADFR ADIF ADIE ADPS2 ADPS1 ADPS0 207
0x05(0x25) ADCH ADC Data Register High byte 208
0x04(0x24) ADCL ADC Data Register Low byte 208
0x03(0x23) TWDR Two-wire Serial Interface Data Register 173
0x02(0x22) TWAR TWA6 TWA5 TWA4 TWA3 TWA2 TWA1 TWA0 TWGCE 17
0x01(0x21) TWSR TWS7 TWS6 TWS5 TWS4 TWS3 – TWPS1 TWPS0 170
0x00(0x20) TWBR TWBRTwo-wire Serial Interface Bit Rate Register 171
6
7
sts statt out
// aus Blink/main.S loop:
eor mp,mp inc mp
// Store statt out scheint zu funktionieren // out PORTB,mp
sts 0x38,mp
rcall waitabit rcall waitabit
// Store statt out scheint zu funktionieren // out PORTB,r19
sts 0x38,r19
rcall waitabit lsl mp
// aus Blink/main.S loop:
eor mp,mp inc mp
// Store statt out scheint zu funktionieren // out PORTB,mp
sts 0x38,mp
rcall waitabit rcall waitabit
// Store statt out scheint zu funktionieren // out PORTB,r19
sts 0x38,r19
rcall waitabit lsl mp
Store Direct To Sram An Stelle von
out
8
Die Arbeitsregister
(general purpose Register)
Adresse Reg Bemerkungen
0x0 R0
0x1 R1
… …
0xD R13
0xE R14
0xF R15
0x10 R16
ohne Einschränku 0x11 R17
… …
0x1A R26 X LowByte
16-Bit Adressreg.
0x1B R27 X HighByte 0x1C R28 Y LowByte
16-Bit Adressreg.
0x1D R29 Y HighByte 0x1E R31 Z LowByte
16-Bit Adressreg.
0x1F R31 Z HighByte
keine Literale Erlaubt
Adressregister für SRAM
Adresse Reg Bemerkungen
0x0 R0
0x1 R1
… …
0xD R13
0xE R14
0xF R15
0x10 R16
ohne Einschränku 0x11 R17
… …
0x1A R26 X LowByte
16-Bit Adressreg.
0x1B R27 X HighByte 0x1C R28 Y LowByte
16-Bit Adressreg.
0x1D R29 Y HighByte 0x1E R31 Z LowByte
16-Bit Adressreg.
0x1F R31 Z HighByte
keine Literale Erlaubt
Adressregister
für SRAM
9
Befehle, für R0 ..R15 nicht erlaubt
LDI Rx,K ; load immideate
ANDI Rx,K ; bitwise AND imm.
SER Rx ; Set all Bits to 1 CBR Rx,M ; clear maskbits
SBR Rx,M ; set maskbits CPI Rx,K ; compare imm.
SUBI Rx,K ; Subtract imm.
SBCI Rx,K ; Subtract imm. carry LDI Rx,K ; load immideate
ANDI Rx,K ; bitwise AND imm.
SER Rx ; Set all Bits to 1 CBR Rx,M ; clear maskbits
SBR Rx,M ; set maskbits CPI Rx,K ; compare imm.
SUBI Rx,K ; Subtract imm.
SBCI Rx,K ; Subtract imm. carry
10
Programmspeicher
Flash
●
Wortweise organisiert
●
Befehle sind 16/32 bit groß
●
8 kByte bei ATmega8
●
128 kByte bei ATmega128
●
Beinhaltet ggf. Bootloader am oberen Ende
●
Konstanten (Zeichenketten, KonstantenArrays) können direkt aus dem Flash veratbeitet wertden.
●
Spezielle Adressierungsmodi über Z-(R30/R31) -Regis- ter
●
Spezielle C-Standardfunktionen / Macros verwenden
Flash
●
Wortweise organisiert
●
Befehle sind 16/32 bit groß
●
8 kByte bei ATmega8
●
128 kByte bei ATmega128
●
Beinhaltet ggf. Bootloader am oberen Ende
●
Konstanten (Zeichenketten, KonstantenArrays) können direkt aus dem Flash veratbeitet wertden.
●
Spezielle Adressierungsmodi über Z-(R30/R31) -Regis- ter
●
Spezielle C-Standardfunktionen / Macros verwenden
11
Das leere Programm - was will es uns sagen?
#include <avr/io.h>
char * GloblText="Goethes Faust";
int main(){
while (1);
return 0;
}
#include <avr/io.h>
char * GloblText="Goethes Faust";
int main(){
while (1);
return 0;
} Seine Geheimnisse entlocken wir ihm mit
avr-objdump -D main.elf > main.dump
12
main.elf: file format elf32-avr
Disassembly of section .text:
00000000 <__vectors>:
0: 12 c0 rjmp.+36 ; 0x26 <__ctors_end>
2: 2c c0 rjmp.+88 ; 0x5c <__bad_interrupt>
4: 2b c0 rjmp.+86 ; 0x5c <__bad_interrupt>
6: 2a c0 rjmp.+84 ; 0x5c <__bad_interrupt>
8: 29 c0 rjmp.+82 ; 0x5c <__bad_interrupt>
a: 28 c0 rjmp.+80 ; 0x5c <__bad_interrupt>
c: 27 c0 rjmp.+78 ; 0x5c <__bad_interrupt>
e: 26 c0 rjmp.+76 ; 0x5c <__bad_interrupt>
10:25 c0 rjmp.+74 ; 0x5c <__bad_interrupt>
12:24 c0 rjmp.+72 ; 0x5c <__bad_interrupt>
14:23 c0 rjmp.+70 ; 0x5c <__bad_interrupt>
16:22 c0 rjmp.+68 ; 0x5c <__bad_interrupt>
18:21 c0 rjmp.+66 ; 0x5c <__bad_interrupt>
1a:20 c0 rjmp.+64 ; 0x5c <__bad_interrupt>
1c:1f c0 rjmp.+62 ; 0x5c <__bad_interrupt>
1e:1e c0 rjmp.+60 ; 0x5c <__bad_interrupt>
20:1d c0 rjmp.+58 ; 0x5c <__bad_interrupt>
22:1c c0 rjmp.+56 ; 0x5c <__bad_interrupt>
24:1b c0 rjmp.+54 ; 0x5c <__bad_interrupt>
main.elf: file format elf32-avr
Disassembly of section .text:
00000000 <__vectors>:
0: 12 c0 rjmp.+36 ; 0x26 <__ctors_end>
2: 2c c0 rjmp.+88 ; 0x5c <__bad_interrupt>
4: 2b c0 rjmp.+86 ; 0x5c <__bad_interrupt>
6: 2a c0 rjmp.+84 ; 0x5c <__bad_interrupt>
8: 29 c0 rjmp.+82 ; 0x5c <__bad_interrupt>
a: 28 c0 rjmp.+80 ; 0x5c <__bad_interrupt>
c: 27 c0 rjmp.+78 ; 0x5c <__bad_interrupt>
e: 26 c0 rjmp.+76 ; 0x5c <__bad_interrupt>
10:25 c0 rjmp.+74 ; 0x5c <__bad_interrupt>
12:24 c0 rjmp.+72 ; 0x5c <__bad_interrupt>
14:23 c0 rjmp.+70 ; 0x5c <__bad_interrupt>
16:22 c0 rjmp.+68 ; 0x5c <__bad_interrupt>
18:21 c0 rjmp.+66 ; 0x5c <__bad_interrupt>
1a:20 c0 rjmp.+64 ; 0x5c <__bad_interrupt>
1c:1f c0 rjmp.+62 ; 0x5c <__bad_interrupt>
1e:1e c0 rjmp.+60 ; 0x5c <__bad_interrupt>
20:1d c0 rjmp.+58 ; 0x5c <__bad_interrupt>
22:1c c0 rjmp.+56 ; 0x5c <__bad_interrupt>
24:1b c0 rjmp.+54 ; 0x5c <__bad_interrupt>
Die Interruptvektor- tabelle
Start des
Programms
13
00000026 <__ctors_end>:
26:11 24 eor r1, r1
28:1f be out 0x3f, r1 ; 63 2a:cf e5 ldi r28, 0x5F ; 95 2c:d4 e0 ldi r29, 0x04 ; 4 2e:de bf out 0x3e, r29 ; 62 30:cd bf out 0x3d, r28 ; 61 00000032 <__do_copy_data>:
32:10 e0 ldi r17, 0x00 ; 0 34:a0 e6 ldi r26, 0x60 ; 96 36:b0 e0 ldi r27, 0x00 ; 0 38:e2 e6 ldi r30, 0x62 ; 98 3a:f0 e0 ldi r31, 0x00 ; 0
3c:02 c0 rjmp.+4 ; 0x42 <.do_copy_data_start>
0000003e <.do_copy_data_loop>:
3e:05 90 lpm r0, Z+
40:0d 92 st X+, r0
00000042 <.do_copy_data_start>:
42:a0 37 cpi r26, 0x70 ; 112 44:b1 07 cpc r27, r17
46:d9 f7 brne .-10 ; 0x3e <.do_copy_data_loop>
00000026 <__ctors_end>:
26:11 24 eor r1, r1
28:1f be out 0x3f, r1 ; 63 2a:cf e5 ldi r28, 0x5F ; 95 2c:d4 e0 ldi r29, 0x04 ; 4 2e:de bf out 0x3e, r29 ; 62 30:cd bf out 0x3d, r28 ; 61 00000032 <__do_copy_data>:
32:10 e0 ldi r17, 0x00 ; 0 34:a0 e6 ldi r26, 0x60 ; 96 36:b0 e0 ldi r27, 0x00 ; 0 38:e2 e6 ldi r30, 0x62 ; 98 3a:f0 e0 ldi r31, 0x00 ; 0
3c:02 c0 rjmp.+4 ; 0x42 <.do_copy_data_start>
0000003e <.do_copy_data_loop>:
3e:05 90 lpm r0, Z+
40:0d 92 st X+, r0
00000042 <.do_copy_data_start>:
42:a0 37 cpi r26, 0x70 ; 112 44:b1 07 cpc r27, r17
46:d9 f7 brne .-10 ; 0x3e <.do_copy_data_loop>
Flags löschen
Stackpointer auf Ramende setzen
Kopieren des Daten-
segmentes in den SRAM X(R26,R27)=Ziel im SRAM Z(R30,R31)=Source im Flash
R0:=[Z]
[x]:=R0
Test auf Ende
(0x70)
14
00000048 <__do_clear_bss>:
48:10 e0 ldi r17, 0x00 ; 0 4a:a0 e7 ldi r26, 0x70 ; 112 4c:b0 e0 ldi r27, 0x00 ; 0
4e:01 c0 rjmp.+2 ; 0x52 <.do_clear_bss_start>
00000050 <.do_clear_bss_loop>:
50:1d 92 st X+, r1
00000052 <.do_clear_bss_start>:
52:a0 37 cpi r26, 0x70 ; 112 54:b1 07 cpc r27, r17
56:e1 f7 brne .-8 ; 0x50 <.do_clear_bss_loop>
58:02 d0 rcall .+4 ; 0x5e <main>
5a:02 c0 rjmp.+4 ; 0x60 <_exit>
0000005c <__bad_interrupt>:
5c:d1 cf rjmp.-94 ; 0x0 <__vectors>
0000005e <main>:
5e:ff cf rjmp.-2 ; 0x5e <main>
00000060 <_exit>:
60:ff cf rjmp.-2 ; 0x60 <_exit>
00000048 <__do_clear_bss>:
48:10 e0 ldi r17, 0x00 ; 0 4a:a0 e7 ldi r26, 0x70 ; 112 4c:b0 e0 ldi r27, 0x00 ; 0
4e:01 c0 rjmp.+2 ; 0x52 <.do_clear_bss_start>
00000050 <.do_clear_bss_loop>:
50:1d 92 st X+, r1
00000052 <.do_clear_bss_start>:
52:a0 37 cpi r26, 0x70 ; 112 54:b1 07 cpc r27, r17
56:e1 f7 brne .-8 ; 0x50 <.do_clear_bss_loop>
58:02 d0 rcall .+4 ; 0x5e <main>
5a:02 c0 rjmp.+4 ; 0x60 <_exit>
0000005c <__bad_interrupt>:
5c:d1 cf rjmp.-94 ; 0x0 <__vectors>
0000005e <main>:
5e:ff cf rjmp.-2 ; 0x5e <main>
00000060 <_exit>:
60:ff cf rjmp.-2 ; 0x60 <_exit>
Löschen statischer Variablen auf 0
Interruptroutinen
main
15
Disassembly of section .data:
00800060 <__data_start>:
800060: 47 6f ori r20, 0xF7 ; 247 800062: 65 74 andir22, 0x45 ; 69 800064: 68 65 ori r22, 0x58 ; 88 800066: 73 20 and r7, r3
800068: 46 61 ori r20, 0x16 ; 22 80006a: 75 73 andir23, 0x35 ; 53 80006c: 74 00 .word 0x0074 ; ????
0080006e <GloblText>:
80006e: 60 00 .word 0x0060 ; ????
Disassembly of section .stab:
00000000 <_end-0x800070>:
0: 01 00 .word 0x0001 ; ????
2: 00 00 nop 4: 00 00 nop
6: 8b 00 .word 0x008b ; ????
8: 91 07 cpc r25, r17 a: 00 00 nop
c: 01 00 .word 0x0001 ; ????
e: 00 00 nop
10:64 00 .word 0x0064 ; ????
12:00 00 nop
Disassembly of section .data:
00800060 <__data_start>:
800060: 47 6f ori r20, 0xF7 ; 247 800062: 65 74 andir22, 0x45 ; 69 800064: 68 65 ori r22, 0x58 ; 88 800066: 73 20 and r7, r3
800068: 46 61 ori r20, 0x16 ; 22 80006a: 75 73 andir23, 0x35 ; 53 80006c: 74 00 .word 0x0074 ; ????
0080006e <GloblText>:
80006e: 60 00 .word 0x0060 ; ????
Disassembly of section .stab:
00000000 <_end-0x800070>:
0: 01 00 .word 0x0001 ; ????
2: 00 00 nop 4: 00 00 nop
6: 8b 00 .word 0x008b ; ????
8: 91 07 cpc r25, r17 a: 00 00 nop
c: 01 00 .word 0x0001 ; ????
e: 00 00 nop
10:64 00 .word 0x0064 ; ????
12:00 00 nop
Das ist der Text
"Goethes Faust“
(kaum wiederzuerkennen)
Die Adresse vom Faust
.stab und .stabstr wird nicht Auf den AVR geladen
16
Interruptvectoren
Initialisierung der Flags und des Stackpointers
(Flags Port 0x3F, Stackpointer Port 0x3E,0x3D)
Kopieren initialisierter statischer Daten Flash → SRAM
Löschen nicht initialisierter statischer Daten
Interruptroutinen Programm
Interruptvectoren
Initialisierung der Flags und des Stackpointers
(Flags Port 0x3F, Stackpointer Port 0x3E,0x3D)
Kopieren initialisierter statischer Daten Flash → SRAM
Löschen nicht initialisierter statischer Daten
Interruptroutinen Programm
Segment Inhalt
.text Programm
.data Statische
initialisierte Daten
.bss Nicht
initialisierte statische Daten
.eeprom Daten im
eeprom
Segment Inhalt
.text Programm
.data Statische
initialisierte Daten
.bss Nicht
initialisierte statische Daten
.eeprom Daten im
eeprom
17
Aufbau des SRam zur Laufzeit
0x0000 Register 0x0020 Ports 0x0060
0x045F
initialisierte
statische Daten nicht
initialisierte
statische Daten Heap ↓
Stack ↑ 0x0000 Register 0x0020 Ports 0x0060
0x045F
initialisierte
statische Daten nicht
initialisierte
statische Daten Heap ↓
Stack ↑
18
PROGMEM
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
●
Um wertvollen Platz im SRAM zu sparen, können konstante Werte, wie Strings direkt aus dem Programmspeicher ver- arbeitet werden.
●
Vereinbarung erfordert das Attribut PROGMEM Beispiel:
#include <avr/progmem.h>
static const char pgmTestStringLocal[] PROGMEM = "im Flash";
●
Daten müssen extern/global und mit dem Attribut const ver- sehen sein.
●
Zur Verwendung dieser Daten sind spezielle Funktionen notwendig
●
Daten können nur lesend verarbeitet werden
●
Um wertvollen Platz im SRAM zu sparen, können konstante Werte, wie Strings direkt aus dem Programmspeicher ver- arbeitet werden.
●
Vereinbarung erfordert das Attribut PROGMEM Beispiel:
#include <avr/progmem.h>
static const char pgmTestStringLocal[] PROGMEM = "im Flash";
●
Daten müssen extern/global und mit dem Attribut const ver- sehen sein.
●
Zur Verwendung dieser Daten sind spezielle Funktionen notwendig
●
Daten können nur lesend verarbeitet werden
19
Datenvereinbarung im ProgMem
http://www.nongnu.org/avr-libc/user-manual/pgmspace.html
Typedefs für
Standarddatentypen im Progmem
prog_void prog_char prog_uchar prog_int8_t prog_uint8_t prog_int16_t prog_uint16_t prog_int32_t prog_uint32_t Allgemein gilt:
const int myi PROGMEM=67;
#include <avr/pgmspace.h>
. . .
const unsigned char mydata[11][10] PROGMEM = {
{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09}, {0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13}, . . .
{0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59}, {0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61,0x62,0x63}, {0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D}
};
#define PGM_P const prog_char *
#define PGM_VOID_P const prog_void * Literale können wie folgt vereinbart werden:
const char *ps1 = PSTR("String from:\n");
20
Hammingcode
const uint8_t hamminge[16 ]={
0x15,0x02,0x49,0x5E,0x64,0x73,0x38,0x2F,0xD0,0xC7,0x8C,0x9B,0xA1,0xB6,0xFD,0xEA};
const uint8_t hammingd[256]/*PROGMEM*/={
/*0*/ 0x01,0x00,0x01,0x01,0x00,0x00,0x01,0x01,0x02,0x02,0x01,0x03,0x0A,0x02,0x03,0x07, /*1*/ 0x00,0x00,0x01,0x01,0x00,0x00,0x01,0x00,0x06,0x02,0x03,0x0B,0x02,0x00,0x03,0x03, /*2*/ 0x04,0x0C,0x01,0x05,0x04,0x04,0x05,0x07,0x06,0x06,0x07,0x07,0x06,0x07,0x07,0x07, /*3*/ 0x06,0x04,0x05,0x05,0x04,0x00,0x0D,0x05,0x06,0x06,0x06,0x07,0x06,0x06,0x07,0x07, /*4*/ 0x00,0x02,0x01,0x01,0x04,0x00,0x01,0x09,0x02,0x02,0x03,0x02,0x02,0x02,0x03,0x03, /*5*/ 0x08,0x00,0x01,0x05,0x00,0x00,0x03,0x01,0x02,0x02,0x03,0x03,0x03,0x02,0x03,0x03, /*6*/ 0x04,0x04,0x05,0x05,0x04,0x04,0x04,0x05,0x06,0x02,0x0F,0x07,0x04,0x06,0x07,0x07, /*7*/ 0x04,0x05,0x05,0x05,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x05,0x06,0x0E,0x03,0x07, /*8*/ 0x08,0x0C,0x01,0x09,0x0A,0x08,0x09,0x09,0x0A,0x0A,0x0B,0x0B,0x0A,0x0A,0x0A,0x0B, /*9*/ 0x08,0x08,0x09,0x0B,0x08,0x00,0x0D,0x09,0x0A,0x0B,0x0B,0x0B,0x0A,0x0A,0x0B,0x0B, /*A*/ 0x0C,0x0C,0x0D,0x0C,0x0C,0x0C,0x0D,0x0D,0x0E,0x0C,0x0F,0x0F,0x0A,0x0E,0x0F,0x07, /*B*/ 0x0C,0x0C,0x0D,0x0D,0x0D,0x0C,0x0D,0x0D,0x06,0x0E,0x0F,0x0B,0x0E,0x0E,0x0D,0x0F, /*C*/ 0x08,0x08,0x09,0x09,0x08,0x09,0x09,0x09,0x0A,0x02,0x0F,0x0B,0x0A,0x0A,0x0B,0x09, /*D*/ 0x08,0x08,0x08,0x09,0x08,0x08,0x09,0x09,0x08,0x0A,0x0B,0x0B,0x0A,0x0E,0x03,0x0B, /*E*/ 0x0C,0x0C,0x0F,0x0D,0x04,0x0C,0x0D,0x09,0x0F,0x0E,0x0F,0x0F,0x0E,0x0E,0x0F,0x0F, /*F*/ 0x08,0x0C,0x0D,0x05,0x0C,0x0E,0x0D,0x0D,0x0E,0x0E,0x0F,0x0F,0x0E,0x0E,0x0F,0x0E};
//---
Im SRAM
Im Progmem (Flash)
21
const char strings[][9] PROGMEM=
{
"Zeile 1\n", "Zeile 2\n", "Zeile 3\n", "Zeile 4\n", "Zeile 5\n"
};
const char string1 []PROGMEM= "Zeile 1\n";
const char string2 []PROGMEM= "Zeile 2\n";
const char string3 []PROGMEM= "Zeile 3\n";
const char string4 []PROGMEM= "Zeile 4\n";
const char string5 []PROGMEM= "Zeile 5\n";
PGM_P strings [] PROGMEM=
{
string1,string2,string3,string4,string5 };
const char *str[] PROGMEM = {
"String 1", "String 2", "String 3", "String 4", "String 5"
};
WRONG !!!
22
Macros zum Lesen aus Progmem
●
#include <avr/pgmspace.h>
●
pgm_read_byte(address_short)
●
pgm_read_word(address_short)
●
pgm_read_dword(address_short)
●
Die Varianten near und far sind nur für atmega128 relevant.
●
far erfordert die Verwendung einer 32 bit Adresse, wenn die Daten in den oberen 64 kByte liegen
●
#include <avr/pgmspace.h>
●
pgm_read_byte(address_short)
●
pgm_read_word(address_short)
●
pgm_read_dword(address_short)
●
Die Varianten near und far sind nur für atmega128 relevant.
●
far erfordert die Verwendung einer 32 bit
Adresse, wenn die Daten in den oberen 64
kByte liegen
23
extern PGM_VOID_P memchr_P (PGM_VOID_P s, int val, size_t len);
extern int memcmp_P (const void *, PGM_VOID_P, size_t);
extern void * memcpy_P (void *, PGM_VOID_P, size_t);
extern void * memmem_P (const void *, size_t, PGM_VOID_P, size_t);
extern PGM_VOID_P memrchr_P (PGM_VOID_P s, int val, size_t len);
extern char * strcat_P (char *, PGM_P);
extern PGM_P strchr_P (PGM_P s, int val);
extern PGM_P strchrnul_P (PGM_P s, int val);
extern int strcmp_P (const char *, PGM_P) ; extern char * strcpy_P (char *, PGM_P);
extern int strcasecmp_P(const char *, PGM_P) ; extern char * strcasestr_P (const char *, PGM_P);
extern size_t strcspn_P (const char *s, PGM_P reject) ; extern size_t strlcat_P (char *, PGM_P, size_t );
extern size_t strlcpy_P (char *, PGM_P, size_t );
extern size_t strlen_P (PGM_P);
extern size_t strnlen_P (PGM_P, size_t);
extern int strncmp_P (const char *, PGM_P, size_t) ; extern int strncasecmp_P(const char *, PGM_P, size_t) ; extern char * strncat_P (char *, PGM_P, size_t);
extern char * strncpy_P (char *, PGM_P, size_t);
extern char * strpbrk_P (const char *s, PGM_P accept) ; extern PGM_P strrchr_P (PGM_P s, int val) ;
extern char * strsep_P (char **sp, PGM_P delim);
extern size_t strspn_P (const char *s, PGM_P accept) ; extern char * strstr_P (const char *, PGM_P) ;
extern PGM_VOID_P memchr_P (PGM_VOID_P s, int val, size_t len);
extern int memcmp_P (const void *, PGM_VOID_P, size_t);
extern void * memcpy_P (void *, PGM_VOID_P, size_t);
extern void * memmem_P (const void *, size_t, PGM_VOID_P, size_t);
extern PGM_VOID_P memrchr_P (PGM_VOID_P s, int val, size_t len);
extern char * strcat_P (char *, PGM_P);
extern PGM_P strchr_P (PGM_P s, int val);
extern PGM_P strchrnul_P (PGM_P s, int val);
extern int strcmp_P (const char *, PGM_P) ; extern char * strcpy_P (char *, PGM_P);
extern int strcasecmp_P(const char *, PGM_P) ; extern char * strcasestr_P (const char *, PGM_P);
extern size_t strcspn_P (const char *s, PGM_P reject) ; extern size_t strlcat_P (char *, PGM_P, size_t );
extern size_t strlcpy_P (char *, PGM_P, size_t );
extern size_t strlen_P (PGM_P);
extern size_t strnlen_P (PGM_P, size_t);
extern int strncmp_P (const char *, PGM_P, size_t) ; extern int strncasecmp_P(const char *, PGM_P, size_t) ; extern char * strncat_P (char *, PGM_P, size_t);
extern char * strncpy_P (char *, PGM_P, size_t);
extern char * strpbrk_P (const char *s, PGM_P accept) ; extern PGM_P strrchr_P (PGM_P s, int val) ;
extern char * strsep_P (char **sp, PGM_P delim);
extern size_t strspn_P (const char *s, PGM_P accept) ; extern char * strstr_P (const char *, PGM_P) ;
S pe zi el le F un kt io ne n fü r P ro gm em
24
Zugang zu Daten aus Flash mit Assembler
.text
message2: .asciz "J.W.v. Goethe"; Daten im Flash main:
…
Ldi R31,hi8(message2); Adresse im Ldi r30,lo8(message2); Flash
L1: lpm r0,z+ ; [z++]-> r0
or r0,r0 ; if r0==0
Breq out ; then → out
Mov r24,r0 ;
rcall lcd_putc ; call lcd_putc(r0)
rjmp L1 ; loop
Out: ; go away
.text
message2: .asciz "J.W.v. Goethe"; Daten im Flash main:
…
Ldi R31,hi8(message2); Adresse im Ldi r30,lo8(message2); Flash
L1: lpm r0,z+ ; [z++]-> r0
or r0,r0 ; if r0==0
Breq out ; then → out
Mov r24,r0 ;
rcall lcd_putc ; call lcd_putc(r0)
rjmp L1 ; loop
Out: ; go away
25
EEPROM
EEMEM const char ee_str[] =
"This string from\n ** EEPROM **";
Wird abgelegt im Segment .eeprom
avr-objdump -D main.elf > main.dump liefert detaillierte Informationen
char* eeprom_s=(char*) ee_str;
while((c = eeprom_read_byte((BYTE*) eeprom_s++))){ ...}
EEMEM const char ee_str[] =
"This string from\n ** EEPROM **";
Wird abgelegt im Segment .eeprom
avr-objdump -D main.elf > main.dump liefert detaillierte Informationen
char* eeprom_s=(char*) ee_str;
while((c = eeprom_read_byte((BYTE*) eeprom_s++))){ ...}
26
uint8_t eeprom_read_byte (const uint8_t *addr);
uint16_t eeprom_read_word (const uint16_t *addr);
Void eeprom_read_block (void *pointer_ram,
const void *pointer_eeprom, size_t size);
void eeprom_write_byte (uint8_t *addr,uint8_t value);
void eeprom_write_word (uint16_t *addr,uint16_t value);
void eeprom_write_block (const void *pointer_ram, void *pointer_eeprom,
size_t size);
uint8_t eeprom_read_byte (const uint8_t *addr);
uint16_t eeprom_read_word (const uint16_t *addr);
Void eeprom_read_block (void *pointer_ram,
const void *pointer_eeprom, size_t size);
void eeprom_write_byte (uint8_t *addr,uint8_t value);
void eeprom_write_word (uint16_t *addr,uint16_t value);
void eeprom_write_block (const void *pointer_ram, void *pointer_eeprom,
size_t size);
Funktionen zur Arbeit mit dem internen EEPROM
(vereinfacht aus avr/eeprom.h)
27
EEPROM mit assembler (write)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Daten aus Flash -> eeprom
Ldi r26,lo8(message3) ; Adresse im EEPROM ldi r27,hi8(message3)
ldi R31,hi8(message4) ; Adresse im FLASH ldi r30,lo8(message4)
lwre1: lpm r0,z+ ; [Z++]-> r0
; Warten, bis vorheriges Schreiben abgeschlossen
lwre3: sbic EECR,EEWE ; skip next, if bit in PORT is clear rjmp lwre3
out EEARH, r27 ; EEPROM-Addresse (r26:r27)
out EEARL, r26; ; in EEPROM-Adressregister eintragen out EEDR,r0 ; Write data (r0) to data register
sbi EECR,EEMWE ; Write logical one to EEMWE
; nach max. 4 Takten:
sbi EECR,EEWE ; Start eeprom write by setting EEWE
adiw r26,1 ; inc EEPROM-Addresse
or r0,r0 ; 0 Byte?
breq lwre2 ; → fertig !
rjmp lwre1 ; naechstes Byte
Lwre2:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Daten aus Flash -> eeprom
Ldi r26,lo8(message3) ; Adresse im EEPROM ldi r27,hi8(message3)
ldi R31,hi8(message4) ; Adresse im FLASH ldi r30,lo8(message4)
lwre1: lpm r0,z+ ; [Z++]-> r0
; Warten, bis vorheriges Schreiben abgeschlossen
lwre3: sbic EECR,EEWE ; skip next, if bit in PORT is clear rjmp lwre3
out EEARH, r27 ; EEPROM-Addresse (r26:r27)
out EEARL, r26; ; in EEPROM-Adressregister eintragen out EEDR,r0 ; Write data (r0) to data register
sbi EECR,EEMWE ; Write logical one to EEMWE
; nach max. 4 Takten:
sbi EECR,EEWE ; Start eeprom write by setting EEWE
adiw r26,1 ; inc EEPROM-Addresse
or r0,r0 ; 0 Byte?
breq lwre2 ; → fertig !
rjmp lwre1 ; naechstes Byte
Lwre2:
. . .
EEPROM
Master Write enable
28