Пример #1
0
//------------------------------------------------------------------------------
//./ Configure the DMA Channels: 0 RX, 1 TX.
//./ Channels are disabled after configure.
//------------------------------------------------------------------------------
static void configureDmaChannels(void)
{
    // Enable DMA Peripheral
    PERIPH_ENABLE(AT91C_ID_HDMA);
    // Enable DMA
    DMA_Enable();

    // Free status
    DMA_DisableIt(0xFFFFFFFF);
    DMA_GetChannelStatus();
    DMA_GetStatus();
    DMA_DisableChannels((1 << DMA_CHANNEL_0) | (1 << DMA_CHANNEL_1));
    // RX channel 0
    DMA_SetConfiguration(DMA_CHANNEL_0,
                          AT91C_HDMA_SRC_PER_2
                        | AT91C_HDMA_DST_PER_2
                        | AT91C_HDMA_SRC_H2SEL_HW
                        | AT91C_HDMA_DST_H2SEL_SW
                        | AT91C_HDMA_SOD_ENABLE
                        | AT91C_HDMA_FIFOCFG_LARGESTBURST
                        );

    // TX channel 1
    DMA_SetConfiguration(DMA_CHANNEL_1,
                          AT91C_HDMA_SRC_PER_1
                        | AT91C_HDMA_DST_PER_1
                        | AT91C_HDMA_SRC_H2SEL_SW
                        | AT91C_HDMA_DST_H2SEL_HW
                        | AT91C_HDMA_SOD_ENABLE
                        | AT91C_HDMA_FIFOCFG_LARGESTBURST
                        );
}
Пример #2
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.
//------------------------------------------------------------------------------ 
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);
            }
        }
    }
}
Пример #3
0
//------------------------------------------------------------------------------
/// Initializes the DMA controller.
/// \param dwChannel Particular dwChannel number
/// \param defaultHandler Using the default dmad interrupt handler.
//------------------------------------------------------------------------------
extern void DMAD_Initialize( uint32_t dwChannel, uint32_t defaultHandler )
{
    uint32_t dwStatus ;
    uint32_t dwFlag ;

    /* Enable peripheral clock */
    PMC_EnablePeripheral( ID_DMAC ) ;

    /* Read the dwChannel handler status to ensure the channel is a free channel */
    dwStatus = DMA_GetChannelStatus( DMAC ) ;
    TRACE_INFO( "DMAD_Initialize dwChannel %x  \n\r", dwChannel ) ;
    assert( (dwStatus & (1 << dwChannel)) == 0 ) ;

    /* Clear any pending interrupts on the channel */
    DMA_GetStatus( DMAC ) ;

    /* Disable the channel */
    DMA_DisableChannel( DMAC, dwChannel ) ;

    /* Disable the interrupt */
    dwFlag = 0x3FFFFF ;
    DMA_DisableIt( DMAC, dwFlag ) ;
    /* Enable DMA */
    DMA_Enable( DMAC ) ;

    if ( defaultHandler )
    {
        NVIC_EnableIRQ( DMAC_IRQn ) ;
    }

    // Initialize transfer instance.
    dmad.transfers[dwChannel].transferSize = 0;
}
Пример #4
0
//------------------------------------------------------------------------------
/// SPI DMA transfer ISR, Handle RX complete
//------------------------------------------------------------------------------
void SPI_D_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);
    }
        
}
Пример #5
0
//------------------------------------------------------------------------------
/// Initializes the DMA controller.
/// \param channel Particular channel number
/// \param defaultHandler Using the default dmad interrupt handler.
//------------------------------------------------------------------------------
void DMAD_Initialize(unsigned char channel, unsigned char defaultHandler)
{
    unsigned int status;
    unsigned int flag;
     
    // Enable peripheral clock
#if !defined(at91sam9rl64)    
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_HDMA;    
#endif    
    
    // Read the channel handler status to ensure the channel is a free channel.
    status = DMA_GetChannelStatus();
    TRACE_INFO ("DMAD_Initialize channel %x  \n\r", channel);
    SANITY_CHECK(!(status & (1 << channel)));
    // Clear any pending interrupts on the channel.
    DMA_GetStatus();
    // Disble the channel.
    DMA_DisableChannel(channel);
    // Disable the interrupt
    flag = 0xffffff;
    DMA_DisableIt(flag);
    // Enable DMA.
    DMA_Enable();
    if(defaultHandler) 
    {
        IRQ_ConfigureIT(AT91C_ID_HDMA, 0, DMAD_Handler);
        IRQ_EnableIT(AT91C_ID_HDMA);
    }
    // Initialize transfer instance.
    dmad.transfers[channel].transferSize = 0;
}
Пример #6
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 ) ;
            }
        }
    }
}
Пример #7
0
//------------------------------------------------------------------------------
/// Initializes the DMA controller.
/// \param channel Particular channel number
/// \param defaultHandler Using the default dmad interrupt handler.
//------------------------------------------------------------------------------
void DMAD_Initialize(U8 channel, U8 defaultHandler)
{
//	U32 status;
	U32 flag;
	
//	status = DMA_GetChannelStatus(); // Read the channel handler status to ensure the channel is a free channel.
//	DEBUG_MSG("DMAD_Initialize channel: %x, Status: %x", channel, status);
	DMA_GetStatus(); // Clear any pending interrupts on the channel.
	DMA_DisableChannel(channel); // Disble the channel.
	flag = 0xffffff;
	DMA_DisableIt(flag); // Disable the interrupt
	DMA_Enable(); // Enable DMA.
	if(defaultHandler) 
	{
		IRQ_PeriConf(21, 0, DMAD_Handler);
		IRQ_PeriEn(21);
	}
	dmad.transfers[channel].transferSize = 0; // Initialize transfer instance.
}
Пример #8
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.
			}
		}
	}
}
Пример #9
0
//------------------------------------------------------------------------------
/// Sends the contents of a data buffer a SSC peripheral, using the PDC. Returns
/// true if the buffer has been queued for transmission; otherwise returns
/// false.
/// \param ssc  Pointer to an AT91S_SSC instance.
/// \param buffer  Data buffer to send.
/// \param length  Size of the data buffer.
//------------------------------------------------------------------------------
unsigned char SSC_WriteBuffer(AT91S_SSC *ssc,
                                     void *buffer,
                                     unsigned int length)
{
#if !defined(CHIP_SSC_DMA)
    // Check if first bank is free
    if (ssc->SSC_TCR == 0) {

        ssc->SSC_TPR = (unsigned int) buffer;
        ssc->SSC_TCR = length;
        ssc->SSC_PTCR = AT91C_PDC_TXTEN;
        return 1;
    }
    // Check if second bank is free
    else if (ssc->SSC_TNCR == 0) {

        ssc->SSC_TNPR = (unsigned int) buffer;
        ssc->SSC_TNCR = length;
        return 1;
    }
#else

    unsigned short* startSourceAddr;
    unsigned short* startDestAddr;
    unsigned int srcAddress;
    unsigned int destAddress;
    unsigned int buffSize;
    unsigned int LLI_rownumber = 0;

    startSourceAddr = (unsigned short*)(buffer);
    startDestAddr = (unsigned short*)(&ssc->SSC_THR);
    srcAddress  = (unsigned int)startSourceAddr;    // Set the data start address
    destAddress = (unsigned int)startDestAddr;
    buffSize = length;
    if(buffSize > 0x8000){
        TRACE_WARNING("SSC DMA, size too big %d\n\r", buffSize);
        buffSize = 0x8000;
    }

    // Set DMA channel DSCR
    DMA_SetDescriptorAddr(BOARD_SSC_DMA_CHANNEL, (unsigned int)&LLI_CH[0]);

    // Clear any pending interrupts
    DMA_GetStatus();

    //Set DMA channel control B
    DMA_SetSourceBufferMode(BOARD_SSC_DMA_CHANNEL, DMA_TRANSFER_LLI,
                            (AT91C_HDMA_SRC_ADDRESS_MODE_INCR >> 24));
    DMA_SetDestBufferMode(BOARD_SSC_DMA_CHANNEL, DMA_TRANSFER_LLI,
                            (AT91C_HDMA_DST_ADDRESS_MODE_FIXED >> 28));
    DMA_SetFlowControl(BOARD_SSC_DMA_CHANNEL, AT91C_HDMA_FC_MEM2PER >> 21);

    // Set DMA channel config
    DMA_SetConfiguration(BOARD_SSC_DMA_CHANNEL, BOARD_SSC_DMA_HW_SRC_REQ_ID \
                                        | BOARD_SSC_DMA_HW_DEST_REQ_ID \
                                        | AT91C_HDMA_SRC_H2SEL_SW \
                                        | AT91C_HDMA_DST_H2SEL_HW \
                                        | AT91C_HDMA_SOD_DISABLE \
                                        | AT91C_HDMA_FIFOCFG_LARGESTBURST);

    // Set link list
    while(srcAddress < ((unsigned int)(startSourceAddr + buffSize)))
    {
        if(((unsigned int)(startSourceAddr + buffSize)) - srcAddress <= (BOARD_SSC_DMA_FIFO_SIZE) )
        {
            AT91F_Prepare_Multiple_Transfer(BOARD_SSC_DMA_CHANNEL, LLI_rownumber, LAST_ROW,
                                        srcAddress,
                                        destAddress,
                                        (((((unsigned int)(startSourceAddr + buffSize))
                                                - srcAddress)/2)
                                                  | AT91C_HDMA_SRC_WIDTH_HALFWORD
                                                  | AT91C_HDMA_DST_WIDTH_HALFWORD
                                                  | AT91C_HDMA_SCSIZE_1
                                                  | AT91C_HDMA_DCSIZE_1
                                                      ),
                                        ( //| AT91C_HDMA_DST_DSCR_FETCH_FROM_MEM
                                         AT91C_HDMA_DST_DSCR_FETCH_DISABLE
                                        | AT91C_HDMA_DST_ADDRESS_MODE_FIXED
                                        | AT91C_HDMA_SRC_DSCR_FETCH_FROM_MEM
                                        //| AT91C_HDMA_SRC_DSCR_FETCH_DISABLE
                                        | AT91C_HDMA_SRC_ADDRESS_MODE_INCR
                                        | AT91C_HDMA_FC_MEM2PER));
        }
        else
        {
            AT91F_Prepare_Multiple_Transfer(BOARD_SSC_DMA_CHANNEL, LLI_rownumber, 0,
                                        srcAddress,
                                        destAddress,
                                        ((BOARD_SSC_DMA_FIFO_SIZE)/2
                                            | AT91C_HDMA_SRC_WIDTH_HALFWORD
                                            | AT91C_HDMA_DST_WIDTH_HALFWORD
                                            | AT91C_HDMA_SCSIZE_1
                                            | AT91C_HDMA_DCSIZE_1
                                                ),
                                        ( //| AT91C_HDMA_DST_DSCR_FETCH_FROM_MEM
                                        AT91C_HDMA_DST_DSCR_FETCH_DISABLE
                                        | AT91C_HDMA_DST_ADDRESS_MODE_FIXED
                                        | AT91C_HDMA_SRC_DSCR_FETCH_FROM_MEM
                                        //| AT91C_HDMA_SRC_DSCR_FETCH_DISABLE
                                        | AT91C_HDMA_SRC_ADDRESS_MODE_INCR
                                        | AT91C_HDMA_FC_MEM2PER));

        }

        srcAddress += BOARD_SSC_DMA_FIFO_SIZE;

        
        LLI_rownumber++;
    }
#endif
    // No free banks
    return 0;
}