Forum: Mikrocontroller und Digitale Elektronik AVR (ATmega644p): Wie Speicherbedarf prüfen ?


von Frank G. (dg1sbg)


Lesenswert?

Hallo zusammen,

ich schon wieder. Dank der Hilfe der Guten Geister Dieses Forums habe 
ich es geschafft, meinen ATMega644P zu programmieren. Ich bin von einem 
ATMega32 auf den 644P umgestiegen, weil ich mehr Speicher benötige. Nun 
zeigt sich aber, dass ich wahrscheinlich wieder in Speicherprobleme 
(Überlauf) reinlaufe.

Mit meinem Makefile (siehe Anhang) und
1
$ make clean && make all
2
3
Linking: psuctrl.elf
4
avr-gcc -mmcu=atmega644p -I. -gdwarf-2 -DF_CPU=8000000UL  -O2 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=controller.o -I/Users/frgo/gnc//avr/gaul -std=gnu99 -MD -MP -MF .dep/psuctrl.elf.d controller.o --output psuctrl.elf -Wl,-Map=psuctrl.map,--cref   /Users/frgo/gnc//avr/gaul/libgaul.a -Wl,-u,vfprintf -lprintf_flt  -lm
5
6
Creating load file for Flash: psuctrl.hex
7
avr-objcopy -O ihex -R .eeprom psuctrl.elf psuctrl.hex
8
9
Creating load file for EEPROM: psuctrl.eep
10
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
11
  --change-section-lma .eeprom=0 -O ihex psuctrl.elf psuctrl.eep
12
avr-objcopy: --change-section-lma .eeprom=0x00000000 never used
13
14
Creating Extended Listing: psuctrl.lss
15
avr-objdump -h -S psuctrl.elf > psuctrl.lss
16
17
Creating Symbol Table: psuctrl.sym
18
avr-nm -n psuctrl.elf > psuctrl.sym
19
20
Size after:
21
psuctrl.elf  :
22
section                     size          addr
23
.data                         692   8388864
24
.text                      23942              0
25
.bss                         1124   8389556
26
.stab                        1632              0
27
.stabstr                      198              0
28
.debug_aranges           512             0
29
.debug_pubnames     4350             0
30
.debug_info             26417             0
31
.debug_abbrev           6897            0
32
.debug_line              22310            0
33
.debug_frame            3280            0
34
.debug_str                 5554            0
35
.debug_loc               14555            0
36
.debug_ranges           1912            0
37
Total                      113375
38
39
AVR Memory Usage:
40
-----------------
41
Device: atmega644p
42
43
Program:   24634 bytes
44
(.text + .data + .bootloader)
45
46
Data:       1816 bytes
47
(.data + .bss + .noinit)
48
49
-------- end --------

Das sieht für mich immer noch gut aus, denn der 644p hat 64k Flash und 
4k SRAM. Das ist alles noch weit von dem entfernt, was ich hier sehe. 
Dennoch bleibt mein Programm hängen - was ich schon vom ATMega32 kenne.

Wie kann ich sicher erkennen, dass ich keine Speicherschreiber habe ? 
Gibt es eine Magic Formula ?

Danke im Voraus für Hinweise!

Grüße
   Frank

von Michael M. (technikus)


Lesenswert?

Leider läßt sich aus der Ausgabe von .data + .bss + .noinit der 
wirkliche SRAM-Bedarf zur Laufzeit nicht ermitteln. Denn zur Laufzeit 
kostet jede aufgerufene Funktion Platz auf dem Stack (lokale 
Variablen!). Am besten mal den wahren Speicherverbrauch zur Laufzeit 
bestimmen. Eine brauchbare Methode dazu findest Du hier:
http://www.rn-wissen.de/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc

Es kann natürlich leicht sein, daß Dein Code eigentlich mit dem SRAM 
auskommen müßte, Du aber irgendwo ein Speicherleck hast, z.B. schreiben 
über die Array-Grenzen hinaus. Das mußt Du natürlich ausschließen.

Servus
Michael

von Hubert G. (hubertg)


Lesenswert?

Für welchen Kontroller wurde der Code denn ursprünglich geschrieben?
Wie sind die LCD- und sonstige Ausgabetexte gespeichert.

von Oliver (Gast)


Lesenswert?

Auch wenn lokale Variable SRAM benötigen, sind da zunächst mal noch über 
2k frei. Da passt schon eine Menge rein.

