Forum: Mikrocontroller und Digitale Elektronik ARM-GCC/Cortex M3: Zeiger ist Zeiger auf?


von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
ich habe gerade ein Verständnisproblem: Der Cortex-M3 ist ein 
32-Bit-Prozessor, also sollte eine Speicheradresse 32 Bit umfassen (?).

Ich lese den Speicher byteweise aus und stelle  ihn auf einem 
Grafikdisplay dar:
1
char readflash(uintptr_t i) {
2
  uint32_t temp;
3
  uint32_t address = i/4 +FLASH_OFFSET;
4
  uint8_t byteno   = i%4;
5
6
  temp = *( (uint32_t *) address);
7
  return (char) (temp>>(8*byteno));
8
}
Für jedes i wird eine 8 Pixel breite Spalte gesetzt. Das Ganze zeigt in 
eine Region des Flashs, die wie folgt gefüllt ist:
1
const unsigned char Font58Lookup [] = {
2
  6,                                  // Fontbreite
3
  CP_COMPACT,                         // Codepage
4
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5
  ....
6
  0x14, 0x7f, 0x14, 0x7f, 0x14, 0x00,  // #
7
  0x24, 0x2a, 0x7f, 0x2a, 0x12, 0x00,  // $
8
  0xc4, 0xc8, 0x10, 0x26, 0x46, 0x00,  // %
9
  0x36, 0x49, 0x55, 0x22, 0x50, 0x00,  // &
10
  0x00, 0x05, 0x03, 0x00, 0x00, 0x00,  // '
11
  0x00, 0x1c, 0x22, 0x41, 0x00, 0x00,  // (
12
  0x00, 0x41, 0x22, 0x1c, 0x00, 0x00,  // )
13
  0x14, 0x08, 0x3E, 0x08, 0x14, 0x00,  // *
14
  0x08, 0x08, 0x3E, 0x08, 0x08, 0x00,  // +
15
  0x00, 0x00, 0xA0, 0x60, 0x00, 0x00,  // ,
16
  0x10, 0x10, 0x10, 0x10, 0x10, 0x00,  // -
17
  0x00, 0x60, 0x60, 0x00, 0x00, 0x00,  // .
18
  0x20, 0x10, 0x08, 0x04, 0x02, 0x00,  // /
19
  0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00,  // 0
20
  0x00, 0x42, 0x7F, 0x40, 0x00, 0x00,  // 1
21
...
also eine Zeichensatztabelle. Bei einem Blick aufs Display werden alle 
32-Bit-Blöcke beim inkrementieren von i jeweils nur um 1 Byte und nicht 
um 4 Byte inkrementiert.

Und ich verstehe nicht warum.

Wo liegt mein Denkfehler?

Viele Grüße
W.T.

Edit: Wie's korrekt dargestellt wird ist klar:
1
  #define FLASH_OFFSET 0x08000000
2
  #define FLASH_END    (64*1024)
3
char readflash(uintptr_t i) {
4
  uint32_t address = i +FLASH_OFFSET;
5
  return *(char *) address;
6
}
Mich interessiert nicht die Berichtigung, sondern der Grund der 
Adressierung.

: Bearbeitet durch User
von Jim M. (turboj)


Lesenswert?

Walter Tarpan schrieb:
> Der Cortex-M3 ist ein
> 32-Bit-Prozessor, also sollte eine Speicheradresse 32 Bit umfassen (?).

Nein, der Speicher wird als Byte addressiert. Wenn Du 32 Bits (=4 
Byte) speicherst, belegst Du 4 Addressen (0, 1, 2, 3).

Der 32 Bit Core kann die 4 Byte aber in einem Zyklus schreiben.

von Dr. Sommer (Gast)


Lesenswert?

Walter Tarpan schrieb:
> Hallo zusammen,
> ich habe gerade ein Verständnisproblem: Der Cortex-M3 ist ein
> 32-Bit-Prozessor, also sollte eine Speicheradresse 32 Bit umfassen (?).
Kommt drauf an was du damit meinst?! Zeiger=Adressen sind 32bit lang, 
ja. Aber jede adressierbare Speicherstelle umfasst wie bei der großen 
Mehrzahl aller Plattformen 1 Byte=8Bits. In C ist ein "char" immer 
genau eine Speicherstelle, und jede Adresse identifiziert im Endeffekt 
genau einen char. Mit anderen Worten: Die Adressen zweier 
aufeinanderfolgender 'char' im Speicher hat die Differenz '1'.
> Ich lese den Speicher byteweise aus und stelle  ihn auf einem
Diese Funktion ist völlig sinnlos. Um auf einer Plattform mit 8bit=1Byte 
(wie AVR, ARM, x86, MIPS, ...) in C auf ein Byte im Adressraum 
zuzugreifen, musst du lediglich einen char-Pointer dereferenzieren, 
z.B.:
1
char* pointerToRAM = (char*) ... ;
2
char myByte = *pointerToRAM;
In deinem Fall sind die Daten ja in einem Array, dann gehts natürlich 
ganz einfach:
1
char myByte = Font58Lookup [arrayIndex];
wobei arrayIndex zwischen 0 und der Größe von Font58Lookup sein muss.

Deine ganze komische Rechnerei da ist völlig unnötig...

Zu beachten ist allerdings: Das mit dem Pointer funktioniert nur bei 
"char"; bei größeren Datentypen ist je nach Plattform Vorsicht geboten, 
z.B. unter ARMv6 (Cortex-M0, <= ARM11) muss zum Laden eines 
short,int,long long die Adresse ein Vielfaches von 4 sein. Bei ARMv7M 
(Cortex-M3,4) müssen die Adressen von long long Vielfaches von 4 sein, 
bei int und kleiner egal. Such nach "unaligned" im ARMv* Architecture 
Reference Manual für mehr Infos.

von Dr. Sommer (Gast)


Lesenswert?

PS: Vertan, bei ARMv6 müssen die Adressen von "shorts"'s nur Vielfache 
von 2 sein.

Aber unbeschadet der Einschränkungen bzgl. Adressen funktionieren 
Array-Zugriffe immer direkt in C; einfach immer per arrayName[Index] 
zugreifen und Pointer-Rechnerei wirklich nur dann verwenden wenn man 
ganz genau weiß was man tut...

von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Jim Meba schrieb:
> Der 32 Bit Core kann die 4 Byte aber in einem Zyklus schreiben.

Dr. Sommer schrieb:
> "char" immer
> genau eine Speicherstelle, und jede Adresse identifiziert im Endeffekt
> genau einen char. Mit anderen Worten: Die Adressen zweier
> aufeinanderfolgender 'char' im Speicher hat die Differenz '1'.

Dr. Sommer schrieb:
> z.B. unter ARMv6 (Cortex-M0, <= ARM11) muss zum Laden eines
> short,int,long long die Adresse ein Vielfaches von 4 sein.

Danke für die Informationen! Ich war irgendwie dem Irrtum ausgesetzt, 
daß die Speicheradresse je einer Registerbreite entspricht.

Dr. Sommer schrieb:
> Diese Funktion ist völlig sinnlos.

Danke auch für diesen hilfrechen Kommentar :-)

Die Funktion stellt die Speicherbelegung (Flash, SRAM oder EEPROM) dar. 
Im Anhang bei einem ATmega32 (Bereich 1kB-2kB), der beim Init mit 0xAA 
gefüllt wurde. Man sieht: Zwischen Stack und Heap sind noch genau 201 
Bytes frei. Ich find's nützlich. Und mit den Zeichensatztabellen läßt 
sie sich eben gut testen.

von Dr. Sommer (Gast)


Lesenswert?

Walter Tarpan schrieb:
> Man sieht: Zwischen Stack und Heap sind noch genau 201
> Bytes frei. Ich find's nützlich
Na das ist auch eine kreative Debugging-Technik. ARM-Entwickler nehmen 
für sowas JTAG und einen Debugger... :-D

Ok wenn man den kompletten Adressraum ausgeben will kann man das tun, 
aber eben nicht mit dieser komischen Rechnerei... Wenn schon so ähnlich:
1
for (uintptr_t i = 0; i < 4294967295; i++) {
2
  outputAChar (*((char*) i));
3
}
Sind ja nur 4GB. Je nach Wunsch den Zählbereich eingrenzen.

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.