uint16_t Array im PROGMEM; erste Elemente stimmen nicht

OP #4858220
Lesenswert?

Hallo,

ich habe eine Frage zum Speichern von Arrays im Programmspeicher. Zu 
Testzwecken habe ich folgendes Array im Programmspeicher abgelegt.
1
const uint16_t c0 [8191] PROGMEM = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20, ... , 8190};

und greife wie folgt im Programm darauf zu:
1
for(uint16_t i = 0; i < 8191; i++)
2
{
3
   uart_writeln(ultoa(pgm_read_word(&(c0[i])), tmpstr, 10));
4
}

Ansonsten macht das Programm nichts weiter. Ich habe noch weitere Arrays 
derart angelegt, um den Programmspeicher zu füllen.

Ausgegeben werden die Werte wie folgt: 8187, 8188, 8189, 8190, 0, 1...
Auch bei den anderen Arrays stimmen die Elemente nicht. Woran kann das 
liegen?

Grüße, Alex
OP #4858902
Lesenswert?

Hallo,

danke für eure Antworten. Ich verwende einen ATxmega128A1. Sinn und 
Zweck der Aktion ist es, meinen Bootloader zu testen, im speziellen die 
Generierung der zu sendenden Daten aus dem Intel-HexFile, und dafür ein 
Programm zu haben, was etwas Sinnvolles macht und dabei möglichst den 
ganzen Flash belegt. Quellcode kann ich morgen früh posten.

Grüße, Alex
#4859481
Lesenswert?

Georg G. schrieb:
> Warum ultoa? 16 Bit ist ein normaler Integer, kein Long.

Ja, das könnte man fragen, ist aber gewiss nicht das Problem.

Alexander H. schrieb:
> Quellcode kann ich morgen früh posten.

Das ist sicher sinnvoll, hänge die Quellcode-Dateien einfach an den 
Beitrag an bzw. wenn du den Code in den Beitrag packst denke daran die 
entsprechenden Tags zu benutzen, sonst liest es sich recht schwer.

Der Fehler ist, dass zuerst die vier letzten Elemente kommen und dann 
beginnt die Aufzählung von vorne? Oder sind zwischen drin auch Fehler?
#4859558
Lesenswert?

Alexander H. schrieb:
> Ich verwende einen ATxmega128A1. Sinn und
> Zweck der Aktion ist es, meinen Bootloader zu testen, im speziellen die
> Generierung der zu sendenden Daten aus dem Intel-HexFile, und dafür ein
> Programm zu haben, was etwas Sinnvolles macht und dabei möglichst den
> ganzen Flash belegt.

Dir ist klar, dass pgm_read_word nur auf die unteren 64k zugreifen kann?

Lass mich raten: zum Füllen des Speichers hast du mehrere dieser Arrays 
angelegt, die alle die selbe Zahlenfolge enthalten. Und bei manchen 
(nämlich jenen, die jenseits der 64k-Grenze liegen) hast du das 
beschriebene Problem.
OP #4862435
Lesenswert?

Stefan E. schrieb:
> Dir ist klar, dass pgm_read_word nur auf die unteren 64k zugreifen kann?
>
> Lass mich raten: zum Füllen des Speichers hast du mehrere dieser Arrays
> angelegt, die alle die selbe Zahlenfolge enthalten. Und bei manchen
> (nämlich jenen, die jenseits der 64k-Grenze liegen) hast du das
> beschriebene Problem.

Du muss Hellseher sein. Also erstens, nein das war mir nicht klar und 
zweitens, ja. Ich habe mich mal an dem Link im letzten Post langehangelt 
und das hier fabriziert:
1
#define FAR(var)                     \
2
({ uint_farptr_t tmp;                \
3
  __asm__ (                         \
4
  "ldi    %A0, lo8(%1)"  "\n\t" \
5
  "ldi    %B0, hi8(%1)"  "\n\t" \
6
  "ldi    %C0, hh8(%1)"         \
7
  : "=d" (tmp)                  \
8
  : "i"  (&(var)));             \
9
  tmp;                              \
10
})
11

12
#define FAR_SECTION   __attribute__((__section__(".far_section")))
13

14
const uint16_t c0 [8192] PROGMEM = {0,1,2...
15
const uint16_t c1 [8192] PROGMEM = {0,1,2...
16
const uint16_t c2 [8192] PROGMEM = {0,1,2...
17
const uint16_t c3 [8192] FAR_SECTION = {0,1,2,...
18
const uint16_t c4 [8192] FAR_SECTION = {0,1,2,...
19
const uint16_t c5 [8192] FAR_SECTION = {0,1,2,...
20
const uint16_t c6 [8192] FAR_SECTION = {0,1,2,...
21

22
int main( void )
23
{
24
 for(uint16_t i = 0; i < 8192; i++)
25
 {
26
  uart_writeln(ultoa(pgm_read_word(c0 + i), tmpstr, 10));
27
  uart_writeln(ultoa(pgm_read_word(c1 + i), tmpstr, 10));
28
  uart_writeln(ultoa(pgm_read_word(c2 + i), tmpstr, 10));
29
  uart_writeln(ultoa(pgm_read_word_far(FAR(c3) + 2 * i), tmpstr, 10));
30
  uart_writeln(ultoa(pgm_read_word_far(FAR(c4) + 2 * i), tmpstr, 10));
31
  uart_writeln(ultoa(pgm_read_word_far(FAR(c5) + 2 * i), tmpstr, 10));
32
  uart_writeln(ultoa(pgm_read_word_far(FAR(c6) + 2 * i), tmpstr, 10));
33
 }
34

35
 while(1);
36
}

Das macht zumindest erst einmal das, was ich erwarte. Warum dazu bei 
FAR_SECTION ein 2*i notwendig ist, habe ich allerdings noch nicht ganz 
verstanden.

Grüße, Alex

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