Hallo Leute,
bis jetzt glaubte ich mit "volatile" mehr oder weniger sattelfest zu
sein, aber das folgende hat mich doch verblüfft.
Ich habe ein Spartan-6 Design mit Microblaze und selbsgeschriebenem IP
core, der einen 64 KB Speicherbereich andeckt.
In diesem Speicherbereich liegen 2 Tabellen zu 16 Worten (32 Bit), an
den Offsets 0x100 und 0x140.
1 | static const uint32_t MNTable_AB_offset = 0x00000100;
|
2 | static const uint32_t MNTable_CD_offset = 0x00000140;
|
3 |
|
4 | #define MNTable_AB (uint32_t *) (XPAR_PRINTCORE_IF_BASEADDR + MNTable_AB_offset)
|
5 | #define MNTable_CD (uint32_t *) (XPAR_PRINTCORE_IF_BASEADDR + MNTable_CD_offset)
|
Eine Funktion
1 | int scanWaveFormForMNs(uint16_t *waveform, int waveformlength, volatile uint32_t *mdtable, unsigned int mdtable_size, uint16_t offset)
|
2 | {
|
3 | int i, count = 0;
|
4 | uint32_t mn;
|
5 | uint8_t mn_old = 0;
|
6 |
|
7 | for (i = 0; i < waveformlength; i++) {
|
8 | if ((*waveform++ & 0xF000) == 0xF000) {
|
9 | mn = (*waveform++ & 0xF000) >> 8;
|
10 | mn |= (*waveform++ & 0xF000) >> 12;
|
11 | if (mn != mn_old) {
|
12 | unsigned ii = i;
|
13 | mn_old = mn;
|
14 | mn <<= 10;
|
15 | ii += i != 0 ? offset : 0;
|
16 | mn |= ii & 0x3FF;
|
17 | mn |= 0xF0000000;
|
18 | mdtable[count] = mn;
|
19 | xil_printf("md[%d] = %x, rb = %x", count, mn, mdtable[count]);
|
20 | count++;
|
21 | }
|
22 | i += 2;
|
23 | }
|
24 | }
|
25 | return count;
|
26 | }
|
füllt diese Tabellen.
Man muss jetzt nicht verstehen, was die Funktion berechnet, aber an der
Stelle
mdtable[count] = mn;
sollte die Tabelle, und somit auch das IP beschrieben werden.
Der Aufruf schaut so aus:
1 | scanWaveFormForMNs((uint16_t *) Kom_Buffer, WaveformLength, MNTable_AB, MNTableSize, 8-3);
|
Lässt man das volatile in
1 | int scanWaveFormForMNs(uint16_t *waveform, int waveformlength, volatile uint32_t *mdtable, unsigned int mdtable_size, uint16_t offset)
|
weg, funktioniert das Ganze nicht, der Zugriff auf die Tabelle im IP
wird nicht ausgeführt.
Man merkt dies auch daran, weil die höchsten 8 Bits in Hardware nicht
existieren, und beim Zurücklesen mit mdtable[count] mit Nullen gefüllt
werden.
Ohne volatile wird z.B. 0xF0000400 zurückgelesen, mit volatile
korrekterweise 0x400.
Wieso können beim Optimieren einer Funktion Schreibzugriffe auf eine zu
füllende Tabelle wegoptimiert werden?
Die Optimierung der Funktion kann ja nicht wissen, was im Rest des
Programms mit diesen Daten passiert?
Optimierungsstufe ist O3.