Forum: Mikrocontroller und Digitale Elektronik uint16_t Array im PROGMEM; erste Elemente stimmen nicht


von Alexander H. (ill_son)


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

von M. K. (sylaina)


Lesenswert?

Alexander H. schrieb:
> 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?

Welcher AVR ist denn in Gebrauch? Ist dir klar, dass dein Array alleine 
16382 Byte Flash brauchen würden?
Warum willst du den Flash-Speicher eigentlich füllen? Was ist Sinn und 
Zweck der Aktion?

von Werther (Gast)


Lesenswert?

Poste das Programm so, wie du es kompiliert hast.

von Alexander H. (ill_son)


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

von Georg G. (df2au)


Lesenswert?

Warum ultoa? 16 Bit ist ein normaler Integer, kein Long.

von M. K. (sylaina)


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?

von Stefan E. (sternst)


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.

von Joachim B. (jar)


Lesenswert?

Stefan E. schrieb:
> Dir ist klar, dass pgm_read_word nur auf die unteren 64k zugreifen kann?

guter Einwand

pgm_read_word_far() sollte helfen?

aber dann konsequent für alles nicht das ein Mischmasch entsteht.

geklaut aus:
Beitrag "Frage: Atmega >64k, PROGMEM und Pointer, AVR Studio 6"

ich bin selbst beim 2560 mal reingefallen, habe den aber lange nicht 
mehr angesehen.

von Alexander H. (ill_son)


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

: Bearbeitet durch User
von Stefan E. (sternst)


Lesenswert?

Alexander H. schrieb:
> Warum dazu bei
> FAR_SECTION ein 2*i notwendig ist, habe ich allerdings noch nicht ganz
> verstanden.

Weil das Array 16-Bit-Elemente enthält. Das FAR() ist ja nicht wirklich 
ein Pointer, sondern nur die Adresse in Form einer Zahl. Es kommt also 
nicht die Pointer-Arithmetik zum tragen.

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Also ist die 2 von sizeof(uint16_t) bzw. sizeof(*c3) ?

von Falk B. (falk)


Lesenswert?

Ja.

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.