Forum: Mikrocontroller und Digitale Elektronik PIC32 Daten im Flash ablegen


von Stephan Storm (Gast)


Lesenswert?

Hallo zusammen,

ich arbeite an einem Projekt mit einem PIC32. Nun sollte ich Information 
zur Konfiguration der Software im Flash des PIC ablegen. Leider komme 
ich nicht weiter. Wichtig: Das Projekt muss in C programmiert werden 
(mir is Assembler zwar lieber, ist aber nicht erlaubt, fragt mich nicht 
warum!).

Ich habe bereits funktionen in der P-Lib von Microchip gefunden. 
NVMProgram wäre nicht schlecht, allerdings blick ich mit diesem 
Memory-Mapping nicht durch. Wo schreibe ich denn meine Daten hin und wo 
(wie) lese ich sie wieder aus. Wäre schön wenn ihr mir helfen könntet.

Stephan

von Stephan Storm (Gast)


Lesenswert?

So Hallo,

also trotz der wenigen Antworten bin ich bezüglich Memory-Mapping so 
weit, dass ich weiß wohin gemappt wird. Fragt mich nicht wie man das 
Konfiguriert aber es läuft so. Also zunächst addressiert man immer 
Virtual. Der von allen verwendete Speicherbereich zum Speichern 
wichtiger Informationen beginnt bei 0x1D000000 (physical) und entspricht 
0xBD000000 (virtual).

Das Speichern eines Words habe ich auch hinbekommen. Ich nutze die 
Funktion NVMWriteWord aus dem PIC32 Family Datasheet. Problem. Ich kann 
nur einmal schreiben. Dann erst wieder nach einem Reset. Ich habe in 
verschiedenen Foren, bzw. implizit im Datenblatt gelesen, dass der 
Speicher vor dem schreiben gelöscht werden muss. Das ist 
nachzuvollziehen, da beim Schreiben ein AND mit den Daten im Speicher 
gemacht wird. Das hatte bei meinem Programm folgende Konsequenzen:

zu schreiben (0x34333231)
im Speicher vorher (0x31323334)
im Speicher nachher (0x30323230)

ich habe nun versucht zunächst die Flash Page zu löschen und dann zu 
schreiben. Dass hat aber zur Konsequenz dass:

1.) Bei Adresse 0x1D009000 immer ein 0xXXXXXX01 Word steht (XXXXXX sind 
die Daten zuvor.

2.) Die Daten nicht gelöscht werden.

3.) Beim Speichern immer noch das beschriebene AND gemacht wird.


Kurioserweise wird nicht Mal ein Fehlerflag gesetzt oder Ähnliches. Auch 
die beiden Config Bits die Schuld sein könnten (CP ^= Code Protect und 
PWP ^= Program Memory Write Protect) stehen beide auf OFF.

Ich weiss nicht mehr weiter. Ich nutze nur Funktionen aus der PLib oder 
dem PIC32 Datenblatt (Copy/Paste) aber es funktioniert nicht.

Sind diese 01 bei 0x1D009000 und in 128 Byte Abständen irgendwelche 
Schreibschutz bits?

Weiß jemand Rat, ich habe ihn bitter nötig!
Vielen Dank im voraus
Stephan

von thomas (Gast)


Lesenswert?

hi,

in welchen Schritten adressierst du den Flash? Adress step size ist 
nämlich 0x4.

post mal bitte deinen quelltext, bei mir gehts nämlich einwandfrei.

ich habe gemerkt, dass die memory view funktion irgendwie nicht geht, 
die daten sind aber auf jeden fall einprogrammiert, da ich diese über 
I2C auslesen kann.

gruß

von Stephan Storm (Gast)


Lesenswert?

Hallo,

danke Thomas. Die Schrittweite habe ich beachtet.

Zum Problem: Es ist gelöst. Also zunächst, die NVM-Funktionen aus der 
PLib funktionieren einwandfrei (sofern man weiß, was für Einschränkungen 
sie unterliegen). So kann man z.B. mit NVMWriteWord() ein Word also 32 
Bit durchaus schreiben. Jedoch nur ein Mal. Die dem Word zugehörige Row 
des Speichers kann dann nicht mehr gelöscht werden. (Erst nach einem 
Reset). Damit man die Pages löschen kann müssen immer komplette Rows 
geschrieben werden. Verwendet man also stets NVMWriteRow() und 
NVMErasePage() und puffert die Daten temporär so ist man auf der 
sicheren Seite. Schade das Micro(shit)chip nicht in der Lage ist, das 
vernünftig zu dokumentieren.

