Forum: Compiler & IDEs Mega32: Program hängt.


von Frank G. (dg1sbg)


Angehängte Dateien:

Lesenswert?

Hallo !

Ich habe ein lange funktionierendes Programm für einen Mega32 erweitert. 
Nun läuft das Ding zwar an, aber es bleibt an einer bestimmten Stelle 
hängen. Das hatte ich früher schon mal - zu viel Speicher benötigt.

Derzeit sieht die Ausgabe des avr-gcc so aus:
1
Linking: psuctrl.elf
2
avr-gcc -mmcu=atmega32 -I. -gdwarf-2 -DF_CPU=8000000UL  -Os -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
3
4
Creating load file for Flash: psuctrl.hex
5
avr-objcopy -O ihex -R .eeprom psuctrl.elf psuctrl.hex
6
7
Creating load file for EEPROM: psuctrl.eep
8
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
9
  --change-section-lma .eeprom=0 -O ihex psuctrl.elf psuctrl.eep
10
avr-objcopy: --change-section-lma .eeprom=0x00000000 never used
11
12
Creating Extended Listing: psuctrl.lss
13
avr-objdump -h -S psuctrl.elf > psuctrl.lss
14
15
Creating Symbol Table: psuctrl.sym
16
avr-nm -n psuctrl.elf > psuctrl.sym
17
18
Size after:
19
psuctrl.elf  :
20
section             size      addr
21
.text              22422         0
22
.data                692   8388704
23
.bss                 863   8389396
24
.stab               1632         0
25
.stabstr             198         0
26
.debug_aranges       512         0
27
.debug_pubnames     4201         0
28
.debug_info        24239         0
29
.debug_abbrev       6788         0
30
.debug_line        19513         0
31
.debug_frame        3104         0
32
.debug_str          5322         0
33
.debug_loc         13478         0
34
.debug_ranges       1104         0
35
Total             104068
36
37
AVR Memory Usage:
38
-----------------
39
Device: atmega32
40
41
Program:   23114 bytes (70,5% Full)
42
(.text + .data + .bootloader)
43
44
Data:       1555 bytes (75,9% Full)
45
(.data + .bss + .noinit)
46
47
-------- end --------

Angehängte Dateien:
controller.c/.h: Der eigentliche Source Code.
libgaul.tar: TAR Datei mit Utility Library (wird auch in anderen 
Projekten erfolgreich eingesetzt)
Makefile: ...

Sieht also doch gut aus, oder?

Bin für jeden Hinweis dankbar !!!

Viele Grüße

  Frank DG1SBG

von Marcus K. (marcusk)


Lesenswert?

hier sind ein paar stellen die mir merkwürdig vorkommen:

> tRelayID get_relay_id( tRelayID nID )
> {
>   return (tRelayID) nID;
> }

der sinn des cast bzw der gesamten funktion ist mir nicht ganz klar

> uint8_t  nTmpSREG = SREG;      // Save status
dafür ist der compiler da, das macht man doch nicht selber

damit könntest du schon etwas sparen.

von gast (Gast)


Lesenswert?

> tRelayID get_relay_id( tRelayID nID )
> {
>   return (tRelayID) nID;
> }


das ist echt witzig ^^

von Frank G. (dg1sbg)


Lesenswert?

Marcus Kunze schrieb:
> hier sind ein paar stellen die mir merkwürdig vorkommen:
>
>> tRelayID get_relay_id( tRelayID nID )
>> {
>>   return (tRelayID) nID;
>> }
>
> der sinn des cast bzw der gesamten funktion ist mir nicht ganz klar

Reine Abstraktion. Das könnte ein paar Byte sparen, wenn dies 
weggelassen würde. Aber: Meine Frage ist ein wenig anders gelagert.

Lt. Compiler habe ich noch Platz ...

>> uint8_t  nTmpSREG = SREG;      // Save status
> dafür ist der compiler da, das macht man doch nicht selber

Aha. Und wie?

>
> damit könntest du schon etwas sparen.

Muss ich denn???

Danke!

Frank

von Frank G. (dg1sbg)


Lesenswert?

gast schrieb:
>> tRelayID get_relay_id( tRelayID nID )
>> {
>>   return (tRelayID) nID;
>> }
>
>
> das ist echt witzig ^^

