Forum: Compiler & IDEs pgm_read_word_far und Compiler-Warnung


von Markus (Gast)


Lesenswert?

Hallo zusammen,

für den CodeCheck in meinem Programm bilde ich mit Hilfe einer 
CRC-Tabelle einen Check über den Flash-Speicher.

Die Tabelle liegt ebenfals mit PROGMEM im Programmspeicher.

Jetzt habe ich das gleiche beim Bootloader für einen ATMEGA1284P 
gemacht.
Hier liegt die Tabelle jetzt natürlich im Bootloader-Bereich. Für den 
Zugriff benutze ich deshalb pgm_read_word_far.

Funktionieren tut es wunderbar, allerdings bekomme ich eine Warnung vom 
Compiler, die ich nicht verstehe, und auch durch casten nicht weg 
bekomme.

Die CRC-Prüfung im Code sieht so aus:
1
for (u32_ByteInd = u32_Start; u32_ByteInd < u32_End-2; u32_ByteInd++)
2
  {
3
    uiCRC = pgm_read_word_far(Crctab + (uiCRC >> 8)) ^ ((uiCRC & 0x00ff) << 8) ^ pgm_read_byte_far(u32_ByteInd);
4
  }
5
  if (    ((uiCRC >> 8)   != pgm_read_byte_far(u32_End-2))
6
       || ((uiCRC & 0xFF) != pgm_read_byte_far(u32_End-1))
7
     )
8
    {
9
        u8_Fehler = 1;
10
    }

Und der Compiler meckert:

warning: cast from pointer to integer of different size

Die Warnung bezieht sich auf jeden Fall auf das pgm_read_word_far, denn 
im ursprünglichen Code, in dem die Tabelle am Anfang des Flashs lag, war 
es nur pgm_read_word und da kam keine Warnung.

Hat jemand ne Ahnung, wo das Problem liegt was ich dagegen tun kann?

Viele Grüße

Markus

von Stefan E. (sternst)


Lesenswert?

Schön, dass du von keiner der beteiligten Variablen die Deklaration mit 
angegeben hast. Raten macht ja auch viel mehr Spaß. Und auf welche der 
Zeilen, die ein pgm_read_byte_far enthalten, sich die Warnung bezieht, 
hast du auch nur indirekt mitgeteilt. Das zeigt, dass du mitdenkst, denn 
mehr Raten bedeutet natürlich mehr Spaß.

Ok, fangen wir an mit dem Raten:
Die Warnung bezieht sich auf "pgm_read_word_far(Crctab + (uiCRC >> 8))" 
und Crctab ist ein PROGMEM-Array. In dem Fall liegt das eigentliche 
Rätsel hier:
> Funktionieren tut es wunderbar
Sicher, dass du den Bootloader richtig platziert hast, er also 
tatsächlich oberhalb von 64k liegt?

von Markus (Gast)


Lesenswert?