Das ist meine Funktion die einwandfreie Ergebnisse liefert:

unsigned int NVMWriteWordEx(void* address, unsigned int data)
{
  unsigned int buffer[1024];
  int i,res;
  unsigned int page_address = ((unsigned int)address-((unsigned 
int)address%1024));
  unsigned int page_offset = ((unsigned int)address%1024)/4;
  for(i=0;i<1024;i++)
  {
    buffer[i] = *((unsigned int*)(page_address+(i*4)));
  }

  buffer[page_offset] = data;

  res = NVMErasePage((void*)page_address);
        if(res!=0) return res;

  for(i=0;i<8;i++)
  {
    res = NVMWriteRow((void*)(page_address+(i*128)), 
(void*)(buffer+(i*128)));
    // Return Result
    if(res!=0) return res;
  }
}

Die Berechnung von page_address kann man sich theoretisch auch sparen. 
Ich habe es zur sicherheit mal implementiert.

Was die Memory-View Funktion von MPLAB angeht: Im wesentlichen 
funktioniert das bei mir. (ICD2). Manchmal verabschiedet sich zwar das 
Debug-Tool in die ewigen Abgründe des Arbeitsspeichers aber nach 
mehrmaligem probieren funktionierts.

OK, ich denke damit ist das Thema abgeschlossen. Falls jemand Probleme 
ähnlicher Art hat stehe ich gerne per E-Mail zur Verfügung: 
stephan.storm@rebbergnet.de

Tschüss und Ade!
Stephan

von Nicola (Gast)


Lesenswert?

Hallo Stephan, habe genau das selbe Problem, welches du zu Beginn 
beschrieben hast. Habe dann auch die zuletzt gepostete Funktion kopiert, 
und bei mir eingesetzt. Allerdings Funktioniert das beschreiben des 
Flashs bei mir nicht wirklich. Für adress habe ich 0xBD000000 
eingesetzt.
Eigentlich weiss ich gar nicht wirklich ob es nun im Flash abgespeichert 
wird oder nicht, da ich den Befehl zum auslesen nicht kenne.

Darum meine wichtigste Frage: WIE KANN ICH DEN GESPEICHERTEN WERT WIEDER 
AUS DEM FLASH-SPEICHER AUSLESEN??

bin schon einige Zeit dran, steh aber voll auf dem schlauch, wäre toll 
wenn du mir weiterhelfen könntest.

von Al (Gast)


Lesenswert?

UINT32 Adress = 0x9D000000; // virtuelle adresse!!!!!!!!!!!!!!

UINT32 Val = (*(UINT32*)(Adress));

von Nicola (Gast)


Lesenswert?

Danke für die Antwort, aber könntest du mir noch erklären was mir dieser 
Code jetzt bringen soll?

Bin (noch) nicht sehr C erfahren und habe deshalb mühe das ohne 
erklärung anzuwenden.

von Nicola (Gast)


Lesenswert?

Am meisten würde mir ein funktionierender helfen, mit dessen Hilfe ich 
Daten vom laufenden Programm aus ins Flash programmieren, und später 
wieder auslesen kann.

Vielen dankt nochmals im Vorraus und sorry für die Belästigung, aber 
sonst ist im Netz wirklich nicht gerade viel Brauchbares über das Thema 
zu finden.

von Al (Gast)


Lesenswert?

>..könntest du mir noch erklären was mir dieser Code jetzt bringen soll?
Mit dem Pic32 kann man direkt über Zeiger ohne besondere 
Funktionenaufruf (wie bei Pic24) das Flash lesen:
1
//Zeiger auf eine 32Bit VIRTUELLE Adresse, bei absoluten Adressen bekommst du einen Fehler
2
UINT32 Adress = 0x9D000000; 
3
//Wert der Adresse lesen
4
UINT32 Val = (*((UINT32*)(Adress)));

Beim Flash Schreiben musst du IMMER vorher eine ganze Page(0x1000 Bytes) 
löschen, dann mit den NVMWrite-Funktionen schreiben (word oder row)

Ein sehr gutes Beispiel dafür ist der USB-BootLoader von microchip (von 
der homepage runterladen), die Funktionen kannst du sicher 1/1 
übernehmen.

von Nicola (Gast)


Lesenswert?

