Die integrierten Funktionen des Compilers können nicht verwendet werden, um in das dsPIC-EEPROM zu schreiben

Wie ich hier erwähnt habe , habe ich Probleme mit EEPROM auf dsPIC30F6012A . Da meine alte EEPROM-Bibliothek schwierig zu analysieren und zu unterstützen war, ging ich zurück zum Anfang und schrieb sie mit den neuen (neuer als meine Bibliothek!) C30-Compiler-integrierten EEPROM-Routinen neu. Ich habe den Microchip-Democode genommen und versucht, ihn auszuführen. Kompiliert, programmiert, keine Probleme, aber es schien nicht richtig zu funktionieren. Ich habe eine modifizierte Version ihrer Demo gemacht, ebenfalls ohne Erfolg.

Ich starte dieses Programm, lese den Inhalt des Chips zurück in MPLAB X und schaue mir den Inhalt des EEPROM an. Löschvorgänge funktionieren korrekt, alle Adressen, die ich lösche, werden als 0xFFFF zurückgegeben. Aber die Schreiboperationen tun nichts. Ich habe mehrere Kombinationen ausprobiert, wiederholte Schreibvorgänge, verschiedene Adressen, nichts scheint geschrieben zu sein.

#include <p30fxxxx.h>
#include <libpic30.h>

 _FOSC(CSW_FSCM_OFF & FRC_PLL16); 
_FWDT(WDT_OFF);                 /* Turn off the Watch-Dog Timer.  */
_FBORPOR(MCLR_EN & PWRT_OFF);   /* Enable MCLR reset pin and turn off the power-up timers. */
_FGS(CODE_PROT_OFF);            /* Disable Code Protection */

 typedef struct _eestruct {
    unsigned char testdata[10];
} eestruct;
 eestruct eedata __attribute__((space(eedata)));
 eestruct backup_eedata __attribute__((space(eedata)));

 int main(){

    _prog_addressT EE_addr;
    //_init_prog_address(EE_addr, eedata);
    EE_addr = 0x7FF000;

    int temp_word = 0x0102;
    _erase_eedata(EE_addr, _EE_WORD);
    _wait_eedata();
    _write_eedata_word(EE_addr, temp_word);
    _wait_eedata();

    while(1){
    ClrWdt();
    };
    return 0;
}

Ich habe vier Theorien:

  1. Es finden Schreibvorgänge statt, und ich lese die Daten nicht korrekt zurück.
  2. Schreibvorgänge finden nicht statt, weil etwas mit meinem Code nicht stimmt.
  3. Schreibvorgänge finden nicht statt, weil etwas mit meinen Projekt-/Build-Optionen nicht stimmt.
  4. Es finden keine Schreibvorgänge statt, weil etwas mit meiner Hardware nicht stimmt.

Ich habe ohne Ergebnis in den Microchip-Foren gepostet. Ich habe ein Ticket bei Microchip eröffnet, und sie sagten mir nur, ich solle einen Versammlungsaufruf verwenden/schreiben. Sie scheinen nicht daran interessiert zu sein, ob/warum diese eingebauten Funktionsaufrufe nicht funktionieren.

Hat jemand irgendwelche Vorschläge?

Was ist das Gerät?
@LeonHeller Aus der zuvor erwähnten Frage ist es adsPIC30F6012a
Richtig, Ergänzung zur Frage.
Liest MPLAB X das EEPROM wie erwartet? Ich habe einige eigene Theorien. (1) Nicht unterstützt. (2) Liest nicht zurück, bis Sie es im Menü anweisen. (3) Liest nicht korrekt zurück. Dies ist alles Original-MPLAB-Erfahrung. Es ist möglich, dass MPLAB X all dies behoben hat. Im Zweifelsfall lasse ich mir vom PIC seinen EEPROM-Inhalt mitteilen (eine Art Dump-Routine).
Die Daten, mit denen ich das EEPROM initialisiere, werden ordnungsgemäß in MPLAB X zurückgelesen, und gelöschte Werte werden als 0xFFFF zurückgelesen. Alles scheint zu funktionieren AUSSER dem Schreiben.

Antworten (2)

Im Zweifelsfall umgestalten.

Es ist wahrscheinlich kein Hardwareproblem, aber um es auszuschließen, würde ich versuchen, die C-Aufrufe durch die genauen Inline-Assembler-Anweisungen zu ersetzen, die in Abschnitt 7 des Datenblatts beschrieben sind, und alle Empfehlungen befolgen (Interrupts deaktivieren, WR abfragen, um auf Fertigkeit zu testen, usw.)

Wenn es funktioniert, erstellen Sie Ihre eigene Funktion/Bibliothek aus der Inline-Assembly und fahren Sie fort.