Nicht unbedingt. Das ist die Umsetzung zwischen Software-Ebene und 
Hardware-Ebene. Wenn  ich die Relays anders beschalte bzw. verdrahte, 
kann ich hier die Addressierung zentral ändern. Zur Zeit bedeutet die 
Funktion: Die Relays sind so mit Nummern versehen, dass diese sich 
direkt als das Bit des Ports nehmen lassen. Das muss nicht immer so 
sein, v.a. wenn das selbe Grund-Programm für mehrere ähnliche Projekte 
verwendet wird.

Das ist einfach eine Abstraktionsebene (mehr).

Gruß,
  Frank

P.S. Ich lach auch gerne - nur gerade eben nicht mehr. Das Programm 
läuft immer noch nicht. ;-)

von Marcus K. (marcusk)


Lesenswert?

>> uint8_t  nTmpSREG = SREG;      // Save status
> dafür ist der compiler da, das macht man doch nicht selber

Aha. Und wie?

einfach weglassen, damit sparst du schon mal 1byte ram

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Du hast das SRAM zu fast 76% mit Variablen gefüllt und zusätzlich in 
einigen Funktionen ziemlich viel lokal auf dem Stack liegen.

Ich würde da abspecken oder versuchsweise auf den pinkompatiblen, aber 
grösseren Atmega644P wechseln 
(http://www.atmel.com/dyn/resources/prod_documents/doc8001.pdf)

von Frank G. (dg1sbg)


Lesenswert?

Marcus Kunze schrieb:
>>> uint8_t  nTmpSREG = SREG;      // Save status
>> dafür ist der compiler da, das macht man doch nicht selber
>
> Aha. Und wie?
>
> einfach weglassen, damit sparst du schon mal 1byte ram

???
Äh - wie kann denn der Compiler ahnen, dass ich das SREG sichern 
will/muss ?

Es gibt da wohl inzwischen ein Makro, ja, aber weglassen ? (Ich bin nur 
Gelegenheits-µC-Programmierer - ich komm einfach nicht drauf, wie der 
Compiler das ohne irgendwas hinbekommt).

Danke!

Gruß,
  Frank

von Peter (Gast)


Lesenswert?

Was ist besser zu lesen?
1
rc_t switch_it( tComponentClassID nObjectClassID, char **ppcTokens, uint16_t nTokenIndex )
2
{
3
  rc_t              nRC            = RC_OK;
4
  tComponentClassID nClassID       = OBJECT_CLASS_ID_INVALID_ID;
5
  uint16_t          nCurTokenIndex = nTokenIndex;
6
  char             *pcCurToken     = ppcTokens[ ++nCurTokenIndex ];
7
8
  nRC = get_key_value_pair( pcCurToken, acKey, acValue );
9
10
  if( nRC == RC_OK )
11
  {
12
    // Value -> Component Class
13
      
14
    nClassID = get_component_class_id( acKey );
15
    if( nClassID == nObjectClassID )
16
    {
17
      tIOID nIOID 
18
        = get_io_id_from_darc_value( nObjectClassID, acValue );
19
          
20
      if( nIOID != NO_IO )
21
      {
22
        // Next token = Key/value pair for mode
23
            
24
        pcCurToken = ppcTokens[ ++nCurTokenIndex ];
25
26
        nRC = get_key_value_pair( pcCurToken, &acKey, &acValue );
27
        if( nRC == RC_OK )
28
        {
29
          tIOStatus nMode = get_mode( acValue );
30
          switch_io( nObjectClassID, nIOID, nMode );
31
        }
32
        else
33
        {
34
          nRC = DARC_CAT_CMD_FC_INVALID_PARAMETER;
35
        }
36
      }
37
      else
38
      {
39
        nRC = DARC_CAT_CMD_FC_INVALID_PARAMETER;
40
      }
41
    }
42
    else
43
    {
44
      nRC = DARC_CAT_CMD_FC_INVALID_PARAMETER;
45
    }
46
  }
47
  else
48
  {
49
    nRC = DARC_CAT_CMD_FC_INVALID_PARAMETER;
50
  }
51
 
52
  return nRC;
53
}

oder
1
rc_t switch_it( tComponentClassID nObjectClassID, char **ppcTokens, uint16_t nTokenIndex )
2
{
3
  rc_t              nRC            = RC_OK;
4
  tComponentClassID nClassID       = OBJECT_CLASS_ID_INVALID_ID;
5
  uint16_t          nCurTokenIndex = nTokenIndex;
6
  char             *pcCurToken     = ppcTokens[ ++nCurTokenIndex ];
7
8
  nRC = get_key_value_pair( pcCurToken, acKey, acValue );
9
  if( nRC != RC_OK ) {
10
    return DARC_CAT_CMD_FC_INVALID_PARAMETER
11
  }
12
13
  // Value -> Component Class
14
  nClassID = get_component_class_id( acKey );
15
  if( nClassID != nObjectClassID ) {
16
     return DARC_CAT_CMD_FC_INVALID_PARAMETER
17
  }
18
19
  tIOID nIOID = get_io_id_from_darc_value( nObjectClassID, acValue );
20
  if( nIOID == NO_IO ) {
21
     return DARC_CAT_CMD_FC_INVALID_PARAMETER;
22
  }
23
24
  // Next token = Key/value pair for mode
25
  pcCurToken = ppcTokens[ ++nCurTokenIndex ];
26
27
  nRC = get_key_value_pair( pcCurToken, &acKey, &acValue );
28
  if( nRC == RC_OK ) {
29
     return DARC_CAT_CMD_FC_INVALID_PARAMETER;
30
  }
31
32
  tIOStatus nMode = get_mode( acValue );
33
  switch_io( nObjectClassID, nIOID, nMode );
34
35
  return RC_OK ;
36
}

Ja ich weiss, es gibt Leute die sagen es darf nur ein return geben, aber 
ich das ist mal ein schönes Beispiel dafür das es das ganze nicht 
lesbarer macht.

von Stefan E. (sternst)


Lesenswert?

Frank Goenninger schrieb:
> Marcus Kunze schrieb:
>>>> uint8_t  nTmpSREG = SREG;      // Save status
>>> dafür ist der compiler da, das macht man doch nicht selber
>>
>> Aha. Und wie?
>>
>> einfach weglassen, damit sparst du schon mal 1byte ram
>
> ???
> Äh - wie kann denn der Compiler ahnen, dass ich das SREG sichern
> will/muss ?

Vergiss das einfach. Marcus hat nur nicht durchschaut, was du da machst. 
Ich würde an deiner Stelle allerdings <util/atomic.h> benutzen.

von Frank G. (dg1sbg)


Lesenswert?

Stefan B. schrieb:
> Du hast das SRAM zu fast 76% mit Variablen gefüllt und zusätzlich in
> einigen Funktionen ziemlich viel lokal auf dem Stack liegen.

Yep. Das ist sicherlich das Problem ...

>
> Ich würde da abspecken oder versuchsweise auf den pinkompatiblen, aber
> grösseren Atmega644P wechseln
> (http://www.atmel.com/dyn/resources/prod_documents/doc8001.pdf)

Ist bestellt ;-)

Danke!

Gruß,
  Frank

von Frank G. (dg1sbg)


Lesenswert?

Peter schrieb:

> rc_t switch_it( tComponentClassID nObjectClassID, char **ppcTokens,
> uint16_t nTokenIndex )
> {
>   ....
>   // Next token = Key/value pair for mode
>   pcCurToken = ppcTokens[ ++nCurTokenIndex ];
>
>   nRC = get_key_value_pair( pcCurToken, &acKey, &acValue );
>   if( nRC == RC_OK ) {
>      return DARC_CAT_CMD_FC_INVALID_PARAMETER;
>   }
>
>   tIOStatus nMode = get_mode( acValue );
>   switch_io( nObjectClassID, nIOID, nMode );
>
>   return RC_OK ;
> }

Stimmt. Übernommen. Nur: Programm damit auch nicht kleiner geworden ;-)

Gruß,
  Frank

von Frank G. (dg1sbg)


Lesenswert?

Stefan Ernst schrieb:
> Frank Goenninger schrieb:
>> Marcus Kunze schrieb:
>>>>> uint8_t  nTmpSREG = SREG;      // Save status
>>>> dafür ist der compiler da, das macht man doch nicht selber
>>>
>>> Aha. Und wie?
>>>
>>> einfach weglassen, damit sparst du schon mal 1byte ram
>>
>> ???
>> Äh - wie kann denn der Compiler ahnen, dass ich das SREG sichern
>> will/muss ?
>
> Vergiss das einfach. Marcus hat nur nicht durchschaut, was du da machst.
> Ich würde an deiner Stelle allerdings <util/atomic.h> benutzen.

Jau. Sicherlich. Der Ur-Quelltext stammt noch aus einer Zeit, als es 
atomic.h noch nicht gab...

Danke übrigens - ich dachte schon, ich hätte was Grundlegendes nicht 
mitbekommen.

Gruß,
  Frank

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Hast Du auch mal an die Stack-Variablen gedacht? 70% full heisst hier 
statische Variablen, da bleibt nicht allzu viel fuer den Stack.

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.