2011-03-02 2 views
3

Je sais que ce sujet (DMA & SPI) a déjà été abordé sur de nombreux threads dans le forum de la micropuce, en fait j'ai lu toutes les 15 pages en résultat de la recherche avec le mot clé " dma "et lire tous les sujets sur dma & spi.Recevoir des données SPI via DMA sur PIC32

Et je suis toujours coincé avec mon problème, j'espère que quelqu'un peut me aider :)

est ici le problème.

Ma puce est un PIC32MX775F512H. J'essaie de recevoir (seulement recevoir) des données en utilisant SPI via DMA. Comme vous ne pouvez pas "juste" recevoir en SPI, et que le noyau SPI commence à basculer l'horloge SPI seulement si vous écrivez dans le SPIBUF (SPI1ABUF pour moi) j'essaye de recevoir mes données en utilisant 2 canaux DMA. DMA_CHANNEL1 pour la partie de transmission. DMA_CHANNEL2 pour la partie réceptrice.

-je copier collé le code de http://www.microchip.com/forums/tm.aspx?tree=true&high=&m=562453&mpage=1#

et a essayé de le faire fonctionner sans chance. Il ne reçoit que plusieurs octets (5 ou 6).

J'ai défini les indicateurs d'activation d'événement sur DMA_EV_BLOCK_DONE pour les deux canaux dma, aucune interruption ne se produit.

Avez-vous une idée?

Voici le code que je utilise:

int Spi_recv_via_DMA(SPI_simple_master_class* SPI_Port, int8u *in_bytes, int16u num_bytes2) 
{ 
DmaChannel dmaTxChn=DMA_CHANNEL1; 
DmaChannel dmaRxChn=DMA_CHANNEL2; 
SpiChannel spiTxChn=SPI_Port->channel; 
    int8u   dummy_input; 

    DmaChnOpen(dmaTxChn, DMA_CHN_PRI3, DMA_OPEN_DEFAULT); 
    DmaChnOpen(dmaRxChn, DMA_CHN_PRI3, DMA_OPEN_DEFAULT); 

    DmaChnSetEventControl(dmaTxChn, DMA_EV_START_IRQ_EN | DMA_EV_START_IRQ(_SPI1A_RX_IRQ)); 
    DmaChnSetEventControl(dmaRxChn, DMA_EV_START_IRQ_EN | DMA_EV_START_IRQ(_SPI1A_RX_IRQ)); 

    DmaChnClrEvFlags(dmaTxChn, DMA_EV_ALL_EVNTS); 
    DmaChnClrEvFlags(dmaRxChn, DMA_EV_ALL_EVNTS); 
    DmaChnSetEvEnableFlags(dmaRxChn, DMA_EV_BLOCK_DONE); 
    DmaChnSetEvEnableFlags(dmaTxChn, DMA_EV_BLOCK_DONE); 

    //SpiChnClrTxIntFlag(spiTxChn); 
    //SpiChnClrRxIntFlag(spiTxChn); 

    DmaChnSetTxfer(dmaTxChn, tx_dummy_buffer, (void *)&SPI1ABUF, num_bytes2, 1, 1); 
    DmaChnSetTxfer(dmaRxChn, (void *)&SPI1ABUF, in_bytes, 1, num_bytes2, 1); 

    while ((SPI1ASTAT & SPIRBE) == 0) 
     dummy_input = SPI1ABUF; 
    SPI1ASTAT &= ~SPIROV; 

    DmaRxIntFlag = 0; 
    DmaChnEnable(dmaRxChn); 
    DmaChnStartTxfer(dmaTxChn, DMA_WAIT_NOT, 0); 


    while(!DmaRxIntFlag); 
    return 1;  
} 

avec ces deux gestionnaires d'interruption:

// handler for the DMA channel 1 interrupt 
void __ISR(_DMA1_VECTOR, ipl5) DmaHandler1(void) 
{ 
int evFlags;  // event flags when getting the interrupt 
    //LED_On(LED_CFG); 
INTClearFlag(INT_SOURCE_DMA(DMA_CHANNEL1)); // acknowledge the INT controller, we're servicing int 

evFlags=DmaChnGetEvFlags(DMA_CHANNEL1); // get the event flags 

    if(evFlags&DMA_EV_BLOCK_DONE) 
    { // just a sanity check. we enabled just the DMA_EV_BLOCK_DONE transfer done interrupt 
     DmaTxIntFlag = 1; 
    DmaChnClrEvFlags(DMA_CHANNEL1, DMA_EV_BLOCK_DONE); 
    } 
    // LED_Off(LED_CFG); 
} 

void __ISR(_DMA2_VECTOR, ipl5) DmaHandler2(void) 
{ 
int evFlags;  // event flags when getting the interrupt 

INTClearFlag(INT_SOURCE_DMA(DMA_CHANNEL2)); // acknowledge the INT controller, we're servicing int 

evFlags=DmaChnGetEvFlags(DMA_CHANNEL2); // get the event flags 

    if(evFlags&DMA_EV_BLOCK_DONE) 
    { // just a sanity check. we enabled just the DMA_EV_BLOCK_DONE transfer done interrupt 
     DmaRxIntFlag = 1; 
    DmaChnClrEvFlags(DMA_CHANNEL2, DMA_EV_BLOCK_DONE); 
    } 
} 

Je finissent par attendre pour toujours à la ligne: while (! DmaRxIntFlag);

J'ai mis des points d'arrêt dans les vecteurs d'interruption, ils ne sont jamais appelés.

C'est l'état de plusieurs registres au cours de la toujours durable attente:

DMACON 0x0000C800
DMASTAT 0x00000001

J'utilise le port SPI1A, si SPI1ABUF et _SPI1A_RX_IRQ

DCH1SPTR 0x5
DCH1SSIZ 0x2B

DCH2DPTR 0x6
DCH2DSI Z 0x2B

DCH2CON 0x00008083
DCH2ECON 0x1B10
DCH2INT 0x00800C4
DCH2SSA 0x1F805820
DCH2DSA 0x00000620

canal 1 est utilisé pour transmettre
Channel 2 est utilisé pour recevoir

+0

Quel type de périphérique se trouve à l'autre extrémité de la connexion SPI? Je dois supposer qu'il est déjà dans un mode où il envoie des données? –

Répondre

0
  1. Êtes-vous utiliser le SPI en mode esclave? ou vous êtes en mode maître, en essayant de lire une réponse pour une commande?
  2. Avez-vous vérifié l'errata de silicium pour cette puce? La famille dspic 33fj avait un problème où le mode esclave SPI ne fonctionnait tout simplement pas.

Autre que cela, je ne pense pas que ce soit une bonne idée d'attendre le changement occupé DmaRxIntFlag. Vous devez configurer le transfert DMA et continuer avec votre boucle principale. Le DMA déclenchera le gestionnaire d'interruption.

Espérons que cela aide.

1

Il vous manque ces:

INTEnable(INT_SOURCE_DMA(dmaTxChn), INT_ENABLED); // Tx 
INTEnable(INT_SOURCE_DMA(dmaRxChn), INT_ENABLED); // Rx 

rigth avant

DmaRxIntFlag = 0; 
DmaChnEnable(dmaRxChn); 
DmaChnStartTxfer(dmaTxChn, DMA_WAIT_NOT, 0); 

Bonne chance!

Questions connexes