Die von Ihnen beschriebenen Daten (vollständige 24-Bit-Nutzung des Programmspeichers zum Speichern von Daten) können in C nicht definiert und initialisiert werden und können nicht direkt über C gelesen werden. Der einzige Weg, darauf zuzugreifen, ist die Kapselung in eine C-aufrufbare Assembly-Funktion oder eine intrinsische.
Hier gibt es wirklich zwei Fragen:
So spielen Sie gut mit dem Compiler, Assembler und Linker, sodass D1
der Compiler diese Variable sehen kann , wenn Sie Ihre 24-Bit-Daten in einer Assembly-Datei als verschiebbare Daten mit einem symbolischen Namen und nicht als unbenannte Daten an einer festen Adresse definieren um seine Adresse zu bestimmen
wie man auf die Daten zugreift
Die zweite Frage (Zugriff auf die Daten) wird für 33EP-Teile in DS70613C beantwortet und sollte für 33FJ-Teile in DS70204C beantwortet werden (in den Beispielen im 33FJ-Handbuch werden jedoch nur die niedrigen 16 Bit verwendet). Hier ist ein Beispiel-Code-Snippet aus dem 33EP-Referenzhandbuch, das für 33EP-Teile + für 33FJ funktioniert (ich habe kein leicht verfügbares 33FJ-Gerät):
(Anmerkung: Code Anwendungen int
, während es besser wäre , zu verwenden uint16_t
und #include <stdint.h>
)
int prog_data[10] __attribute__((space(prog))) =
{0x0000, 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888, 0x9999};
unsigned int lowWord[10], highWord[10];
unsigned int tableOffset, loopCount;
int main(void){
TBLPAG = __builtin_tblpage (prog_data);
tableOffset = __builtin_tbloffset (prog_data);
/* Read all 10 constants into the lowWord and highWord arrays */
for (loopCount = 0; loopCount < 10; loopCount ++)
{
lowWord[loopCount] = __builtin_tblrdl (tableOffset);
highWord[loopCount] = __builtin_tblrdh (tableOffset);
tableOffset +=2;
}
while(1)
;
}
Sie werden feststellen, dass die integrierten Funktionen __builtin_tblrdl()
und __builtin_tblrdh()
zum Lesen der niedrigen und hohen 16-Bit-Wörter von Daten aus einem Programmspeicher __builtin_tblpage() and __builtin_tbloffset()
verwendet werden und zum Extrahieren der Seite und des Versatzes der Adresse verwendet werden können. In diesem speziellen Beispiel ist das highWord-Array immer 0, und das lowWord-Array stimmt mit den in C definierten und initialisierten prog_data überein.
Bitte beachten Sie, dass hier keine Zeiger verwendet werden! Es ist zwar möglich, normale Variablen zu verwenden, die mit Tags versehen sind const
, so dass sie vom Linker im schreibgeschützten Programmbereich lokalisiert werden und Sie den Speicher mit Standard-C-Zeigertechniken lesen können, wobei der Compiler die Paging-Register automatisch verwaltet Für Sie können Sie nur 16-Bit-Daten speichern. Sie müssen auf die integrierten Funktionen TBLRDL und TBLRDH zugreifen, um alle 24 Datenbits abzurufen.
Um mit dem Compiler / Linker / etc gut zu spielen, müssen Sie den Compiler täuschen und ihm mitteilen, dass nur 16-Bit-Daten angezeigt werden. Hier ist ein Beispiel, das funktioniert hat, um an die an anderer Stelle deklarierte Variable D1 zu gelangen:
#define D1_SIZE 18
extern uint16_t __attribute__((space(prog))) D1[D1_SIZE];
#define READ_DATA(dst, v, len) readData(dst, __builtin_tblpage(v), __builtin_tbloffset(v), len)
void readData(uint32_t *pdst, uint16_t page, uint16_t offset, uint16_t len)
{
TBLPAG = page;
while (len-- > 0)
{
uint16_t lo = __builtin_tblrdl (offset);
uint16_t hi = __builtin_tblrdh (offset);
*pdst++ = (((uint32_t)(hi)) << 16) | ((uint32_t)(lo));
offset += 2;
}
}
...
uint32_t d1copy[D1_SIZE];
READ_DATA(d1copy, D1, D1_SIZE);
Dadurch werden 24-Bit-Werte korrekt gelesen und in den unteren 24 Bit eines uint32_t gespeichert. Die in C deklarierte externe D1-Variable ist eine Dummy-Variable, die nur verwendet wird, um an die Startadresse zu gelangen, indem die Zusammenarbeit von Compiler / Assembler / Linker ausgenutzt wird. Die eingebauten Funktionen erledigen den Rest der Arbeit.
Was ich nicht weiß, ist, wie die Größe der Daten automatisch ermittelt wird, da sie in der Assembly definiert + initialisiert sind.