//------------------------------------------------------------------------------ //./ 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 ); }
//------------------------------------------------------------------------------ /// 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; }