Forum: Mikrocontroller und Digitale Elektronik Ein Array vom Ram ins Flash bringen


von Tobias B. (horschtx)


Lesenswert?

Hallo,
habe mal wieder ein Problemchen...

Ich möchte gerne ein paar größere Daten Arrays ins Flash bekommen. Das 
möchte aber nicht so ganz klappen.

Die Routinen die ich bisher habe sehen so aus.

Eines der Arrays:
1
uint8_t DM1_DATA_Data_IC_1[DM1_DATA_SIZE_IC_1] = {
2
0x00, 0xFF, 0x86, 0xCB, 
3
0xFE, 0x00, 0xF2, 0x6B, 
4
0x00, 0xFF, 0x86, 0xCB,  
5
0x00, 0x00, 0x00, 0x00, 
6
0x00, 0x00, 0x00, 0x00, 
7
0x00, 0x00, 0x00, 0x00, 
8
};

Der Prototyp:
1
void Sigma_block_write(uint8_t,uint16_t,uint16_t,uint8_t[]);

Der Aufruf:
1
Sigma_block_write( DEVICE_ADDR_IC_1, PARAM_ADDR_IC_1, PARAM_SIZE_IC_1, Param_Data_IC_1 );

Die Funktion:
1
void Sigma_block_write(uint8_t chip,uint16_t adresse,uint16_t length, uint8_t Data[])
2
{
3
    PORTE.OUTCLR = PIN4_bm;  
4
    SPIE.DATA = chip;
5
    while(!(SPIE.STATUS & SPI_IF_bm))
6
    dummy = SPIE.DATA;
7
    SPIE.DATA = adresse>>8;
8
    while(!(SPIE.STATUS & SPI_IF_bm))
9
    dummy = SPIE.DATA;
10
    SPIE.DATA = adresse & 0xFF;
11
    while(!(SPIE.STATUS & SPI_IF_bm))
12
    dummy = SPIE.DATA;
13
    for(uint16_t z=0;z<length;z++)
14
      {
15
        SPIE.DATA = Data[z];
16
        while(!(SPIE.STATUS & SPI_IF_bm))
17
        dummy = SPIE.DATA;
18
      }
19
    PORTE.OUTSET = PIN4_bm;  
20
    _delay_us(500);
21
}

Ich habe mal versucht die daten mittels
1
const uint8_t DM1_DATA_Data_IC_1[DM1_DATA_SIZE_IC_1] PROGMEM = {
2
0x00, 0xFF, 0x86, 0xCB, 
3
0xFE, 0x00, 0xF2, 0x6B, 
4
0x00, 0xFF, 0x86, 0xCB,  
5
0x00, 0x00, 0x00, 0x00, 
6
0x00, 0x00, 0x00, 0x00, 
7
0x00, 0x00, 0x00, 0x00, 
8
};
ins Flash zu schieben... habe noch den Aufruf abgeändert.
Es konnte ohne Fehler Compiliert werden doch wurden falsche Daten 
geschickt.
Irgendwie habe ich da ein Denkfehler.
Vielleicht kann mir jemand weiterhelfen und es an einem Beispiel zeigen.

Vielen Dank.
Gruß Tobias

: Bearbeitet durch Moderator
von Karl H. (kbuchegg)


Lesenswert?

Tobias B. schrieb:

> ins Flash zu schieben... habe noch den Aufruf abgeändert.

Wenn du mit PROGMEM arbeitest, reicht das nicht.
Dann müssen auch alle Zugriffe auf die Daten auf die Verwendung von 
pgm_readxxx umgestellt werden.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Flash_mit_PROGMEM_und_pgm_read

von Tobias B. (horschtx)


Lesenswert?

Hallo,

danke erstmal für die schnelle Antwort.

Ja das habe ich schon geändert. Aber es will nicht funktionieren.

Hier ist mal der Code wie ich es aktuell versucht habe:

Das Array:
1
const uint8_t DM1_DATA_Data_IC_1[DM1_DATA_SIZE_IC_1] PROGMEM = {
2
0x00, 0xFF, 0x86, 0xCB, 
3
0xFE, 0x00, 0xF2, 0x6B, 
4
0x00, 0xFF, 0x86, 0xCB,  
5
0x00, 0x00, 0x00, 0x00, 
6
0x00, 0x00, 0x00, 0x00, 
7
0x00, 0x00, 0x00, 0x00,  
8
};