Leider hatte ich das, was ich versuche, umzugestalten!
Sie sollten etwas in den Microchip-Foren posten oder sich mit einem FAE in Verbindung setzen, wenn der im Datenblatt veröffentlichte Code nicht funktioniert.
Bereits im Forum gepostet und ein Ticket eröffnet. Auf beides keine Reaktion.
Könnten Sie auch Ihre Demontage- / Auflistungsdatei posten?
Amüsanterweise bestand die Antwort des technischen Supports von Microchip auch darin, die Compiler-Funktionsaufrufe durch Assembler-Code zu ersetzen. Als ich fragte, warum die Funktionen nicht funktionierten, hatten sie keine Antwort und weigerten sich, meinen Code überhaupt zu testen. Anscheinend werden die Funktionen, obwohl die von mir verwendeten Funktionen in der Compiler-Dokumentation aufgeführt sind und obwohl Microchip auf ihrer Website Democode veröffentlicht, nicht wirklich von Microchip unterstützt.

Zunächst können Sie überprüfen, ob das EEPROM erfolgreich geschrieben wurde, indem Sie es über das PSV-Fenster (Program Space Visibility) zurücklesen. In vielen Fällen brauche ich das PSV-Fenster für nichts anderes, also lasse ich es dauerhaft für den Zugriff auf das EEPROM konfiguriert.

Zweitens habe ich mir Ihren C-Code nicht angesehen, aber hier ist ein Ausschnitt aus einem 30F4013-Projekt, das das PSV-Fenster zum Lesen einrichtet und ein Byte in das EEPROM schreibt:

;**************************************************** ******************************
;
; Unterprogramm IEE_INIT
;
; Initialisieren Sie den von diesem Modul verwalteten Hardware- und Softwarestatus.
;
         glbsub iee_init, regg0
;
; Richten Sie das Sichtbarkeitsfenster des Programmbereichs ein, um das interne Daten-EEPROM abzubilden
; zum Datenraum.
;
         mov #psvpage(ieestart), w0
         mov w0, Psvpag ; welcher Bereich des Programmspeichers den Daten adr 8000-FFFF zugeordnet werden soll
         bset Corcon, #Psv ;Sichtbarkeitsfenster des Programmbereichs aktivieren

         Urlaub

;**************************************************** ******************************
;
; Makro WAIT_EEPROM
;
; Warten Sie, bis alle vorherigen EEPROM-Operationen abgeschlossen sind. TASK_YIELD wird aufgerufen
; eine Schleife für die Dauer des Wartens. TASK_YIELD wird nicht aufgerufen, wenn das EEPROM
; ist bei der Eingabe nicht aktiv.
;
.macro wait_eeprom
1: ;hierher zurück, um EEPROM wieder belegt zu prüfen
         btss Nvmcon, #Wr ;EEPROM ist beschäftigt ?
         jump 2f ;nein, fertig
         gcall task_yield ;anderen Tasks die Möglichkeit geben, ausgeführt zu werden
         springe 1b ;zurück, um erneut zu prüfen, ob das EEPROM belegt ist
2: ;das EEPROM ist jetzt im Leerlauf
         .endm

;**************************************************** ******************************
;
; Unterprogramm IEE_WRITE
;
; Schreiben Sie den Wert in W0 in das EEPROM-Wort am Offset in W1. W1 muss
; enthalten die niedrigen 16 Bits der EEPROM-Position, wie sie im Programm abgebildet sind
; Speicher. Dies kann zum Beispiel durch Verwendung der TBLOFFSET-Funktion auf gefunden werden
; eines der oben im .EEPROM-Abschnitt definierten Adresssymbole. Seitdem
; sind zwei Adressen pro EEPROM-Wort und es wird immer ein ganzes Wort geschrieben, das
; Low-Bit von W1 ist irrelevant.
;
; W1 wird um 2 erhöht zurückgegeben, was die Adresse des nächsten EEPROMs ist
; Wort. Aufeinanderfolgende Aufrufe dieser Routine, ohne daher W1 zu modifizieren
; sequentielle EEPROM-Wörter setzen.
;
; Diese Routine kehrt zurück, nachdem der Schreibvorgang abgeschlossen ist. Das könnte mehrere
; Millisekunden. TASK_YIELD wird während jeder Wartezeit in einer Schleife aufgerufen.
;
; Dieser Prozessor hat 512 Worte EEPROM.
;
         glbsub iee_write, regf2

         wait_eeprom ;warten, bis alle vorherigen Operationen abgeschlossen sind
