//------------------------------------------------------------------------------ // Local functions //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /// This handler function must be called by the DMAC interrupt service routine. /// Identifies which event was activated and calls the associated function. //------------------------------------------------------------------------------ void DMAD_Handler() { unsigned int status; unsigned char channel; DmaTransfer *pTransfer; status = DMA_GetStatus(); // Check if the buffer transfer completed is set. if(status & AT91C_BTC) { // Scan each channel status. for(channel = 0; channel < DMA_CHANNEL_NUM; channel++) { if(!(status & (DMA_BTC << channel))){ continue; } dmad.transfers[channel].transferSize -= dmad.transfers[channel].bufSize; // if next buffer is to be the last buffer in the transfer, then clear the automatic mode bit. if(dmad.transfers[channel].transferSize <= dmad.transfers[channel].bufSize) { DMA_ClearAutoMode(channel); } // Transfer finished if(dmad.transfers[channel].transferSize == 0) { pTransfer = &(dmad.transfers[channel]); pTransfer->callback(); DMA_DisableIt(DMA_BTC << channel); DMA_DisableChannel(channel); } else { // Write the KEEPON field to clear the STALL states. DMA_KeeponChannel(channel); } } } }
//------------------------------------------------------------------------------ /// Starts buffer transfer on the given channel /// \param channel Particular channel number. /// \param size Total transfer size in byte. /// \param callback Optional callback function. /// \param polling Polling channel status enable. //------------------------------------------------------------------------------ unsigned char DMAD_BufferTransfer(unsigned char channel, unsigned int size, DmaCallback callback, unsigned char polling) { DmaTransfer *pTransfer = &(dmad.transfers[channel]); // Check that no transfer is pending on the channel if (pTransfer-> transferSize > 0 ) { TRACE_ERROR("DAM transfer is already pending\n\r"); return DMAD_ERROR_BUSY; } pTransfer->status = DMAD_ERROR_BUSY; pTransfer->transferSize = size; pTransfer->callback = callback; if(!polling){ DMA_EnableIt(DMA_BTC << channel); } // Enable the channel. DMA_EnableChannel(channel); if(polling){ while ((DMA_GetChannelStatus() & (DMA_ENA << channel)) == (DMA_ENA << channel)); pTransfer->callback(); DMA_DisableChannel(channel); } return 0; }
//------------------------------------------------------------------------------ /// Starts buffer transfer on the given channel /// \param channel Particular channel number. /// \param size Total transfer size in byte. /// \param callback Optional callback function. /// \param polling Polling channel status enable. //------------------------------------------------------------------------------ U8 DMAD_BufferTransfer(U8 channel, U32 size, DmaCallback callback, U8 polling) { DmaTransfer *pTransfer = &(dmad.transfers[channel]); if (pTransfer-> transferSize > 0 ) // Check that no transfer is pending on the channel { DEBUG_MSG("DAM transfer is already pending"); return DMAD_ERROR_BUSY; } pTransfer->status = DMAD_ERROR_BUSY; pTransfer->transferSize = size; pTransfer->callback = callback; if(!polling) { DMA_EnableIt(0x1 << channel); } DMA_EnableChannel(channel); // Enable the channel. if(polling) { while ((DMA_GetChannelStatus() & (0x1 << channel)) == (0x1 << channel)); if (pTransfer->callback) { pTransfer->callback(); } pTransfer->transferSize = 0; DMA_DisableChannel(channel); } return 0; }
//------------------------------------------------------------------------------ // Local functions //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /// This handler function must be called by the DMAC interrupt service routine. /// Identifies which event was activated and calls the associated function. //------------------------------------------------------------------------------ extern void DMAC_IrqHandler( void ) { uint32_t dwStatus ; uint32_t dwChannel ; DmaTransfer *pTransfer ; dwStatus = DMA_GetStatus( DMAC ) ; // Check if the buffer transfer completed is set. if ( dwStatus & (DMAC_EBCISR_BTC0|DMAC_EBCISR_BTC1|DMAC_EBCISR_BTC2|DMAC_EBCISR_BTC3|DMAC_EBCISR_BTC4|DMAC_EBCISR_BTC5) ) { // Scan each dwChannel status. for ( dwChannel = 0 ; dwChannel < DMA_CHANNEL_NUM ; dwChannel++ ) { if ( !(dwStatus & (DMAC_EBCISR_BTC0 << dwChannel)) ) { continue ; } dmad.transfers[dwChannel].transferSize -= dmad.transfers[dwChannel].bufSize ; // if next buffer is to be the last buffer in the transfer, then clear the automatic mode bit. if ( dmad.transfers[dwChannel].transferSize <= dmad.transfers[dwChannel].bufSize ) { DMA_ClearAutoMode( DMAC, dwChannel ) ; } // Transfer finished if ( dmad.transfers[dwChannel].transferSize == 0 ) { pTransfer = &(dmad.transfers[dwChannel]) ; pTransfer->callback() ; DMA_DisableIt( DMAC, DMAC_EBCIDR_BTC0 << dwChannel ) ; DMA_DisableChannel( DMAC, dwChannel ) ; } else { // Write the KEEPON field to clear the STALL states. DMA_KeeponChannel( DMAC, dwChannel ) ; } } } }
//------------------------------------------------------------------------------ /// Starts buffer transfer on the given dwChannel /// \param dwChannel Particular dwChannel number. /// \param size Total transfer size in byte. /// \param callback Optional callback function. /// \param polling Polling dwChannel status enable. //------------------------------------------------------------------------------ extern uint32_t DMAD_BufferTransfer( uint32_t dwChannel, uint32_t dwSize, DmaCallback callback, uint32_t dwPolling ) { DmaTransfer *pTransfer = &(dmad.transfers[dwChannel]) ; // Check that no transfer is pending on the dwChannel if ( pTransfer-> transferSize > 0 ) { TRACE_ERROR( "DAM transfer is already pending\n\r" ) ; return DMAD_ERROR_BUSY ; } pTransfer->status = DMAD_ERROR_BUSY ; pTransfer->transferSize = dwSize ; pTransfer->callback = callback ; if ( dwPolling == 0 ) { DMA_EnableIt( DMAC, DMA_BTC << dwChannel ) ; } // Enable the dwChannel. DMA_EnableChannel( DMAC, dwChannel ) ; if ( dwPolling != 0 ) { while ( (DMA_GetChannelStatus( DMAC ) & (DMAC_CHSR_ENA0 << dwChannel)) == (DMAC_CHSR_ENA0 << dwChannel)) ; if ( pTransfer->callback ) { pTransfer->callback() ; } pTransfer->transferSize = 0 ; DMA_DisableChannel( DMAC, dwChannel ) ; } return 0 ; }
//------------------------------------------------------------------------------ /// This handler function must be called by the DMAC interrupt service routine. /// Identifies which event was activated and calls the associated function. //------------------------------------------------------------------------------ void DMAD_Handler() { U32 status; U8 channel; DmaTransfer *pTransfer; status = DMA_GetStatus(); if(status & (0xFF)) // Check if the buffer transfer completed is set. { for(channel = 0; channel < 8; channel++) // Scan each channel status. { if(!(status & (0x1 << channel))) { continue; } dmad.transfers[channel].transferSize -= dmad.transfers[channel].bufSize; if(dmad.transfers[channel].transferSize <= dmad.transfers[channel].bufSize) // if next buffer is to be the last buffer in the transfer, then clear the automatic mode bit. { DMA_ClearAutoMode(channel); } if(dmad.transfers[channel].transferSize == 0) // Transfer finished { pTransfer = &(dmad.transfers[channel]); pTransfer->callback(); DMA_DisableIt(0x1 << channel); DMA_DisableChannel(channel); } else { DMA_KeeponChannel(channel); // Write the KEEPON field to clear the STALL states. } } } }