Der Prototyp:
1
void Sigma_block_write(uint8_t,uint16_t,uint16_t,const uint8_t[]);

Der Aufruf:
1
Sigma_block_write( DEVICE_ADDR_IC_1, DM1_DATA_ADDR_IC_1, DM1_DATA_SIZE_IC_1, DM1_DATA_Data_IC_1 );


Die Funktion:
1
void Sigma_block_write(uint8_t chip,uint16_t adresse,uint16_t length, const uint8_t Data[])
2
{
3
    PORTE.OUTCLR = PIN4_bm;  
4
    SPIE.DATA = chip;
5
    while(!(SPIE.STATUS & SPI_IF_bm))
6
    dummy = SPIE.DATA;
7
    SPIE.DATA = adresse>>8;
8
    while(!(SPIE.STATUS & SPI_IF_bm))
9
    dummy = SPIE.DATA;
10
    SPIE.DATA = adresse & 0xFF;
11
    while(!(SPIE.STATUS & SPI_IF_bm))
12
    dummy = SPIE.DATA;
13
    for(uint16_t z=0;z<length;z++)
14
      {
15
        SPIE.DATA = pgm_read_byte (Data[z]);
16
        while(!(SPIE.STATUS & SPI_IF_bm))
17
        dummy = SPIE.DATA;
18
      }
19
    PORTE.OUTSET = PIN4_bm;  
20
    _delay_us(500);
21
}

So bekomme ich aber falsche Daten. Habe da wohl noch ein Denkfehler 
drin...

von Falk B. (falk)


Lesenswert?

@ Tobias B. (horschtx)

>        SPIE.DATA = pgm_read_byte (Data[z]);

Falsch. Eher so
1
        SPIE.DATA = pgm_read_byte (&Data[z]);


Jaja, Arrays und Pointer sind bei C ein wenig verwirrend ;-)

von Tobias B. (horschtx)


Lesenswert?

Ohhh Danke :)

Man man man... so ein blödes &

Da fehlt mir einfach noch die erfahrung und routine dafür

von Falk B. (falk)


Lesenswert?

erfahrung & routine

;-)

von traini (Gast)


Lesenswert?

Um welchen Controller gehts denn überhaupt?

von Falk B. (falk)


Lesenswert?

AVR

von traini (Gast)


Lesenswert?

Falk Brunner schrieb:
> AVR

Ach der, der soll ja ganz gut sein, hab ich gehört.

von Tobias B. (horschtx)


Lesenswert?

traini schrieb:
> Um welchen Controller gehts denn überhaupt?

Wer es genau Wissen möchte, es ist ein Atmel Xmega 128A1

von Karlo (Gast)


Lesenswert?

Nimm _flash anstatt PROGMEM dann klappt alles out-of-the-box.
Musst auch deinen restlichen Code nicht modifizieren.

von Ernie (Gast)


Lesenswert?

Karlo schrieb:
> Nimm _flash anstatt PROGMEM dann klappt alles out-of-the-box.
> Musst auch deinen restlichen Code nicht modifizieren.

Gibt es einen fertigen Beispielcode, wie man Daten ins Flash schreiben 
kann, in diesem Thread werden immer nur Andeutungen gemacht.

von Karl H. (kbuchegg)


Lesenswert?

?

Weiter oben hab ich einen Link ins Tutorial gepostet. Da drehen sich 
mindestens 5 Bildschirmseiten nur um dieses Thema. In allen Variationen.

von Ernie (Gast)


Lesenswert?

Karl Heinz schrieb:
> Weiter oben hab ich einen Link ins Tutorial gepostet. Da drehen sich
> mindestens 5 Bildschirmseiten nur um dieses Thema. In allen Variationen.

Da geht es immer nur darum, wie man Daten aus dem Flash liest, nicht wie 
man Daten zur Laufzeit in den Flash schreibt.

von Karl H. (kbuchegg)


Lesenswert?

Ernie schrieb:
> Karl Heinz schrieb:
>> Weiter oben hab ich einen Link ins Tutorial gepostet. Da drehen sich
>> mindestens 5 Bildschirmseiten nur um dieses Thema. In allen Variationen.
>
> Da geht es immer nur darum, wie man Daten aus dem Flash liest, nicht wie
> man Daten zur Laufzeit in den Flash schreibt.