Hast du große Arrays lokal angelegt? Nutzt du malloc, oder rekursive 
Funktionsaufrufe?

Wenn nicht, ist das sehr wahrscheinlich kein Speicherplatzproblem.

Oliver

von Frank G. (dg1sbg)


Lesenswert?

Michael M. schrieb:
> Leider läßt sich aus der Ausgabe von .data + .bss + .noinit der
> wirkliche SRAM-Bedarf zur Laufzeit nicht ermitteln. Denn zur Laufzeit
> kostet jede aufgerufene Funktion Platz auf dem Stack (lokale
> Variablen!). Am besten mal den wahren Speicherverbrauch zur Laufzeit
> bestimmen. Eine brauchbare Methode dazu findest Du hier:
> http://www.rn-wissen.de/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc

Danke für den Link !!

>
> Es kann natürlich leicht sein, daß Dein Code eigentlich mit dem SRAM
> auskommen müßte, Du aber irgendwo ein Speicherleck hast, z.B. schreiben
> über die Array-Grenzen hinaus. Das mußt Du natürlich ausschließen.

Yep, ist klar. Da der Code (bis auf eine neue Funktion, die das 
Speicher-Fass beim ATMega32 zum Überlaufen brachte) auf dem ATMega32 
läuft, habe ich bisher nicht in dieser Richtung gesucht....

> Servus
> Michael

Cheers
  Frank

von Frank G. (dg1sbg)


Lesenswert?

Hubert G. schrieb:
> Für welchen Kontroller wurde der Code denn ursprünglich geschrieben?
> Wie sind die LCD- und sonstige Ausgabetexte gespeichert.

Für den ATMega32.

Als PSTRs. Überwiegend (zu ca. 90%). Mehr geht nicht - denn die 
restlichen Strings sind Format-Strings.

Gruß,
  Frank

von Frank G. (dg1sbg)


Lesenswert?

Oliver schrieb:
> Auch wenn lokale Variable SRAM benötigen, sind da zunächst mal noch über
> 2k frei. Da passt schon eine Menge rein.
>
> Hast du große Arrays lokal angelegt?

Nein.

> Nutzt du malloc,

Nein.

> oder rekursive Funktionsaufrufe?

Nein.

> Wenn nicht, ist das sehr wahrscheinlich kein Speicherplatzproblem.

Vermute ich inzwischen auch. Sieht nach UART Problem aus, weiss aber 
nicht wieso. Denn: DAS LIEF ALLES SCHON MAL AUF EINEM ATMEGA32 ... 
Schnief!

> Oliver

Frank

von Hubert G. (hubertg)


Lesenswert?

Dann würde ich das mal mit dem Code probieren der auf dem Mega32 lief, 
der hat nur halb so viel SRAM.
Wenn das läuft dann die neue Funktion einfügen. Dann hast du zumindest 
einen Anhaltspunkt zum suchen.

von Frank G. (dg1sbg)


Lesenswert?

Hubert G. schrieb:
> Dann würde ich das mal mit dem Code probieren der auf dem Mega32 lief,
> der hat nur halb so viel SRAM.
> Wenn das läuft dann die neue Funktion einfügen. Dann hast du zumindest
> einen Anhaltspunkt zum suchen.

Jau. gelesen, getan. Alles läuft, bis auf UART. Sobald ich den UART (ich 
nutze die Lib von Peter Fleury) dazunehme, per Aufruf:

In darc.h:
1
#if !defined( DARC_BAUDRATE )
2
#define DARC_BAUDRATE                  38400 
3
#endif

In main():
1
...
2
darc_init( DARC_BAUDRATE ); // Enable communication link "DARC" using USART0
3
...
4
}

In darc.c:
1
rc_t darc_init( unsigned long nBaudrate )
2
{
3
  // Initialize UART of the controller board (uses Peter Fleury's
4
  // UART Library).
5
6
  uart_init( UART_BAUD_SELECT( nBaudrate, F_CPU ));
7
8
  // Set streams
9
10
  stdout = (FILE *) &darc_stdio;
11
  // stdin  = (FILE *) &darc_stdio;
12
13
  _darc_stream = (FILE *) &darc_stdio;
14
   
15
  // Init buffers
16
 
17
  darc_clear_receive_buffer();
18
  darc_clear_send_buffer();
19
    
20
  // Save init status
21
 
22
  bDARCIsInitialized  = TRUE;
23
  bDARCCommandAvailable = FALSE;
24
    
25
  // Done.
26
27
  return RC_OK;
28
}

