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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Alexander H. (ill_son)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
1 lesenswert
nicht lesenswert
Poste das Programm so, wie du es kompiliert hast.

von Alexander H. (ill_son)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Warum ultoa? 16 Bit ist ein normaler Integer, kein Long.

von M. K. (sylaina)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Also ist die 2 von sizeof(uint16_t) bzw. sizeof(*c3) ?

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
Ja.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.