AnsweredAssumed Answered

Pausing/resuming DMA in descriptor array mode on BF561

Question asked by CannonFodder on Jun 22, 2011
Latest reply on Aug 4, 2011 by Prashant

Hi,
I'm trying to use Descriptor Array mode to DMA in and demultiplex variable sized packets of data coming into the PPI port of the BF561

However I'm having an issue getting the DMA to resume after being paused.

 

Each packet starts with a fixed sized header which defines the type of packet and its size.


I'm attempting to define an array of descriptors of the form

Header 
Packet
Header
Packet
...etc

 

When a header is DMA'd in I'd want to inspect the packet size and update the X_COUNT to match the
size of the next packet of data.

 

The form of descriptor being used is as follows:-

#pragma pack(2)
typedef struct {

void *start_addr;
uint16 dma_cfg;
uint16 x_count;
} ppi_dma_desc_t;
#pragma pack()

 

The descriptor array is initialised as follows:-

 

section ("sdram_bank3") static ppi_dma_desc_t m_desc_array1[MAX_DESCRIPTORS];

for(desc_entry = 0U; desc_entry < MAX_DESCRIPTORS;) {

desc_array[desc_entry].start_addr = ppiHeader;
desc_array[desc_entry].x_count = sizeof(ppiHeader) / 4U;
desc_array[desc_entry++].dma_cfg = DMA_FLOW_DESC_ARRAY | DMA_NDSIZE(4U) | WDSIZE_32 | WNR | DMAEN | DI_EN;
  
desc_array[desc_entry].start_addr = dest[dest_entry];
desc_array[desc_entry].x_count = (DEFAULT_PACKET_SZIE - sizeof(ppiHeader)) / 4U;
desc_array[desc_entry].dma_cfg = DMA_NDSIZE(4U) | WDSIZE_32 | WNR;
desc_entry ++;
}

 

An interrupt is generated on DMA completion of the header and the FLOW is set to 0 for the next descriptor to pause the DMA until it's restarted.

 

The initial DMA is kicked off as follows:-

*pPPI0_CONTROL = PPI_XFR_NON_ITU656 | PPI_NO_EXT_SYNC | PPI_FLDSEL_EXT_TRIG |  PACK_EN | DMA32;

*pDMA1_0_X_COUNT = desc_array[0].x_count;
*pDMA1_0_Y_COUNT = 0U;
*pDMA1_0_X_MODIFY = 4U; 
*pDMA1_0_Y_MODIFY = 1U;
*pDMA1_0_NEXT_DESC_PTR = 0U;
*pDMA1_0_CURR_DESC_PTR = desc_array;
ssync();

/*
** Start transfer.
*/
*pDMA1_0_CONFIG = desc_array[0].dma_cfg;
ssync();
*pPPI0_CONTROL |= PORT_EN;
ssync();


The intention is to restart the DMA during the interrupt handler;
The interrupt handler is as follows:-

#ifdef VDK_REENTRANT_ISR
EX_REENTRANT_HANDLER(EVT_IVG8_Entry)
#else
EX_INTERRUPT_HANDLER(EVT_IVG8_Entry)
#endif
{
ppi_dma_desc_t * descPtr = NULL;

/* Insert your ISR code here */
ssync();

descPtr = *pDMA1_0_CURR_DESC_PTR;

*pDMA1_0_X_COUNT = ppiHeader[packetSize] / 4U; //Update count to what's in the header

*pDMA1_0_CONFIG |= DMA_FLOW_DESC_ARRAY;

*pDMA1_0_CONFIG |= DMAEN; //Renable DMA


*pDMA1_0_IRQ_STATUS |= DMA_DONE; //Acknowledge the interrupt. Register is a Write-1-to-Clear

}


Inspection of the DMA registers once inside the interrupt handler indicate that the next descriptor has been loaded but not yet executed.
So I just need to get it going but I'm not having any luck.

I've referred to BF561 Hardware Reference Section 9 and figures 9-15 & 9-16.

Any ideas as to what I'm doing wrong?
Is this approach way off the mark?

Regards.

Outcomes