uart_init() ist in Peter's Lib definiert als:
1
#if defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__)
2
 /* ATmega with two USART */
3
 #define ATMEGA_USART0
4
 #define ATMEGA_USART1
5
 #define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
6
 #define UART1_RECEIVE_INTERRUPT   SIG_USART1_RECV
7
 #define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA
8
 #define UART1_TRANSMIT_INTERRUPT  SIG_USART1_DATA
9
 #define UART0_STATUS   UCSR0A
10
 #define UART0_CONTROL  UCSR0B
11
 #define UART0_DATA     UDR0
12
 #define UART0_UDRIE    UDRIE0
13
 #define UART1_STATUS   UCSR1A
14
 #define UART1_CONTROL  UCSR1B
15
 #define UART1_DATA     UDR1
16
 #define UART1_UDRIE    UDRIE1
17
#endif
18
19
/*************************************************************************
20
Function: uart_init()
21
Purpose:  initialize UART and set baudrate
22
Input:    baudrate using macro UART_BAUD_SELECT()
23
Returns:  none
24
**************************************************************************/
25
void uart_init(unsigned int baudrate)
26
{
27
    UART_TxHead = 0;
28
    UART_TxTail = 0;
29
    UART_RxHead = 0;
30
    UART_RxTail = 0;
31
    
32
#if defined( AT90_UART )
33
    /* set baud rate */
34
    UBRR = (unsigned char)baudrate; 
35
36
    /* enable UART receiver and transmmitter and receive complete interrupt */
37
    UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN);
38
39
#elif defined (ATMEGA_USART)
40
    /* Set baud rate */
41
    if ( baudrate & 0x8000 )
42
    {
43
       UART0_STATUS = (1<<U2X);  //Enable 2x speed 
44
       baudrate &= ~0x8000;
45
    }
46
    UBRRH = (unsigned char)(baudrate>>8);
47
    UBRRL = (unsigned char) baudrate;
48
   
49
    /* Enable USART receiver and transmitter and receive complete interrupt */
50
    UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
51
    
52
    /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
53
    #ifdef URSEL
54
    UCSRC = (1<<URSEL)|(3<<UCSZ0);
55
    #else
56
    UCSRC = (3<<UCSZ0);
57
    #endif 
58
    
59
#elif defined (ATMEGA_USART0 )
60
    /* Set baud rate */
61
    if ( baudrate & 0x8000 ) 
62
    {
63
       UART0_STATUS = (1<<U2X0);  //Enable 2x speed 
64
       baudrate &= ~0x8000;
65
     }
66
    UBRR0H = (unsigned char)(baudrate>>8);
67
    UBRR0L = (unsigned char) baudrate;
68
69
    /* Enable USART receiver and transmitter and receive complete interrupt */
70
    UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
71
    
72
    /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
73
    #ifdef URSEL0
74
    UCSR0C = (1<<URSEL0)|(3<<UCSZ00);
75
    #else
76
    UCSR0C = (3<<UCSZ00);
77
    #endif 
78
79
#elif defined ( ATMEGA_UART )
80
    /* set baud rate */
81
    if ( baudrate & 0x8000 ) 
82
    {
83
      UART0_STATUS = (1<<U2X);  //Enable 2x speed 
84
      baudrate &= ~0x8000;
85
    }
86
    UBRRHI = (unsigned char)(baudrate>>8);
87
    UBRR   = (unsigned char) baudrate;
88
89
    /* Enable UART receiver and transmitter and receive complete interrupt */
90
    UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
91
92
#endif
93
94
}/* uart_init */

Ich habe keine Hinweise in Sachen USART für die Portierung von ATMega32 
auf ATMega644P gefunden ...

Gruß,
  Frank

von Oliver (Gast)


Lesenswert?

>Ich habe keine Hinweise in Sachen USART für die Portierung von ATMega32
>auf ATMega644P gefunden ...

Da gibt es schon Unterschiede, aber die lib handelt das (hoffentlich 
richtig).

Da hilft alles nichts, da ist jetzt intelligentes debugging angesagt.

Oliver

von Frank G. (dg1sbg)


Lesenswert?

Oliver schrieb:

> Da hilft alles nichts, da ist jetzt intelligentes debugging angesagt.

;-) Yep - das ist wohl wahr. Und hält mich schon ein paar Stunden auf 
Trab...

Danke nochmals.

Grüße
  Frank

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.