Mit gdb auf (Peripherie)Register zugreifen

OP #2262982
Lesenswert?

Hallo,
ich bin momentan noch darüber mich an gdb (bzw. ddd) zu gewöhnen und 
stehe jetzt vor folgendem Problem. An sich möchte ich nur die 
Registerinhalte anschauen. Z.B. in das TWCR (Two-Wire Control Register) 
um eben zu sehen welche Bits gesetzt sind. Mit dem AVR Studio ist das ja 
überhaupt kein Problem und auch noch schön bunt und idiotensicher 
gemacht, aber wie mache ich das mit dem gdb?

Auf http://www.oreilly.de/german/freebooks/rlinux3ger/ch142.html habe 
ich schon entdeckt wie ich den Inhalt eines bestimmten Adressbereichs 
ausgeben kann, nämlich mittels
1
x/3x 0x00800108
erhalte ich den Inhalt von 3 Bytes beginnend an der Adresse 0x00800108. 
Nur möchte ich den u.U. auch ändern und da meckert dbg bzw. ddd. Das ist 
das eine Problem und das andere ist, wie adressiere denn das Register 
TWCR? Wenn ich einen Blick in die
1
/usr/lib/avr/include/avr/iocanxx.h
werfe, dann finde ich dort
1
/* RegDef:  TWI Control Register */
2
#define TWCR   _SFR_MEM8(0xBC)
Das _SFR_MEM8 ist wiederum in
1
/usr/lib/avr/include/avr/sfr_defs.h
definiert und schaut wie folgt aus
1
#define _SFR_MEM8(mem_addr) (mem_addr)
Was doch bedeutet, dass mem_addr unverändert bleibt. Sprich obiger Wert 
für TWCR ist und bleibt 0xBC während z.B. IO-Register noch eine 
Verschiebung erfahren.
1
#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)

Werfe ich jetzt einen Blick ins Datenblatt des at90can128 
(http://www.atmel.com/dyn/resources/prod_documents/doc4250.pdf) finde 
ich im Kapitel Memories (4.) eine Übersicht zu den Speicherbereichen
1
,------------------------------.
2
|    32     |  Size   32 bytes |
3
| Registers |  0x0000 - 0x001F |
4
|-----------|------------------|
5
|  I/O      |  Size   64 bytes |
6
| Registers |  0x0020 - 0x005F |
7
|-----------|------------------|
8
| Ext I/O   |  Size  160 bytes |
9
| Registers |  0x0060 - 0x00FF |
10
`------------------------------´
Wenn ich jetzt versuche mein 0xBC richtig einzuordnen, dann müsste ich 
das doch in den Ext I/O Registern wiederfinden, oder? Aber woher weiß 
denn mein Compiler, dass er aus dem 0xBC eigentlich 0x00BC machen 
müsste? Er hat doch auch nur die gleichen Header zur Verfügung. Wenn ich 
dann noch einen Blick in meine Anwendung.map werfe, finde ich noch ganz 
andere Adressen, z.B.  diese
1
0x00800108     tmp_counter
Der interne SRAM liegt aber laut Datenblatt nur zwischen 0x0100 und 
0x10FF wie passt das jetzt zusammen?

Ich fasse noch einmal kurz zusammen. Wie kann ich auf die speziellen 
µController-Register zugreifen und diese auch ändern?
Wäre nett wenn mir da jmd auf die Sprünge helfen könnte :)
Danke,
Thorsten
OP #2264439
Lesenswert?

Dem konstruktiven Schweigen konnte ich schon einmal entnehmen, dass ich 
ja einfach einen Pointer anlegen könnte, der auf das jeweilige Register 
zeigt.
1
unsigned char *TWCR_ptr = &TWCR;
Klappt auch wie erwartet, aber das ist jetzt nicht die Antwort, die ich 
mir erhofft habe :) Schließlich will ich nicht für jedes Register einen 
extra Pointer anlegen.
#2264843
Lesenswert?

Thorsten S. schrieb:
>
1
0x00800108     tmp_counter
> Der interne SRAM liegt aber laut Datenblatt nur zwischen 0x0100 und
> 0x10FF wie passt das jetzt zusammen?

Der AVR hat bekanntermassen getrennte Adressräume für Code und Daten, 
d.h. die Adresse 0x108 kann zwei verschiedene Orte meinen, was 
gcc/binutils wohl nicht so einfach unterstützt. In der avr-gcc Toolchain 
ist das dann halt so implementiert, dass der Daten-Adressraum ab 
0x800000 beginnt und der Linker damit umzugehen weiß.


Zum Schreiben mit gdb an beliebige Adressen funktioniert ein
1
set *(uint8_t *)0xabcd = 1234
 Wenn das zu viel Schreibarbeit ist, kann man ja in gdb Makros 
definieren ("define" in der gdb Dokumentation).

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren