Les données que vous décrivez (utilisation complète de 24 bits de la mémoire du programme pour stocker les données) ne peuvent pas être définies et initialisées en C, et ne peuvent pas être lues directement via C; la seule façon d'y accéder est d'encapsuler dans une fonction d'assemblage appelable C ou intrinsèque.
Il y a vraiment deux questions ici:
comment bien jouer avec le compilateur, l'assembleur et l'éditeur de liens, de sorte que lorsque vous définissez vos données 24 bits dans un fichier d'assemblage en tant que données déplaçables avec un nom symbolique D1
, plutôt que des données sans nom à une adresse fixe, le compilateur peut voir cette variable pour déterminer son adresse
comment accéder aux données
La deuxième question (comment accéder aux données) est répondue pour les pièces 33EP dans DS70613C et doit être répondue pour les pièces 33FJ dans DS70204C (mais les exemples dans le manuel 33FJ n'utilisent que les 16 bits bas). Voici un exemple d'extrait de code du manuel de référence 33EP qui fonctionne pour les pièces 33EP + devrait pour 33FJ (je n'ai pas de périphérique 33FJ facilement disponible):
(Remarque: le code utilise int
, alors qu'il serait préférable d'utiliser uint16_t
et #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)
;
}
Vous remarquerez que les fonctions intégrées __builtin_tblrdl()
et __builtin_tblrdh()
sont utilisées pour lire les mots de données bas et hauts de 16 bits à partir d'un emplacement de mémoire de programme, et __builtin_tblpage() and __builtin_tbloffset()
peuvent être utilisées pour extraire la page et le décalage de l'adresse. Dans cet exemple particulier, le tableau highWord est toujours 0 et le tableau lowWord correspond au prog_data défini et initialisé en C.
Veuillez noter qu'aucun pointeur n'est utilisé ici! Bien qu'il soit possible d'utiliser des variables normales qui sont étiquetées avec const
, afin qu'elles soient localisées par l'éditeur de liens dans l'espace programme en lecture seule, et que vous puissiez lire la mémoire en utilisant des techniques de pointeur C standard, le compilateur gérant automatiquement les registres de pagination pour vous, vous ne pouvez stocker que des données 16 bits. Vous devez accéder aux fonctions intégrées TBLRDL et TBLRDH pour obtenir les 24 bits de données.
Quant à savoir comment bien jouer avec le compilateur / éditeur de liens / etc, vous devez tromper le compilateur et lui dire qu'il ne voit que des données 16 bits. Voici un exemple qui a fonctionné pour obtenir la variable D1 déclarée ailleurs:
#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);
Cela lit correctement les valeurs 24 bits et les stocke dans les 24 derniers bits d'un uint32_t. La variable extern D1 déclaré dans C est une variable factice qui ne sert à obtenir à l'adresse de départ en tirant parti de la façon dont le compilateur / assembleur / éditeur de liens de travail ensemble. Les fonctions intégrées gèrent le reste du travail.
Ce que je ne sais pas, c'est comment obtenir automatiquement la taille des données, car elles sont définies + initialisées en assembleur.