ok, hier nochmal komplett
1
Tu16 Crctab[256] PROGMEM =                                           //PROGMEM um Tabelle im Flash zu speichern
2
{
3
0x0000,0x1021,0x2042,0x3063,0x4084,0x50A5,0x60C6,0x70E7,0x8108,0x9129,
4
0xA14A,0xB16B,0xC18C,0xD1AD,0xE1CE,0xF1EF,0x1231,0x0210,0x3273,0x2252,
5
0x52B5,0x4294,0x72F7,0x62D6,0x9339,0x8318,0xB37B,0xA35A,0xD3BD,0xC39C,
6
0xF3FF,0xE3DE,0x2462,0x3443,0x0420,0x1401,0x64E6,0x74C7,0x44A4,0x5485,
7
0xA56A,0xB54B,0x8528,0x9509,0xE5EE,0xF5CF,0xC5AC,0xD58D,0x3653,0x2672,
8
0x1611,0x0630,0x76D7,0x66F6,0x5695,0x46B4,0xB75B,0xA77A,0x9719,0x8738,
9
0xF7DF,0xE7FE,0xD79D,0xC7BC,0x48C4,0x58E5,0x6886,0x78A7,0x0840,0x1861,
10
0x2802,0x3823,0xC9CC,0xD9ED,0xE98E,0xF9AF,0x8948,0x9969,0xA90A,0xB92B,
11
0x5AF5,0x4AD4,0x7AB7,0x6A96,0x1A71,0x0A50,0x3A33,0x2A12,0xDBFD,0xCBDC,
12
0xFBBF,0xEB9E,0x9B79,0x8B58,0xBB3B,0xAB1A,0x6CA6,0x7C87,0x4CE4,0x5CC5,
13
0x2C22,0x3C03,0x0C60,0x1C41,0xEDAE,0xFD8F,0xCDEC,0xDDCD,0xAD2A,0xBD0B,
14
0x8D68,0x9D49,0x7E97,0x6EB6,0x5ED5,0x4EF4,0x3E13,0x2E32,0x1E51,0x0E70,
15
0xFF9F,0xEFBE,0xDFDD,0xCFFC,0xBF1B,0xAF3A,0x9F59,0x8F78,0x9188,0x81A9,
16
0xB1CA,0xA1EB,0xD10C,0xC12D,0xF14E,0xE16F,0x1080,0x00A1,0x30C2,0x20E3,
17
0x5004,0x4025,0x7046,0x6067,0x83B9,0x9398,0xA3FB,0xB3DA,0xC33D,0xD31C,
18
0xE37F,0xF35E,0x02B1,0x1290,0x22F3,0x32D2,0x4235,0x5214,0x6277,0x7256,
19
0xB5EA,0xA5CB,0x95A8,0x8589,0xF56E,0xE54F,0xD52C,0xC50D,0x34E2,0x24C3,
20
0x14A0,0x0481,0x7466,0x6447,0x5424,0x4405,0xA7DB,0xB7FA,0x8799,0x97B8,
21
0xE75F,0xF77E,0xC71D,0xD73C,0x26D3,0x36F2,0x0691,0x16B0,0x6657,0x7676,
22
0x4615,0x5634,0xD94C,0xC96D,0xF90E,0xE92F,0x99C8,0x89E9,0xB98A,0xA9AB,
23
0x5844,0x4865,0x7806,0x6827,0x18C0,0x08E1,0x3882,0x28A3,0xCB7D,0xDB5C,
24
0xEB3F,0xFB1E,0x8BF9,0x9BD8,0xABBB,0xBB9A,0x4A75,0x5A54,0x6A37,0x7A16,
25
0x0AF1,0x1AD0,0x2AB3,0x3A92,0xFD2E,0xED0F,0xDD6C,0xCD4D,0xBDAA,0xAD8B,
26
0x9DE8,0x8DC9,0x7C26,0x6C07,0x5C64,0x4C45,0x3CA2,0x2C83,0x1CE0,0x0CC1,
27
0xEF1F,0xFF3E,0xCF5D,0xDF7C,0xAF9B,0xBFBA,0x8FD9,0x9FF8,0x6E17,0x7E36,
28
0x4E55,0x5E74,0x2E93,0x3EB2,0x0ED1,0x1EF0
29
} ;
30
31
Tu8 CRC_Test (Tu32 u32_Start, Tu32 u32_End)
32
{
33
  Tu16    uiCRC       = 0;                                     //Start-CRC = 0
34
  Tu32    u32_ByteInd;                                         //aktuelles Byte zum auslesen
35
  Tu8     u8_Fehler = 0;
36
37
38
39
  for (u32_ByteInd = u32_Start; u32_ByteInd < u32_End-2; u32_ByteInd++)
40
  {
41
    uiCRC = pgm_read_word_far(Crctab + (uiCRC >> 8)) ^ ((uiCRC & 0x00ff) << 8) ^ pgm_read_byte_far(u32_ByteInd);
42
  }
43
  if (    ((uiCRC >> 8)   != pgm_read_byte_far(u32_End-2))
44
       || ((uiCRC & 0xFF) != pgm_read_byte_far(u32_End-1))
45
     )
46
    {
47
        u8_Fehler = 1;
48
    }
49
50
  return u8_Fehler;
51
}

Die Meldung bezieht sich auf die Zeile in der for-Schleife, also auf das 
pgm_read_word_far und nicht pgm_read_word_byte.

Der Bootloader und auch die CRC-Tabelle liegen im Bereich ab 0x1F000, 
das ist sicher, der Bootloader funktioniert und ich habe auch das 
hex-file kontrolliert.

von Stefan E. (sternst)


Lesenswert?

Markus schrieb:
> Der Bootloader und auch die CRC-Tabelle liegen im Bereich ab 0x1F000,
> das ist sicher, der Bootloader funktioniert

Nun, ich hätte jetzt auf den ersten Blick gesagt, dass das nicht 
funktionieren kann, weil das Argument von pgm_read_word_far nur eine 16 
Bit große Adresse ist. Tut es aber doch, aber eher zufällig, denn die 
Adresse wird vorzeichenbehaftet auf 32 Bit erweitert, und RAMPZ besteht 
ja nur aus einen Bit, so dass die ganzen anderen Einsen in den oberen 2 
Byte nicht weiter stören.

Ich würde es eher so schreiben:
1
pgm_read_word_far((uint16_t)(Crctab + (uiCRC >> 8)) + 0x10000)
Das eliminiert die Warnung und es funktioniert auch nicht mehr nur aus 
Zufall.

von Markus (Gast)


Lesenswert?

Hallo Stefan,

ja, es funktioniert so tatsächlich ohne Warnung.
Das Problem dabei ist nur, dass ich ja dann festlege, wo sich der 
Bootloader befinden muss, bei kleineren oder größeren Controllern müsste 
ich da wieder aufpassen, dass ich die Offset-Adresse ändere.
Was ist denn, wenn ich irgendetwas im normalen Programm als PROGMEM 
speichere und da eine 64k-Grenze überschreite?
Gibts ne Möglichkeit, den Crctab direkt irgendwie als 32bit Pointer zu 
bekommen, denn bei 16bit bleibt das Problem ja immer irgendwie.

Oder wie könnte man das ganze vielleicht noch anders lösen?

Vielen Dank für deine Hilfe.

von Stefan E. (sternst)


Lesenswert?

Markus schrieb:
> Gibts ne Möglichkeit, den Crctab direkt irgendwie als 32bit Pointer zu
> bekommen, denn bei 16bit bleibt das Problem ja immer irgendwie.

In reinem C nicht, höchstens über Inline-Assembler.

Markus schrieb:
> Oder wie könnte man das ganze vielleicht noch anders lösen?

Ich würde die CRC-Bildung ohne LUT implementieren. Oder inwieweit ist 
das im Bootloader zeitkritisch?

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.