Äh.
Ausser in einem Bootloader - gar nicht.
Das ist ja der ganze Witz an der Harvard Architektur.

: Bearbeitet durch User
von traini (Gast)


Lesenswert?

Karl Heinz schrieb:
> Äh.
> Ausser in einem Bootloader - gar nicht.
> Das ist ja der ganze Witz an der Harvard Architektur.

Welchen Teil von "Ein Array vom RAM ins Flash bringen" hab ich dann 
nicht verstanden?

von Karl H. (kbuchegg)


Lesenswert?

traini schrieb:
> Karl Heinz schrieb:
>> Äh.
>> Ausser in einem Bootloader - gar nicht.
>> Das ist ja der ganze Witz an der Harvard Architektur.
>
> Welchen Teil von "Ein Array vom RAM ins Flash bringen" hab ich dann
> nicht verstanden?

Dass es darum geht, ein konstantes Array mit konstanten Werten so 
anzulegen, dass es nicht im RAM liegt, sondern vom Compiler im Flash 
angelegt wird.
Von 'zur Laufzeit den Arrayinhalt ändern' ist da nicht die Rede. Der 
Inhalt des Arrays ist zur Laufzeit fix und wird nicht geändert.

: Bearbeitet durch User
von traini (Gast)


Lesenswert?

Gibt es dann eine Funktion, die im Bootloader-Bereich platziert wird, 
und Daten zur Laufzeit in den Flash schreiben kann? Es gibt ja auch 
AVRs, die keinen speziellen Bootloader-Bereich haben, da könnte diese 
Funktion ja eigentlich überall stehen?

von Dennis R. (dennis_r93)


Lesenswert?

Ich weiß von den stm32f4 Chips, dass der Flash in Blöcken zur Laufzeit 
gelöscht und beschrieben werden kann

Ob das die avrs unterstützen musst du im Datenblatt nachlesen

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

traini schrieb:
> Gibt es dann eine Funktion, die im Bootloader-Bereich platziert wird,
> und Daten zur Laufzeit in den Flash schreiben kann? Es gibt ja auch
> AVRs, die keinen speziellen Bootloader-Bereich haben, da könnte diese
> Funktion ja eigentlich überall stehen?

Was genau ist eigentlich das Problem?
AVR sind so ausgelegt, dass
* im Flash das Programms steht (also alles was sich zur Laufzeit nicht 
ändert)
* es ein SRAM für Variablen gibt
* alles was eine Stromabschaltung überleben muss, im EEPROM gespeichert 
wird

AVR gibt es in verschiedenen Ausbaustufen, mit unterschiedlichen Größen 
von Flash, SRAM und EEPROM. Wenn das nicht reicht, kann man für 
Massendaten noch eine SD-Karte anschliessen oder bei manchen auch 
externen Speicher.
Aber eines macht man normalerweise nicht: den Flash über Umwege zum 
Speichern von Werten zu benutzen. Wenn das Speicherangebot nicht reicht, 
dann benutzt du ganz einfach den falschen Prozessor. Dafür sind die AVR 
nicht ausgelegt.

Ja, man könnte den Bootloader Modus ausnutzen. Allerdings ist das mühsam 
und Geschwindigkeitsrekord wirst du damit auch keinen brechen.

: Bearbeitet durch User
von isidor (Gast)


Lesenswert?

Dennis R. schrieb:
> Ich weiß von den stm32f4 Chips, dass der Flash in Blöcken zur Laufzeit
> gelöscht und beschrieben werden kann
>
> Ob das die avrs unterstützen musst du im Datenblatt nachlesen

Sollte bei den AVRs eigentlich funktionieren, denn Bootloader ist
ja auch "Laufzeit". Nur - wie du bereits erwähnst - wird das nur
eingeschränkt möglich sein da Flash Speicher immer Page-weise
gelöscht wird. Also müsste ein Array innerhalb einer oder mehrerer
Flash Pages zu liegen kommen und nichts anderes. Nicht sehr
praktikabel .....

von traini (Gast)


Lesenswert?

Karl Heinz schrieb:
> AVR gibt es in verschiedenen Ausbaustufen, mit unterschiedlichen Größen
> von Flash, SRAM und EEPROM.

Der EEprom ist im Vergleich zum Flash relativ klein, wenn man mehr Daten 
ablegen will muß man ja nicht gleich einen externen EEprom verwenden.

