EEPROM-Werte im XC8-Compiler vordefinieren

Ich arbeite mit einem PIC16F690 und verwende den XC8-Compiler von Microchip. Ich möchte EEPROM-Werte in die Hex-Datei einbetten, damit das EEPROM gleichzeitig mit dem Programmspeicher programmiert wird.

Ich habe dies in der Vergangenheit mit dem C18-Compiler (es war für einen PIC18, nicht diesen PIC16) wie folgt gemacht:

#pragma romdata eedata_scn=0xf00000
    rom unsigned char my_eeprom_values[256] = {0, 4, 2, 1, (and so on), 3};
#pragma romdata

Das EEPROM befindet sich nicht wirklich an diesem Speicherplatz (0xf00000), aber C18 greift so darauf zu. Sie können diese Adresse erhalten, indem Sie im Linker-Skript nachsehen:

CODEPAGE NAME=eedata START=0xF00000 END=0xF000FF PROTECTED

Jedenfalls funktioniert dies nicht in XC8. Es gibt eine andere Aussage, die ähnlich ist:

__EEPROM_DATA (0,1,2,3,3,2,1,0);

Aber diese Anweisung kann nur acht Argumente annehmen, und Sie können ihr, soweit ich das beurteilen kann, keinen Startort im EEPROM geben. Ihr Code endet also mit 32 dieser Anweisungen (für 256 Bytes EEPROM), was unhandlich erscheint.

Außerdem sagt das XC8-Benutzerhandbuch, dass diese Anweisung für PIC18's nicht implementiert ist. Das betrifft mich jetzt nicht, aber es wird in Zukunft!

Gibt es einen besseren Weg, dies in XC8 zu tun?


Bearbeiten:

Ich habe ein Support-Ticket bei Microchip eröffnet und diese Frage gestellt. Es stellt sich heraus, dass das Makro __EEPROM_DATA die einzige empfohlene Methode zum Initialisieren der EEPROM-Werte ist.

Positiv ist, dass dieses Makro tatsächlich für alle PIC18-Geräte mit internem EEPROM funktioniert. Mein Missverständnis kam von dieser Aussage in der Bedienungsanleitung :

2.5.9.4 VORBEHALTE MPLAB XC8 implementiert die __eeprom-Qualifizierer für keine PIC18-Geräte; Dieser Qualifizierer funktioniert wie erwartet für andere 8-Bit-Geräte.

Das Makro __EEPROM_DATA funktioniert jedoch. Ich habe es gerade erfolgreich getestet.

Trotzdem ist dies immer noch unhandlich. Gibt es eine Problemumgehung, die die Initialisierung eines bestimmten EEPROM-Standorts ermöglicht, ohne am Anfang zu beginnen?

Danke noch einmal.

Antworten (2)

Um alles unten zu testen, habe ich MPLAB 8.76, Compiler XC8 Version 1.30 verwendet:

Erstmal ein Exkurs/Hinweis: Falls Sie kürzlich auf PIC16F690 umgestiegen sind: Vor ~ 6 Wochen habe ich mich entschieden, diesen Chip außer für wirklich kleine Projekte aufzugeben. Es hat wenig FLASH, wenig RAM und nur 256 EEPROM. Und Sie können es nicht einfach auf echtem Ziel debuggen. Ich verwende jetzt 18FK4620: Es hat 16-mal so viel FLASH (64 kB), 4-mal mehr EEPROM (1 kB) und fast 16-mal mehr RAM (~ 4 kB), es kann mit bis zu 64 MHz Fosc (!) Und mehr Ports laufen, usw.

Und das WICHTIGSTE: Sie können 18F46K20 mit Standard PICKIT2 und MPLAB 8.76 ... 8.91 DEBUGEN (ich benutze MPLAB X noch nicht, da ich viele schlechte Geschichten darüber gehört habe). Und Sie benötigen keine zusätzlichen Schnittstellenkarten usw. Nur Ihre Zielkarte --> PICKIT2 (dh Sie müssen nicht auf ein Missgeschick PICKIT3 umsteigen)

Und der Preis ist sehr ähnlich: 18F46K20 kostet ~ 2,90 $ und 16F690 ~ 2,40 $ im Einzelhandel.

JETZT LÖSUNGEN FÜR SIE:

---------------------- Lösung 1a: Verwenden Sie so etwas (und ändern Sie '20' auf die gewünschte Array-Größe):

__eeprom unsigned char my_eeprom_values[20] =  
        {   0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20,
            0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30};**

Aber wenn Sie das Obige verwenden, wissen Sie NICHT, wo der Compiler diese im EEPROM platzieren wird. (Beachten Sie jedoch, dass der Qualifizierer __eeprom vom XC8-Compiler für viele PIC18Fxxx-Geräte ignoriert wird.)

---------------------- Lösung 1b:

