Hallo,
ich hoffe Ihr könnt mir weiterhelfen, da ich ein recht mehrkwürdiges
Problem beim Debuggen habe.
Ich bin erst kürzlich in die Mikrocontroller-Programmierung eingestiegen
und habe ein Evalations-Board mit einem AT91SAM7X256 und einen JTAG
J-Link für ARM. Als IDE verwende ich Eclipse unter Windows XP mit
ZylinCDT und dem yagarto Toolchain, sowie den J-Link GDB-Server
Ich habe alles nach folgender Anleitung eingerichtet:
http://www.yagarto.de/howto/yagarto2/index.html
Ich habe ein einfaches Projekt geschrieben, mit einer Ausgabe über
Seriell und einem blinkenden LED.
Das kuriose ist, dass ich es schon auf dem Board via JTAG debuggen
konnte aber neuerdings geht es nicht mehr. Dabei bin ich mir nicht
bewußt etwas verstellt zu haben. Auch ein Löschen von Eclipse und eine
erneute Einrichtung schaffte keine Abhilfe.
Wenn ich das Projekt das erste mal aus Eclipse heraus debugge kommt
folgende Meldung:
Soweit ich das bewerten kann ist deine Debug-Configuration in Eclipse
verbogen.
Hast du unter GDB- commandline eine Datei angegeben die ein Kommando
'info proc' enthält? Oder unter dem Tab. Commands solch ein Kommando
eingegeben?
Da grabe mal.
Unter Command File habe ich wie im HowTo beschriben die Datei
sam7x256_ram_jlink.gdb angegeben.
Inhalt ist:
1
#
2
# This config file was tested with J-Link GDB Server v4.04
3
#
4
5
# Listening for commands on this PC's tcp port 2331
6
target remote localhost:2331
7
8
# Set gdb server to little endian
9
monitor endian little
10
11
# Set JTAG speed to 30 kHz
12
monitor speed 30
13
14
# Reset the chip to get to a known state.
15
monitor reset 8
16
monitor sleep 10
17
18
#
19
# Disable the watchdog and setup the PLL
20
#
21
22
# WDT_MR, disable watchdog
23
monitor writeu32 0xFFFFFD44 = 0x00008000
24
25
# CKGR_MOR
26
monitor writeu32 0xFFFFFC20 = 0x00000601
27
monitor sleep 10
28
29
# CKGR_PLLR
30
monitor writeu32 0xFFFFFC2C = 0x00480a0e
31
monitor sleep 10
32
33
# PMC_MCKR
34
monitor writeu32 0xFFFFFC30 = 0x00000007
35
monitor sleep 10
36
37
# PMC_IER
38
monitor writeu32 0xFFFFFF60 = 0x00480100
39
monitor sleep 100
40
41
# Set JTAG speed in khz
42
monitor speed 12000
43
44
load
45
break main
46
continue
Wenn ich im Debugger einzeln durchsteppe. Bekomme ich bei der
Konfiguration der Debugschnittstelle die meldung, dass er eine
lib1funcs.asm nicht finden könne.
Du mußt das Ganze etwas präziser beschreiben.
Wann machst du genau was und was sind die Ausgaben Konsolenfenster in
Eclipse dazu.
Wenn er Datei Namens lib1funcs.asm nicht findet ist die Lage doch
eindeutig. Er versucht nach einem Step oder Breakpoint den Source dieser
Stelle anzuzeigen. Dazu benötigt er die Datei, die er aber nicht findet.
Warum steht auf einem anderen Blatt.
Dann willst du aber doch die Bibliothek debuggen. Damit wiederum
musst du aber (damit das Sinn hat) auch den Sourcecode der
Bibliothek in Reichweite haben. Was erwartest du, wie der Debugger
dich durch die einzelnen Stufen von printf() hindurch geleiten
könnte (bis zur Ausgabe des Zeichens "ganz unten"), wenn er den
entsprechenden Sourcecode nicht finden kann?
Nein, der Sourcecode ist kein Bestandteil der Debug-Informationen
in der Objektdatei. Dort stehen lediglich Zeiger (Dateiname und
Zeilennummer) auf die Quelle.
Naja, wenn dein printf() nicht geht, hast du zwei Varianten:
. Du installierst in der Tat den Sourcecode für die Bibliothek und
hangelst dich mit dem Debugger durch. Der Sourcecode muss natürlich
zum Objektcode passen, am sinnvollsten, indem man die Bibliothek
gleich selbst compiliert.
. Du liest die Dokumentation und versuchst herauszufinden, was du
falsch gemacht hast. ;-) Irgendwo muss ja dokumentiert sein, wie
das backend für stdio beschaffen sein muss, damit die Ausgaben
auch am gewünschten Gerät ankommen.
Jörg Wunsch schrieb:
> . Du liest die Dokumentation und versuchst herauszufinden, was du> falsch gemacht hast. ;-) Irgendwo muss ja dokumentiert sein, wie> das backend für stdio beschaffen sein muss, damit die Ausgaben> auch am gewünschten Gerät ankommen.
Wahrscheinlich würde es auch vernünftig, erst mal herauszufinden, wie
dieser printf Unterbau beschaffen sein muss und diesen erst mal in den
vorhandenen Sourcen zu identifizeren und sich anzusehen, was da
eigentlich abgeht.
1
#include"typedefs.h"
2
#include"dbgu.h"
3
#include"board.h"
4
#include<stdio.h>
5
6
7
intmain(void)
8
{
9
DBGU_Configure(DBGU_STANDARD,115200,MCK);
10
printf("test");
11
12
return(0);
13
}
ich tippe mal auf "board.h"
Eventuell wäre es auch schlau, zuerst die System Header zu inkludieren
und erst dann die spezifischen. So nach dem Muster: gib den spezifischen
Teilen die Chance, die allgemein gültigen aus den Systemheadern zu
überschreiben. (Das kann, muss aber nicht Abhilfe sein)
Unter YAGARTO wird die newlib verwendet. Die erfordert auch eine
syscalls.c für die low-level Funktionen. printf() nutzt diese dann z.B.
um eine Ausgabe zu machen.
In deinem YAGARTO-Verzeichnis in der Datei yagarto_newlib.txt solltest
du einen Hinweis darauf finden. Dort wird dann auf die syscalls.c
verwiesen mittels diesem Link:
http://www.yagarto.de/download/yagarto/syscalls.c
Dort gibt es z.B. einen Routine write_r(...) die eine Ausgabe auf den
uart schicken sollte (ist dort mit '#if 0' ausgeklammert.
Diese Datei (syscalls.c) müßtest du eigentlich irgendwie dazulinken,
weil sonst dein Linker über fehlende Symbole meckert. Und die Datei
müßtest du so ändern dass die Stubs in dieser Datei eine sinnvolle
Funktion ergeben.
Auf der YAGARTO-Seite ist sehr schön beschrieben, was man alles machen
muß.
Falls es sich um ein Beispiel aus der AT91-Library handelt: Atmel nutzt,
zumindest in der evtl. nicht ganz aktuellen Version, die ich mir zuletzt
angeschaut habe, eigene Implementierungen von printf. Der Quellcode dazu
findet sich in den Beispielenprojeketen (utils/stdio.c o.ä.). Diese
nutzt putc, dass ebenfalls in projektspezifischem Code implementiert
ist, und das leitet die Zeichen an den DBGU-"UART". Langer Rede: wurden
die Atmel-Beispiel-Makefiles unverändert genutzt oder selbst etwas
zusammengebastelt? Es sieht so aus, als würden newlib-stdio und AT91LIB
stdio irgendwie gemixt, wenn ja, kann das die Ursache für die Probleme
sein. Die Linker-Optionen und -Reihenfolge müssen sorgfältig gesetzt
werden.
@Martin Thomas
Das Mischen ist in der Tat wohl das Problem, wie ich festgestellt habe.
Das erste Beispielprogramm was ich hatte war das von der Yagarto-Seite.
Darauf aufbauend wollte ich nun ein Atmel-Beispiel implementieren.
Im util-Ordner von Atmel gibt es allerdings keine stdio.c. Allerdings
eine trace.c in der folgendes vermerkt ist.
Ich habe jetzt statt DBGU_CONFIGURE TRACE_CONFIGURE aus der trace.h
verwendet und kann nun zumindest mit DBGU_PutChar was auf der
Debug-Schnittstelle ausgeben.
Printf will aber immer noch nicht.
Vielleicht bin ich blind aber ich finde keine Infos zu der syscalls.c
auf der yagarto-Seite. Die Datei selbst habe ich aber schon im Projekt.
Christian L. schrieb:
> Vielleicht bin ich blind aber ich finde keine Infos zu der syscalls.c> auf der yagarto-Seite.
Hmmm.... ich find das auch grad nicht wieder. :-/
Sonst lies dir auch die Datei "yagarto_newlib.txt" in deiner
YAGARTO-Installation.
Ich formuliere die Frage mal um. Wie bekomme ich printf zum Debuggen
über die Debugschnittstelle ans laufen? Ich habe nun mal im Detail
geguckt und die Atmel-Beispiele sind ja alle für IAR und dort sind die
Bibliotheken doch recht anders als die von yagarto.
Falls es Beispiele von YAGARTO gibt, versuche die. Ansonsten hat Martin
Thomas auf seiner Webseite sehr viele funktionierende Beispiele auch für
ARM. Den Link hab ich gerade nicht.
So den Link hab ich auch:
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/index.html
Das sind jede Menge Beispiele. Weches davon jetzt gerade die syscalls.c
mit nutzt, das muß er selber hier mal mitteilen. Das brauchst du für die
printf() Funktion. Jedenfalls weiß ich keinen anderen weg.
Ich hoffe er liest noch mit :-)
Soweit erinnert, ist das "gamma"-Beispiel mit syscalls und newlib-stdios
(i)printf. Grade nicht sicher, ob write an die DGBU oder einen
"normalen" UART gebunden ist. Wenn nicht ersichtlich, nochmal fragen,
ich schaue dann in den Code.
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/index_at91.html#at91_gamma
Die Atmel AT91LIB-Methode printf komplett selbst zu implementieren
findet man in deren Quellcode. Zumindest in der Version der des
AT91-Software-Packages für AT91SAM7S-EK und AT91SAM7X-EK, in die ich
zuletzt reingeschaut habe, werden sehr wohl GNU-Tools unterstützt (nicht
nur IAR EWARM). (Nochmal) Wenn richtig erinnert, habe ich den
betreffenden Atmel-Code auch in meinem AT91-SD-Card-Bespiel verwendet.
Habe auch da jetzt nicht reingeschaut, kann ich aber bei Bedarf machen.
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/arm_memcards/index.html#chanfat_at91sam7
Ich habe mal versucht mit Hilde Deines Gamma-Beispieles ein
minimalistisches Programm zu schreiben, welches nur etwas auf der
Debug-Schnittstelle ausgibt.
1
#include<stdint.h>
2
#include<stdio.h>
3
4
#include"board.h"
5
#include"dbgu.h"
6
7
8
intmain(void){
9
// Set-up DBGU Usart ("UART2")
10
11
AT91F_DBGU_Init();
12
iprintf("1234567890");
13
AT91F_DBGU_Printk("\r\n\r\ntest\r\n");
14
}
mit iprintf kommt auf der Schnittstelle gar nichts an und mit
AT91_DBGU_Printk nur Müll.
dbgu.c und h sowie die syscalls.c sind aus dem Gamma-Projekt.
Es gab einen Error bezüglich isatty. Dieser war nach folgender Änderung
der syscalls.c verschwunden.
1
int_isatty(intfile);/* avoid warning */
2
3
int_isatty(intfile)
4
{
5
return1;
6
}
Wobei ich nicht weiß, ob man da ohne weiteres einen Unterstrich
vorschreiben kann.
> Wobei ich nicht weiß, ob man da ohne weiteres einen Unterstrich> vorschreiben kann.
Kann man, aber man sollte wissen, warum man ihn davor schreibt :)
Bei _funktionen ist die Übereinkunft, dass die zum System
(Systemlibrary) gehören also dass es keine übliche Anwenderfunktion ist.
Das Einhalten der Übereinkunft erleichtert den Eingeweihten die
Codelesbarkeit und das Codeverständnis.
wenn im System allerdings die Funktion fehlt, andere Teile des Systems
sie aber referenzieren, dann kann der Anwender als Bugfix oder
Workaround die Funktion nachträglich implementieren. Das scheint hier zu
passieren.
Eine ähnliche Übereinkunft gibt es bei Makros mit oder _. Makros mit
diesen Namen "gehören" dem Compiler.