ARM-GCC/Cortex M3: Zeiger ist Zeiger auf?

OP #3555132
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.
Angehängte Dateien:
Gast #3555158
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.
Gast #3555185
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...
OP #3555195
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.
Angehängte Dateien:
Gast #3555203
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.

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