const unsigned char abc1 @ 0x2100 = 0x11; // @ EEPROM addr = 0
    // ......
    const unsigned char abc2 @ 0x2110 = 0x22; // @ EEPROM addr = 17**

Beachten Sie, dass das EEPROM in 16F690 bei Adresse beginnt. 0x2100 (nicht 0xF00000, wie Sie erwähnt haben). Ich habe die .map-Datei nach dem Build überprüft. Ich habe auch das Ergebnis des obigen nach dem Kompilieren des Codes überprüft und dann das EEPROM mit PICKIT2 angezeigt (oder wenn Sie unter MPLAB mit MPLAB SIM debuggen, gehen Sie nach dem Erstellen des Codes zu Menü -> ANSICHT -> EEPROM). Dort sehen Sie alle gewünschten Daten.

---------------------- Lösung 1c:

Sie können (1a) und (1b) oben mischen, Sie können 'int' anstelle von 'char' verwenden, aber: - Beachten Sie, dass eine Anweisung einige der anderen überschreibt, da __EEPROM_DATA die Angabe der eerpom-Adresse nicht zulässt . Um dies zu veranschaulichen, habe ich 0x99 an Stellen platziert, die überschrieben WÜRDEN. XC8 warnt trotzdem davor - siehe Ende meines Posts. - Endian, dass XC8 'Swaps'-Bytes vom Typ 'int' verwendet: Die folgenden 'abc'-Daten werden gespeichert als: 22114433, anstatt als 11223344.

---------------------- BEISPIEL:

Hier ist ein getestetes Beispiel für 16F690 unter XC8 Version 1.30:

    const unsigned int abc1 @ 0x2100 = 0x1122;
    const unsigned int abc2 @ 0x2102 = 0x3344;
  __EEPROM_DATA(0x99, 0x99, 0x99, 0x99, 5, 6, 7, 8);
    const unsigned int abc3 @ 0x2108 = 0x5566;
    __EEPROM_DATA(0x99, 0x99, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88);
    __eeprom unsigned char my_eeprom_values[20] = \ 
    {   0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20,
        0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30};

Der resultierende EEPROM-INHALT ist dieser:

22 11 44 33 05 06 07 08 66 55 83 84 85 86 87 88
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
27 28 29 30 FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF ...

Also 0x(22 11 44 ​​33) hat 4 x 0x99 überschrieben. Dasselbe gilt für 0x(66 55). Beachten Sie jedoch, dass der Rest nur eine einfache Kopie von Daten im C-Code ist.

---------------------- Lösung 2: 'deine': Platzieren Sie so viele '8 Byte' lange __EEPROM_DATA-Anweisungen wie Sie brauchen. Was ist daran falsch? Es ist einfach und funktioniert immer. Der Compiler platziert Daten in der Reihenfolge, in der Sie sie in Ihrem C-Code haben werden. Wenn einige Bytes unverändert bleiben sollen, platzieren Sie 0xFF für sie. Z.B.

__EEPROM_DATA(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);  // addr: 0x00 ... 0x07 
__EEPROM_DATA(0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88);  // addr: 0x08 ... 0x0F
__EEPROM_DATA(0x55, 0x66, 0x87, 0x65, 0xFF, 0xFF, 0xFF, 0xFF);  // addr: 0x10 ... 0x17 
etc.

Während des Einbaus von (1b/1c) gibt der XC8-Compiler diese Warnungen aus:

.... object "_abc1" lies outside available code space

... (1343) hexfile data at address 0x4200 (0x99) overwritten with 0x22 

aber ich habe Daten, die ich wollte, im EEPROM, wo ich sie haben wollte, also ist es mir egal.

Speicherzusammenfassung: Benutzter Programmplatz F00h (3840) von 1000h Worten (93,8%) Benutzter Datenplatz E4h (228) von 100h Bytes (89,1%) Benutzter EEPROM-Platz 24h (36) von 100h Bytes (14,1%) ...

-Ende-

Nachdem ich mir die obigen Vorschläge und einige andere Suchen angesehen hatte, stieß ich auf die folgende Lösung. Dies schließt die Aktualisierungen des Compilers ein, sodass ich MPLABX 5.25 und XC8 v2.1 verwende. Ich habe den folgenden Befehl verwendet, da das Eeprom für den PIC1846K80 ab 0xF00000 "lokalisiert" ist.

const uint8_t my_variable __at (0xF0000C) = 0xA5; //0xF0000C zum Schreiben an Position 0xC

Das obige ergab die folgende Hex-Datei mit dem folgenden Chunk. Die erste Zeile zeigt an, dass es sich jetzt auf das EEPROM bezieht, die zweite Zeile listet 1 Byte im Speicher 0x0C des EEPROM auf und hat 0xA5, die letzte Zeile zeigt das Ende der Datei an.

:0200000400F00A // Offset zum EEPROM-Speicherort

:01000C00A54E // bei EEPROM-Adresse 0x0C schreibe 0xA5

:00000001FF // Dateiende