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):
SPI_MR
:MSTR
= 1PS
= 0PCSDEC
= 0PCS
= 0111DLYBCS
= 0
SPI_CSR[3]
:CPOL
= 0NCPHA
= 1CSAAT
= 0BITS
= 0000SCBR
= 20DLYBS
= 0DLYBCT
= 0
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:
- Qu'est-ce qui provoque le périphérique SPI devenir désactivé sur l'écriture à
SPI_TDR
? Devrais-je supprimer la ligne
SPI_Write()
qui lit le registreSPI_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); }
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
(enSPI_Write()
), le code fonctionne parfaitement et les communications MOTIVEE.
Liens utiles:
- AT91SAM7X Series Preliminary.pdf
- ATMEL software package/library
- spi.c from Atmel's library
- spi.h from Atmel's library
Un exemple d'initialisation du SPI et d'exécution d'un transfert de 5 octets est très apprécié et utile.
Avez-vous résolu ce problème? Nous serions intéressés de savoir si vous avez trouvé la cause première. – Bwooce
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
Notamment, ce code ne "transmet pas cinq octets de données". –