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
charreadflash(uintptr_ti){
2
uint32_ttemp;
3
uint32_taddress=i/4+FLASH_OFFSET;
4
uint8_tbyteno=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
constunsignedcharFont58Lookup[]={
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
charreadflash(uintptr_ti){
4
uint32_taddress=i+FLASH_OFFSET;
5
return*(char*)address;
6
}
Mich interessiert nicht die Berichtigung, sondern der Grund der
Adressierung.
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.
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
charmyByte=*pointerToRAM;
In deinem Fall sind die Daten ja in einem Array, dann gehts natürlich
ganz einfach:
1
charmyByte=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.
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...
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.
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_ti=0;i<4294967295;i++){
2
outputAChar(*((char*)i));
3
}
Sind ja nur 4GB. Je nach Wunsch den Zählbereich eingrenzen.