Forum: Mikrocontroller und Digitale Elektronik LPC2106 Variablendefinition Subroutinen debuggen


von Sven W. (woehlb)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe das Beispiel demo2106_blink zum Olimex Evaluationboard 
folgendermaßen erweitert:

test.c:
void addition(int counter){
  counter++;
}

main.c:
extern void addition(int counter);

main(){
...
int counter = 0;
...
addition(counter);
...
}

Meine erste Frage:
Im Beispiel sind einige andere Variablen in main als static vereinbart. 
Was heißt das in diesem Zusammenhang, landen diese Variablen im Flash. 
Kann aber doch eigentlich nicht sein, wenn sie nicht zusätzlich als 
const vereinbart sind. Normalerweise bleibt der Speicher bei einer 
static Variable auch außerhalb ihres Gültigkeitsbereiches reserviert, 
und damit der Speicherinhalt erhalten. Nur was hat das für einen Sinn 
auf der main() Ebene, solange das Programm läuft wird doch dieser 
Gültigkeitsbereich nicht verlassen?

Meine zweite Frage:
Was muß beim Debuggen der Funktion addition() im Flash beachtet werden. 
Genau das funktioniert bei mir nicht. Der Debugger springt nicht in 
diese Funktion, und scheint auch den Code nicht auszuführen. Außerdem 
springt er beim schrittweisen Debuggen ziemlich wild im Quellcode hin 
und her. Beim Debuggen im RAM dagegen geht alles klar.

Danke Sven!

PS:

Hier noch meine Openocd Konfiguration für den Flash:

#daemon configuration
telnet_port 4444
gdb_port 3333

#interface
interface ft2232
ft2232_device_desc "USB <-> Serial Cable A"
ft2232_layout usbjtag
ft2232_vid_pid 0x0403 0x0x6010
jtag_speed 3
#use combined on interfaces or targets that can't set TRST/SRST 
separately
reset_config trst_and_srst srst_pulls_trst

#jtag scan chain
#format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE)
jtag_device 4 0x1 0xf 0xe

#target configuration
daemon_startup reset
#target <type> <startup mode>
#target arm7tdmi <reset mode> <chainpos> <endianness> <variant>
target arm7tdmi little run_and_halt 0 arm7tdmi-s_r4
run_and_halt_time 0 30

#for ram debugging disabled
working_area 0 0x40000000 0x4000 nobackup

#flash configuration
flash bank lpc2000 0x0 0x20000 0 0 lpc2000_v1 0 14745.6 calc_checksum


Diese Befehle werden von Eclipse dem GDB zur Initialisierung übergeben:

target remote localhost:3333
monitor wait_halt
monitor sleep 500
monitor poll
monitor flash write 0 main.bin 0
monitor soft_reset_halt
monitor arm7_9 sw_bkpts disable
monitor arm7_9 force_hw_bkpts enable
monitor mww 0xE01FC040 0x0001
monitor mdw 0xE01FC040
symbol-file main.elf
set $pc=0x0


Und abschließend noch mein Makefile:

NAME   = demo2106_blink

CC      = arm-elf-gcc
LD      = arm-elf-ld -v
AR      = arm-elf-ar
AS      = arm-elf-as
CP      = arm-elf-objcopy
OD  = arm-elf-objdump

#LSCRIPT = lpc2106_ram.lkr
LSCRIPT = lpc2106_flash.lkr

CSRCS = main.c test.c

CFLAGS  = -I./ -c -fno-common -O0 -g -mcpu=arm7tdmi-s -march=armv4t
AFLAGS  = -ahls -mapcs-32 -o crt.o
LFLAGS  =  -Map main.map -T$(LSCRIPT)
CPHFLAGS = -O ihex
CPBFLAGS = -O binary
ODFLAGS  = -x --syms

all: main.elf
  @ echo "...copying"
  $(CP) $(CPHFLAGS) main.elf main.hex
  $(CP) $(CPBFLAGS) main.elf main.bin
  $(OD) $(ODFLAGS) main.elf > main.dmp

main.elf: crt.o ${CSRCS:.c=.o} $(LSCRIPT)
  @ echo "..linking"
  $(LD) $(LFLAGS) -o main.elf  crt.o ${CSRCS:.c=.o}

crt.o: crt.s
  @ echo ".assembling"
  $(AS) $(AFLAGS) crt.s > crt.lst