Würde mich wundern, wenn es noch nie jemand versucht hat, Daten im Flash 
abzulegen.

Im schlimmsten Fall, muß man einen Bootloader umfunktionieren.

von S. R. (svenska)


Lesenswert?

traini schrieb:
> Würde mich wundern, wenn es noch nie jemand versucht hat, Daten im Flash
> abzulegen.
Da gibt es bestimmt jemanden. Aber da die Idee, das zur Laufzeit zu 
machen - von ganz bestimmten Sonderfällen mal abgesehen - schlicht dumm 
ist, sind das sicherlich nicht genug.

Die AVRs sind da schlicht das falsche Pferd. Auf dem STM32 gibt es eine 
EEPROM-Emulations-Bibliothek, die den Flash benutzt. Nimm einfach das 
richtige Werkzeug für dein Problem.

: Bearbeitet durch User
von traini (Gast)


Lesenswert?

S. R. schrieb:
> Da gibt es bestimmt jemanden. Aber da die Idee, das zur Laufzeit zu
> machen - von ganz bestimmten Sonderfällen mal abgesehen - schlicht dumm
> ist, sind das sicherlich nicht genug.

Der Flash scheint etwas weniger störanfällig als der EEPROM zu sein, man 
könnte also z.B. Kalibrierdaten im Flash ablegen.

von Oliver J. (skriptkiddy)


Lesenswert?

Mal als Ergänzung:
1
/* Locate array[] in flash memory */
2
const __flash int array[] = { 3, 5, 7, 11, 13, 17, 19 };
3
     
4
int i = 1;
5
6
int main (void)
7
{
8
   /* Return 17 by reading from flash memory */
9
   return array[array[i]];
10
}
Quelle: https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html

Grüße Oliver

von S. R. (svenska)


Lesenswert?

Ja, aber das geht nicht zur Laufzeit (was der TO wollte).
Schöne Grüße übrigens. ;-)

von Oliver J. (skriptkiddy)


Lesenswert?

S. R. schrieb:
> Ja, aber das geht nicht zur Laufzeit (was der TO wollte).
> Schöne Grüße übrigens. ;-)

Hab ich ja auch nicht behauptet alter Schwede :) Wollten nur auf das 
"neue" Feature des arv-gcc aufmerksam machen. Damit kann man sich das 
abartige pgm_read*** sparen und der Code wird dadurch überichtilicher. 
Gerade bei im flash abgelegten Strukturen und solchen Sachen. Durfte ich 
gerade selbst bei nem Projekt feststellen.

Grüße vom Chiemsee

von Andreas (Gast)


Lesenswert?

Nagelt mich nicht fest, aber ich meine mich zu erinnern, dass das 
Flash-Schreiben bei einigen AVRs direkt aus dem Programm ging, bei dem 
Rest muss es im Bootloader passieren.

Mal abgesehen von dem erhöhtem Flash-Verschleiß ist es auch nicht ganz 
trivial und es ergeben sich ein paar Probleme:
- Die Adresse der Schreibfunktion im Bootloader muß fest und bekannt 
sein, damit man dahin springen kann. Und dann muss man auch noch zurück 
;-)
- Die Adresse der Daten im Flash darf nicht mit dem Programm und 
Booloader kollidieren. Es ist mindestens eine Flashseite groß.
- Man kann die Bytes nicht einzeln speichern, sondern immer alles - 
soviel RAM muss erstmal frei sein.
- const __flash ...{1,2,3..} klappt damit trotzdem nicht

Ich glaube es ist einfacher einen Externen SPI Flash oder EEPROM zu 
benutzen.

von Pete K. (pete77)


Lesenswert?

Wenn der Flash nicht zuverlässig ist, tut es vielleicht externes FRAM.

von Peter D. (peda)


Lesenswert?

S. R. schrieb:
> Da gibt es bestimmt jemanden. Aber da die Idee, das zur Laufzeit zu
> machen - von ganz bestimmten Sonderfällen mal abgesehen - schlicht dumm
> ist, sind das sicherlich nicht genug.

Das geht prima und ist überhaupt nicht dumm.
Manchmal muß man eben mehr Daten volatile speichern, als der EEPROM 
fassen kann.
In meinem Bootloader ist dazu eine Funktion, die in C aufgerufen werden 
kann.

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.