Vielen Dank erstmal für die tolle Erklärung. Auslesen des Speichers 
funktioniert nun einwandfrei! Hätte nicht gedacht das das so einfach 
geht...

Welchen USB-Bootloader von Microchip meinst du?

Habe immer noch die Funktion von Stephan implementiert, aber den 
Speicherwerwert kann ich noch nicht ändern. Warum, versuche ich nun noch 
rauszufinden.

von Al (Gast)


Lesenswert?

auf der Microchip Seite / Pic32 oder USB Teil findest du viele 
Beispiele, auch von dem Bootloader für die Pic32 Reihe.

USB Framework for PIC18, PIC24 & PIC32:
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2680&dDocName=en537044

von Nicola (Gast)


Lesenswert?

Ok danke. Das file habe ich heruntergeladen und das Projekt "Mass 
Storage Bootloader C32" geöffnet. Die Funktion, um ins Flash zu 
schreiben kann ich allerdings nicht finden..

Aber funktioniert denn der oben von Stephan gepostete Code nicht? Muss 
man bei seinem Code noch die NVMCON Register setzen damit er 
funktioniert? Ich versteh einfach nicht, worin mein Fehler liegt...

von heinzhorst (Gast)


Lesenswert?

Warum so kompliziert? Ich mache das auf dem PIC32 mit der Data EEPROM 
Emulation Library von Microchip:

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2680&dDocName=en538000

Ist eine fertige Rundum-Glücklich-Lösung und hat die selbe Syntax, wie 
die Funktionen, mit denen du ein einen "echten" EEPROM im PIC 
beschreibst.

von Nicola (Gast)


Lesenswert?

WOW ja der Beschreibung nach sollte das ja wirklich funktionieren...wäre 
ja toll.

Ich habe das jetzt mal heruntergeladen (DEE Emulation 16-bit), darin 
wird jedoch der 32MX PIC ja gar nicht aufgeführt... wird der trotzdem 
unterstützt, also kann ich die Funktionen einfach so verwenden oder muss 
etwas angepasst werden?

von heinzhorst (Gast)


Lesenswert?

Nein, da muss nichts angepasst werden. Das macht der Präpozessor beim 
Compillieren von alleine. Ich benutze das auf einem PIC32MX795.

von Nicola (Gast)


Lesenswert?

ok, ich benutze den PIC32MX440F512H, habe das .c, .h und .s file meinem 
Programm hinzugefügt und erhalte beim kompilieren hunderte Fehler wie 
unter anderem:

DEE Emulation 16-bit.h:104: error: conflicting types for 'DATA_EE_FLAGS'

oder