main.o: main.c
  @ echo ".compiling main.c"
  $(CC) $(CFLAGS) main.c

test.o: test.c
  @ echo ".compiling test.c"
  $(CC) $(CFLAGS) test.c

clean:
  -rm crt.lst crt.o ${CSRCS:.c=.o} main.elf main.hex main.bin main.map

von Sven Woehlbier (Gast)


Lesenswert?

Wie bei meinem Beitrag zum Debuggen aus dem Flash heraus gilt auch hier, 
den Flash unabhängig von der Initialisierung des GDB's vorher 
programmieren! Danach funktionierte bei mir alles.

Ein Unterschied bei der Deklaration von static Variablen zu einer 
normalen Deklaration habe ich ausgemacht. Static Variablen werden 
automatisch mit dem Wert 0 initialisiert. Haben die folgenden 
Deklaration also das selbe Ergebnis?

main(){
  int i = 0;
}

oder:

main(){
  static int i;
}

Tschau Sven!

von Karl H. (kbuchegg)


Lesenswert?

static kann je nachdem wo es benutzt wird, verschiedene
Bedeutungen haben.

* static Variablen innerhalb einer Funktion

  Bsp

  void foo( int j )
  {
    static int i = 0;

    i += j;
  }

  Hier bedeutet static: Die Variable i unterliegt nicht den
  normalen Lebenszyklus-Regeln wie andere lokale Variablen
  der Funktion.

  Die Variable i wird beim ersten Aufruf der Funktion erzeugt
  (und initialisiert) wie jede andere lokale Variable. Aber anders
  als sonstige loakle Variablen, wird i nicht beim Verlassen der
  Funktion zurstört, sondern lebt weiter bis zum endgültigen
  Programmende.
  Im obigen Beispiel realisiert i also eine Summenvariable, die
  bei jedem Funktionsaufruf den übergebenen Wert zur bisherigen
  Summe hinzuzählt. Mit einer normalen lokalen Variablen würde
  das nicht gehen, weil diese ja mit dem Beenden der Funktion
  zerstört werden würde, bzw. bei jedem Aufruf der Funktion neu
  erzeugt (und initialisiert) werden würde.

* static globale Variablen

  main.c
  ******

  static int i;

  int main()
  {
  }


  Hier hat static eine völlig andere Bedeutung.
  Wird eine globale Variable stativ gemacht, so bedeutet dies
  das ihr Sichtbarkeitsbereich auf diese Übersetzungseinheit
  (die Quellcodedatei) eingeschränkt wird.

  Würde man machen

  int i;

  int main()
  {
  }

  dann könnte man in einer anderen *.c Datei auf diese Variable
  zugreifen:

  helper.c
  ********

  extern int i;

  void foo()
  {
    i = 8;
  }

  Hier sind die in main.c definierte Variable und die in helper.c
  deklarierte Variable i, ein und dieselbe Variable.

  Durch static wird dies globale Sichtbarkeit eingeschränkt.

  main.c
  ******

  static int i;

  int main()
  {
  }

  Hier ist i nur noch in main.c sichtbar. Eine Mitbenutzung durch
  extern, wie oben, ist dadurch nicht mehr möglich.

  Gleiches gilt übrigens auch für Funktionen:

  main.c
  ******

  static void add()
  {
  }

  int main()
  {
    add();
  }

  Die Funktion add() ist nur in main.c sichtbar. In einem anderen
  *.c File kann sie nicht angesprochen werden. Es ist quasi so
  als ob die Funktion add ausserhalb von main.c nicht existiert.

von Sven Woehlbier (Gast)


Lesenswert?

Hallo Karl Heinz,

danke für Deine Antwort!

Die erste Variante war mir bekannt. Daß man mit static den 
Gültigkeitsbereich globaler Variablen bzw. Funktionen einschränken kann, 
war mir allerdings neu. :-|

Bisher habe ich in der Firma vorrangig mit relativ alten C/C++ Compilern 
von Borland gearbeitet. Erst mit der Anwendung der ARM-Prozessoren 
beschäftige ich mich überhaupt wieder mit dem GCC, und da dieser Bereich 
neu ist auch mit einer neueren GCC Version.

Soweit ich weiß gibt es mittlerweile einen neuen C/C++ Standard. Wurde 
die Bedeutung von static eventuell erweitert?


Tschau Sven!

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.