2 votes

Le périphérique SPI de l'AT91SAM7X512 est désactivé lors de l'écriture de SPI_TDR.

Le périphérique SPI de mon AT91SAM7X512 est désactivé à l'heure X (X varie) où j'écris dans la base de données. SPI_TDR . En conséquence, le processeur s'accroche à la boucle while qui vérifie les données de la TDRE le drapeau en SPI_SR . Cette boucle while est située dans la fonction SPI_Write() qui appartient au progiciel/à la bibliothèque fournis par ATMEL. Le problème survient de manière arbitraire - parfois tout fonctionne bien et parfois il échoue lors de tentatives répétées (tentative = télécharger le même binaire sur le MCU et exécuter le programme).

Les configurations sont (définies dans l'ordre d'écriture) :

  1. SPI_MR :
    • MSTR = 1
    • PS = 0
    • PCSDEC = 0
    • PCS = 0111
    • DLYBCS = 0
  2. SPI_CSR[3] :
    • CPOL = 0
    • NCPHA = 1
    • CSAAT = 0
    • BITS = 0000
    • SCBR = 20
    • DLYBS = 0
    • DLYBCT = 0
  3. SPI_CR :
    • SPIEN = 1

Après avoir défini les configurations, le code vérifie que le SPI est activé, en vérifiant le paramètre SPIENS drapeau.

J'effectue une transmission d'octets comme suit :

const short int dataSize = 5;
// Filling array with random data
unsigned char data[dataSize] = {0xA5, 0x34, 0x12, 0x00, 0xFF};
short int i = 0;
volatile unsigned short dummyRead;

SetCS3();   // NPCS3 == PIOA15
while(i-- < dataSize) {
    mySPI_Write(data[i]);
    while((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
    dummyRead = SPI_Read(); // SPI_Read() from Atmel's library
}
ClearCS3();
/**********************************/
void mySPI_Write(unsigned char data) {
    while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
    AT91C_BASE_SPI0->SPI_TDR = data;
    while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TDRE) == 0); // <-- This is where
    // the processor hangs, because that the SPI peripheral is disabled
    // (SPIENS equals 0), which makes TDRE equal to 0 forever.
}

Questions :

  1. Qu'est-ce qui fait que le périphérique SPI est désactivé lors de l'écriture dans SPI_TDR ?

  2. Dois-je dé-commenter la ligne dans SPI_Write() qui lit le SPI_RDR s'inscrire ?
    Moyens, la 4ème ligne du code suivant : (La 4ème ligne est à l'origine marquée comme un commentaire)

    void SPI_Write(AT91S_SPI *spi, unsigned int npcs, unsigned short data)
    {
        // Discard contents of RDR register
        //volatile unsigned int discard = spi->SPI_RDR;
        /* Send data */
        while ((spi->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
        spi->SPI_TDR = data | SPI_PCS(npcs);
        while ((spi->SPI_SR & AT91C_SPI_TDRE) == 0);
    }
  3. Y a-t-il un problème avec le code ci-dessus qui transmet 5 octets de données ?

Veuillez noter :

  • Le numéro de ligne du NPCS. 3 est une ligne GPIO (c'est-à-dire en mode PIO), et n'est pas contrôlée par le contrôleur SPI. Je contrôle cette ligne moi-même dans le code, en activant le pin ChipSelect#3 (NPCS3) quand c'est nécessaire. La raison pour laquelle je fais cela est que des problèmes sont survenus lorsque j'ai essayé de laisser le contrôleur SPI contrôler cette broche.

  • Je n'ai pas utilisé le contrôleur PDC/DMA et je préfère ne pas l'utiliser.

  • Je n'ai pas réinitialisé le périphérique SPI deux fois, parce que l'errata dit de le réinitialiser deux fois seulement si je fais un reset - ce que je ne fais pas. Je cite l'errata :

    Si une réinitialisation logicielle (SWRST dans le registre de contrôle SPI) est effectuée, le SPI peut ne pas fonctionner. correctement (l'horloge est activée avant la sélection de puce).
    Résolution du problème/contournement
    Le champ du registre de contrôle SPI, SWRST (Software Reset) doit être écrit deux fois pour être corrigé. correctement.

  • J'ai remarqué que parfois si je mets un délai avant l'écriture dans le fichier SPI_TDR registre (en SPI_Write() ), alors le code fonctionne parfaitement et la communication réussit.

Liens utiles :

Un exemple d'initialisation du SPI et d'exécution d'un transfert de 5 octets serait très apprécié et utile.

1voto

obareey Points 213

Vous utilisez

while(i-- < dataSize)

décrémenter un nombre entier signé i en ne l'incrémentant pas et en accédant à data[i] jusqu'à i déborde sur une valeur positive. Qui sait ce qui se passe, à quelle mémoire ou à quels registres vous accédez ? L'utilisation d'entiers non signés est généralement préférable si vous n'avez pas besoin de conserver des valeurs négatives.

En outre, vous vérifiez déjà TXEMPTY ce qui implique que les données sont déplacées dans le registre à décalage et envoyées. Donc, vous n'avez pas besoin de vérifier TDRE également, ce qui implique que les données sont déplacées vers le registre à décalage mais ne peuvent pas être envoyées.

De plus, je recommande fortement d'utiliser PDC si vous n'échangez pas de données simultanément, ce qui n'est pas le cas je pense.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X