DEE Emulation 16-bit.c:100: warning: `space' attribute directive ignored

Keine ahnung aber langsam glaube ich ich bin einfach zu blöd dafür..

von Nicola (Gast)


Lesenswert?

Hallo Leute,

und schon wieder ist ein Arbeitstag ins Land gezogen, ohne dass wirklich 
ein Fortschritt bei meinem Projekt passiert ist.
Ich habe heute Alles. was mit dem Aeschreiben meines Flashs zu tun hat, 
nochmals aus dem Programm gelöscht und neu imolementiert. Alles schön 
nach Datenblatt wie ich meine...aber es funktioniert einfach nicht.

Ich bitte deshalb darum, dass Jemand der einen funktionierenden C-Code 
besitzt diesen doch bitte hier posten könnte (mit Funktionsaufruf und 
allem was dazu gehört / was man sonst noch falsch machen könnte). Dafür 
wäre ich euch wirklich sehr dankbar!

Ansonsten bleibt mir nur noch die möglichkeit, ein externes EEPROM 
nachträglich auf den extern gefertigten Print zu fädeln -.-

Vielen Dank im Voraus
Nicola

von Al (Gast)


Lesenswert?

Na, hättest du das Beispiel von USB-Bootloader für PIC32 genommen, 
hättest du jetzt keine Probleme mehr!

von Nicola (Gast)


Lesenswert?

Al schrieb:
> Na, hättest du das Beispiel von USB-Bootloader für PIC32 genommen,
> hättest du jetzt keine Probleme mehr!

Hab ich mir ja angeschaut aber in der .zip datei die ich heruntergeladen 
habe, hat es sehr viele files. Köntest du bitte den codeteil nennen, den 
du meins oder zumindest den namen des files damit ich weiss, wo ich 
suchen muss? Sollte das problem wirklich schnellstmöglich lösen...oder 
besser gesagt: ich sollte es schon gelöst haben :-S

Gruss

von Al (Gast)


Angehängte Dateien:

Lesenswert?

hier ist ein Muster:
- Prüfe vor dem Schreiben ob die Page schon gelöscht ist oder nicht
- Schreibe im Flash Wortweise (du kannst es dann anpassen)

Gruß

von Nicola (Gast)


Lesenswert?

Vielen dank für die Mühe A1, jetzt habe ich doch noch die Hoffnung, es 
heute noch hin zu kriegen.

Hab den Code jetzt bei mir eingebunden, allerdings Funktionieren die 
Befehle "IntHex32Packet.dataLen" und "IntHex32Packet.baseAddress" nicht. 
Ich kenne die Befehle erlich gesagt auch nicht, kannst du mir sagen wie 
ich den Fehler beheben kann?

gruss

von heinzhorst (Gast)


Lesenswert?

So, nochmal zur EEPROM Emumation Library. Ich benutze das, um beim 
Microchip TCPIP Stack die Netzwerkkonfiguration in einem nichtflüchtigen 
Speicher abzulegen. Bei mir sieht das so aus:

Konfiguration wird beim Booten gelesen:
1
#include "dee_emulation_pic32.h"
2
3
// EEPROM mapping
4
5
#define EEPADR_APPCONF  0
6
7
// initialisierung
8
DataEEInit();
9
10
// Konfiguration aus EEPROM in RAM kopieren
11
DataEEReadArray(&AppConfig, EEPADR_APPCONF, sizeof(AppConfig));

oder zum Wegspeichern:
1
// Konfiguration aus RAM in EEPROM kopieren
2
DataEEWriteArray(&AppConfig, EEPADR_APPCONF, sizeof(AppConfig));
3
4
PackEE();

von Günther (Gast)


Lesenswert?

ojeeeeeeeeeee Nicola!
du kannst wohl nicht programmiern!!

Das wird natürlich nicht auf Anhieb funktionieren, es war nur ein Teil 
von meinem Bootloader.

Für das Prüfen/Löschen der Pages und Flash-Schrieben reichts es aber.

Du musst es jetzt zu deiner Applikation anpassen:
("IntHex32Packet ist eine Sturktur wo ich die Daten zum schreiben 
speichere")

du musst dann deine Daten holen und in WriteToFlash() ersetzen.

was ist überhaupt deine Aufgabe?
Was willst im Flash schrieben? große Menge Daten? nur eine ID oder ein 
Int??

von Nicola (Gast)


Lesenswert?

Es geht darum, verschiedene Prüfprogramme abzuspeichern. Würde mir aber 
reichen, wenn ich z.B. 0xFFFFFFFF abspeichern könnte, dann wüsste ich 
wieder, wie ich weitermachen muss.

Und nein, ich kann wirklich noch nicht so gut programmieren, lerne aber 
laufend dazu...hoffe ich

Gruss

von Günther (Gast)


Lesenswert?

dann definiere dir einen extra Speicherbereich dafür, feste Flash 
Adressen, wichtig ist:
- Da du nur ganze Pages löschen kannst, muss das ganze in pages 
aufgeteilt sein
1- Der Compiler darf in diesem Bereich nichts schreiben, also hier wird 
es noch komplezierter: Der Linker musst anpassen werden
2- Linker anpassen: im Linker script:
1
kseg0_program_mem    (rx)  : ORIGIN = 0x9D000000, LENGTH = 0x40000 /* Main */ 
2
// ändern auf zum Beispiel
3
kseg0_program_mem    (rx)  : ORIGIN = 0x9D000000, LENGTH = 0x40000-0x1000 /* Main */
jetzt hast du die letzte page nur für deine Daten.

Was sind verschiedene Prüfprogramme?, werden dann gestartet?

von Nicola (Gast)


Lesenswert?

Prüfprogramme ist ein wenig übertrieben...es handelt sich um daten wie 
Artikelnummer, Zielwert, Toleranz usw. also um einen Struct eigentlich.

Naja ich schaus mir am Wochenende nochmals an...komm nicht ganz draus 
was in dem Beispielprogramm von heute morgen genau passiert..hatte heute 
aber auch keine zeit, daran zu arbeiten...

Wenn noch jemand einen Funktionierenden Code für mich hat, bei dem am 
bessten nur Adresse und Daten eingegeben werden müssen, bitte Posten!

Allen noch schönes Wo.Ende!

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.