2010-03-18 2 views
2

Le périphérique SPI de mon AT91SAM7X512 est désactivé sur l'heure X (X varie) que j'écris à SPI_TDR. Par conséquent, le processeur se bloque sur la boucle while qui vérifie l'indicateur TDRE dans SPI_SR. Cette boucle While est située dans la fonction SPI_Write() qui appartient au logiciel/bibliothèque fourni par ATMEL. Le problème se produit de manière arbitraire - parfois, tout fonctionne correctement et parfois il échoue lors de tentatives répétées (tentative = téléchargement du même fichier binaire dans le MCU et exécution du programme).Le périphérique SPI d'AT91SAM7X512 est désactivé lors de l'écriture sur SPI_TDR

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 réglé les configurations, le code vérifie que le SPI est activé, en vérifiant le drapeau SPIENS.

-je effectuer 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 provoque le périphérique SPI devenir désactivé sur l'écriture à SPI_TDR?
  2. Devrais-je supprimer la ligne SPI_Write() qui lit le registre SPI_RDR?
    moyens, la 4ème ligne dans le code suivant: (La 4ème ligne est à l'origine marqué 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 at-il quelque chose de mal avec le code ci-dessus qui transmet 5 octets de données?

S'il vous plaît noter:

  • La ligne num PNJs. 3 est une ligne GPIO (signifie, 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 dé/affirmant la broche ChipSelect # 3 (NPCS3) si nécessaire. La raison pour laquelle je le fais est parce que des problèmes sont survenus en essayant 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, car l'errata dit de le réinitialiser deux fois seulement si j'effectue une réinitialisation - ce que je ne fais pas. Citant le errata:

    Si une réinitialisation logicielle (SWRST dans le contrôle SPI Register) est effectuée, le SPI peut ne pas fonctionner correctement (l'horloge est activé avant la sélection de puce.)
    Problème Fix/Solution
    Le champ Registre de contrôle SPI, SWRST (réinitialisation logicielle) doit être écrit deux fois pour être correctement défini.

  • je remarquai que parfois, si je mets un délai avant l'écriture au registre SPI_TDR (en SPI_Write()), le code fonctionne parfaitement et les communications MOTIVEE.

Liens utiles:

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

+0

Avez-vous résolu ce problème? Nous serions intéressés de savoir si vous avez trouvé la cause première. – Bwooce

+0

Je ne me souviens pas comment j'ai résolu le problème. Je pense que j'ai eu un problème dans le processus d'initialisation de l'horloge du processeur: les étapes de init n'étaient pas comme écrit dans la fiche technique. – Dor

+0

Notamment, ce code ne "transmet pas cinq octets de données". –

Répondre

1

Vous utilisez

while(i-- < dataSize) 

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

De plus, vous vérifiez déjà TXEMPTY ce qui implique que les données sont déplacées vers 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.

Aussi, 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.

Questions connexes