//------------------------------------------------------------------------------ /// The SPI_Handler must be called by the SPI Interrupt Service Routine with the /// corresponding Spi instance. /// The SPI_Handler will unlock the Spi semaphore and invoke the upper application /// callback. /// \param pSpid Pointer to a Spid instance. //------------------------------------------------------------------------------ void SPID_Handler(Spid *pSpid) { SpidCmd *pSpidCmd = pSpid->pCurrentCommand; AT91S_SPI *pSpiHw = pSpid->pSpiHw; volatile unsigned int spiSr; // Read the status register spiSr = READ_SPI(pSpiHw, SPI_SR); if (spiSr & AT91C_SPI_RXBUFF) { // Disable transmitter and receiver WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS); // Disable the SPI clock WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << pSpid->spiId)); // Disable buffer complete interrupt WRITE_SPI(pSpiHw, SPI_IDR, AT91C_SPI_RXBUFF); // Release the dataflash semaphore pSpid->semaphore++; // Invoke the callback associated with the current command if (pSpidCmd && pSpidCmd->callback) pSpidCmd->callback(0, pSpidCmd->pArgument); // Nothing must be done after. A new DF operation may have been started // in the callback function. } }
/** * \brief SPI xDMA Rx callback * Invoked on SPi DMA reception done. * \param channel DMA channel. * \param pArg Pointer to callback argument - Pointer to Spid instance. */ static void SPID_Rx_Cb(uint32_t channel, Spid* pArg) { SpidCmd *pSpidCmd = pArg->pCurrentCommand; Spi *pSpiHw = pArg->pSpiHw; if (channel != spiDmaRxChannel) return; /* Disable the SPI TX & RX */ SPI_Disable ( pSpiHw ); /* Configure and enable interrupt on RC compare */ NVIC_ClearPendingIRQ(XDMAC_IRQn); NVIC_DisableIRQ(XDMAC_IRQn); /* Disable the SPI Peripheral */ PMC_DisablePeripheral ( pArg->spiId ); /* Release CS */ SPI_ReleaseCS(pSpiHw); /* Release the DMA channels */ XDMAD_FreeChannel(pArg->pXdmad, spiDmaRxChannel); XDMAD_FreeChannel(pArg->pXdmad, spiDmaTxChannel); /* Release the dataflash semaphore */ pArg->semaphore++; printf("\n\r%s\n\r",pArg->pCurrentCommand->pRxBuff); /* Invoke the callback associated with the current command */ if (pSpidCmd && pSpidCmd->callback) { //printf("p %d", pArg->semaphore); pSpidCmd->callback(0, pSpidCmd->pArgument); } }
//------------------------------------------------------------------------------ /// SPI DMA transfer ISR, Handle RX complete //------------------------------------------------------------------------------ void SPID_Handler(Spid *pSpid) { unsigned int dmaStatus; SpidCmd *pSpidCmd = pSpid->pCurrentCommand; AT91S_SPI *pSpiHw = pSpid->pSpiHw; dmaStatus = DMA_GetStatus(); if ((dmaStatus & AT91C_CBTC) == 0) return; if ((dmaStatus & (DMA_CBTC << DMA_CHANNEL_0)) == 0) return; // Disable the SPI TX & RX WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SPIDIS); // Disable the SPI Peripheral PERIPH_DISABLE(pSpid->spiId); // Disable DMA DMA_Disable(); // Disable DMA Peripheral PERIPH_DISABLE(AT91C_ID_HDMA); // Release the dataflash semaphore pSpid->semaphore++; // Invoke the callback associated with the current command if (pSpidCmd && pSpidCmd->callback) { pSpidCmd->callback(0, pSpidCmd->pArgument); } }