;
; Hole den aktuellen EEPROM-Zielwortwert in W2.
;
         mov #tblpage(ieestart), w2
         mov w2, Tblpag ;Auswahl der Programmspeicherseite, auf die zugegriffen werden soll
         tblrdl [w1], w2 ;Lesen Sie das Ziel-EEPROM-Wort
         cp w0, w2 ;den neuen Wert mit dem bestehenden vergleichen
         bra z, iew_leave ;keine Änderung, nichts zu tun ?
;
; Löschen Sie das EEPROM-Wort, wenn irgendwelche 0-Bits in 1-Bits geändert werden. Der
; vorhandener Wert des Wortes ist in W2. TBLPAG ist bereits passend dafür gesetzt
; die EEPROM-Adresse.
;
         com w2, w2 ;Maske der Bits erstellen, die derzeit auf 0 gesetzt sind
         und w2, w0, w2 ; Maske aus 0-Bits erstellen, um sie auf 1 zu ändern
         bra z, iew_derase ;keine 1-Bits, die sich auf 0 ändern, das Löschen überspringen
         ;
         ; Führen Sie die Löschung durch.
         ;
         ; Laut dem Familien-Referenzhandbuch führen Sie eine Löschung durch
         ; müssen die Adresse einstellen und dann ein Wort löschen. Allerdings haben wir
         ; festgestellt, dass dies beim ersten Schreibversuch seit dem Start nicht funktioniert.
         ; Nach einigem Experimentieren wurde festgestellt, dass ein Schreib-Latch geladen wird
         ; Einmal scheint das zu sein, was das Löschen ermöglicht. Wir laden daher die
         ; Write-Latch vor dem Löschen, auch wenn dies nicht notwendig ist
         ; laut Dokumentation. Seit dem Laden des Schreib-Latch für
         ; Das Wort zum Löschen setzt auch die Adresse, wir müssen sie nicht setzen
         ; NVMADR ausdrücklich. Die Daten, die wahrscheinlich in das Schreiblatch geschrieben wurden
         ; spielt keine Rolle, aber wir schreiben den Löschwert, da das die macht
         ; am sinnvollsten und hat die besten Chancen, weitere zu umgehen
         ; undokumentiertes Verhalten.
         ;
         Bewegung #0xFFFF, w2
         tblwtl w2, [w1] ;Latch mit dem Löschwert laden, Adresse setzen

         mov #0b0100000001000100, w2
                 ; 0--------------- Betrieb jetzt nicht einleiten
                 ; -1-------------- Löschvorgang aktivieren
                 ; --0------------ Alle vorherigen Fehlerzustände löschen
                 ; ---XXXXX-------- unbenutzt
                 ; --------0100---- Löschvorgang auswählen
                 ; -------------0100 ein Datenwort
         mov w2, Nvmcon ; für den Löschvorgang konfigurieren

         disi #5 ;Interrupts um die Unlock-Sequenz herum deaktivieren
         mov #0x55, w2 ;Freischaltsequenz ausführen
         mov w2, Nvmkey
         Bewegung #0xAA, w2
         mov w2, Nvmkey
         bset Nvmcon, #Wr ;löschen starten

         wait_eeprom ;warten, bis der Löschvorgang abgeschlossen ist
iew_derase: ;Fertig mit dem Löschen des Wortes
;
; Schreibe das Wort.
;
         tblwtl w0, [w1] ;Wort schreiben, Adresse erhöhen

         mov #0b0100000000000100, w2
                 ; 0--------------- Betrieb jetzt nicht einleiten
                 ; -1-------------- Löschvorgang aktivieren
                 ; --0------------ Alle vorherigen Fehlerzustände löschen
                 ; ---XXXXX-------- unbenutzt
                 ; --------0000---- Schreibvorgang auswählen
                 ; -------------0100 ein Datenwort
         mov w2, Nvmcon ; für den Löschvorgang konfigurieren

         disi #5 ;Interrupts um die Unlock-Sequenz herum deaktivieren
         mov #0x55, w2 ;Freischaltsequenz ausführen
         mov w2, Nvmkey
         Bewegung #0xAA, w2
         mov w2, Nvmkey
         bset Nvmcon, #Wr ;löschen starten

         wait_eeprom ;warten, bis der Schreibvorgang abgeschlossen ist

iew_leave: ;gemeinsamer Austrittspunkt
         w1, #2, w1 addieren ;Adresse zum nächsten EEPROM-Wort inkrementieren

         Urlaub

Beachten Sie, dass diese Routine einige nette Dinge tut, die über das blinde Schreiben der neuen Daten in das EEPROM hinausgehen. Es tut nichts, wenn das EEPROM-Wort bereits wie gewünscht eingestellt ist, und es überspringt auch das Löschen, wenn nur 1-Bits auf 0 gekippt werden. Dadurch wird das EEPROM weniger abgenutzt, insbesondere wenn ein anderer Code versehentlich in eine Schleife gerät, die in das EEPROM schreibt .