Linked list multi block DMA transfer with DAVE 4 / XMCLib

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
Hi,

I am trying to copy data from multiple memory locations into a contiguous address space using DMA.
As a first step I want to copy data from one memory location to another.
Therefore, I am trying to set up a DMA multi block transfer with linked list in DAVE 4.

I try to apply the instructions given for DAVE 3 in the tutorial under http://www.infineonforums.com/threads/1763-XMC_HOT-XMC4500-How-to-do-Multi-BLK-DMA-transfer-%28SRC-L... on DAVE4 / XMCLib.

I created a DMA_CH app in DAVE 4. Single block transfer was working fine.

Afterwards, I changed the app configuration to the following settings:
transfer type setting: "Multi-block: source address linked , destination address reload."
destination address: "dst_ptr_0" (a pointer to the destination array
linked list pointer: "list_ptr_0" (a pointer to the first linked list entry of type "XMC_DMA_LLI_t"
All channel transfer events are enabled in the "Event Settings" panel.


The source array "Dma_source" is filled with numbers in ascending order.


XMC_DMA_LLI_t __attribute__((aligned(32))) list_0, list_1, list_2;

.....
/* Configure DMA */
DMA_CH_t *pDma_ch;
XMC_DMA_t *pDma;
pDma_ch = &DMA_CH_0;
pDma = DMA_CH_0.dma_global->dma;

// list 0
list_0.src_addr = (uint32_t ) &Dma_source[16]; // Source address
list_0.dst_addr = (uint32_t ) &Dma_result[0]; // Destination address

//list_0.control = ?? // How to set this?

list_0.block_size = 8; // Transfer block size
list_0.llp = &list_1; // Pointer to next list entry

// list 1
list_1.src_addr = (uint32_t) &Dma_source[8];
list_1.dst_addr = (uint32_t) &Dma_result[16];

//list_1.control = ??

list_1.block_size = list_0.block_size;
list_1.llp = &list_2;

// list 2
list_2.src_addr = (uint32_t) &Dma_source[0];
list_2.dst_addr = (uint32_t) &Dma_result[32];

//list_2.control = ??

list_2.block_size = list_0.block_size;;
list_2.llp = NULL; // according to DAvE 3 tutorial, the last entry must point to 0x0000


XMC_DMA_CH_SetLinkedListPointer(pDma, 0, &list_0);
DMA_CH_Init( &DMA_CH_0 ); // init here, not in Dave_Init()


With the code above, DMA is copying data, but
- the callback function is never executed
- source address pointer is increased continously, and not according to the linked list configuration


I suspect this behaviour might be because the control register value is not configured in my code. In the DAVE3 tutorial, this configuration is copied from the global app configuration.
Unfortunately, I could not figure out, how to do this using the DAVE4 / XMCLib API that I am using.

Did anybody do this before and can give me a hint / code example?

Kind regards,
Christian
0 Likes
4 Replies
Travis
Employee
Employee
First solution authored Welcome! 500 replies posted
Hi csuel,

you did not set the control parameters of the linked list. The control parameters refers to the control register high and low, without this parameters means that nothing is configured into control register high and low.

Please reference from previous GPDMA Linked list example as shown below.


void Make_LinkedList (void)
{

DMA002_Handle0.DMAChRegs->LLP = (uint32_t)&LLI0;

/**************************************************
* Make Linked List 0
***************************************************/
LLI0.sar = (uint32_t)(&source_buffer_2);
LLI0.dar = (uint32_t)(&destination_buffer);
LLI0.llp = (uint32_t)(&LLI1); // Pointer to next link list

LLI0.ctl_l = DMA002_Handle0.DMAChRegs->CTLL;
LLI0.ctl_h = DMA002_Handle0.DMAChRegs->CTLH;


/**************************************************
* Make Linked List 1
***************************************************/
LLI1.sar = (uint32_t)(&source_buffer_1);
LLI1.dar = (uint32_t)(&destination_buffer);
LLI1.llp = (uint32_t)(&LLI2); // Pointer to next link list
LLI1.ctl_l = DMA002_Handle0.DMAChRegs->CTLL;
LLI1.ctl_h = DMA002_Handle0.DMAChRegs->CTLH;


/**************************************************
* Make Linked List 2 (Last LLI)
***************************************************/
LLI2.sar = (uint32_t)(&source_buffer_0);
LLI2.dar = (uint32_t)(&destination_buffer);
LLI2.llp = 0x0000; // set to 0 for last LLI
LLI2.ctl_l = DMA002_Handle0.DMAChRegs->CTLL;
LLI2.ctl_h = DMA002_Handle0.DMAChRegs->CTLH;



}


Best Regards
Travis
0 Likes
User11706
Level 2
Level 2
Hello Gents,

I have the same problem, and Travis answer does not help.
The latest DMA app (Dave 4) does nor have members ctl_l and ctl_h , but rather :

typedef struct XMC_DMA_LLI
{
uint32_t src_addr; /**< Source address */
uint32_t dst_addr; /**< Destination address */
struct XMC_DMA_LLI *llp; /**< Linked list pointer of type XMC_DMA_LLI_t */
union
{
struct
{
uint32_t enable_interrupt: 1; /**< Enable interrupts? */
uint32_t dst_transfer_width: 3; /**< Destination transfer width */
uint32_t src_transfer_width: 3; /**< Source transfer width */
uint32_t dst_address_count_mode: 2; /**< Destination address count mode */
uint32_t src_address_count_mode: 2; /**< Source address count mode */
uint32_t dst_burst_length: 3; /**< Destination burst length */
uint32_t src_burst_length: 3; /**< Source burst length */
uint32_t enable_src_gather: 1; /**< Enable source gather? */
uint32_t enable_dst_scatter: 1; /**< Enable destination scatter? */
uint32_t : 1; /**< Reserved bits */
uint32_t transfer_flow: 3; /**< DMA transfer flow */
uint32_t : 4; /**< Reserved bits */
uint32_t enable_dst_linked_list: 1; /**< Enable destination linked list? */
uint32_t enable_src_linked_list: 1; /**< Enable source linked list? */
uint32_t : 3; /**< Reserved bits */
} cs;
uint32_t control;
} cu;
uint32_t block_size; /**< Transfer block size */
uint32_t src_status; /**< Source status */
uint32_t dst_status; /**< Destination status */
} XMC_DMA_LLI_t;

How shall we set cu.control , block_size, src_status and dst_status members ?

Jorge

Is there any example somewhere ?
0 Likes
lock attach
Attachments are accessible only for community members.
jferreira
Employee
Employee
10 sign-ins 5 sign-ins First like received
Hi,

Please look at the attached example.
The example copies four non consecutive set of data to a linear array using linked list. Bear in mind that this example can be done more elegantly using the gather functionality.

Regards,
Jesus
0 Likes
lock attach
Attachments are accessible only for community members.
Eric1
Employee
Employee
Hi,

Here is another example to copy with the GDMA from a pheripheral to memory via linked list.
Regards
Eric


* This example shows a DMA transfer from VADC to an array.
* With a CCU8 trigger the sampling of 2 Pins is started (P15.3, P15.2, @10kHz).
* The Result is stored in an array of 16 elements. The order is A,B,A,B.
*
* To enlarge the time between 2 transfers 4 channels instead of 2 channels are used.
* The additional 2 channels are also connected to P15.3 and P15.2. (VADC Alias feature)
* But have their own result registers.
* The 4th result generates an DMA trigger where all 4 results are stored in an array.
*
* The DMA is configured as list with 3 elements. After the 3th transfer is completed an interrupt occurs.
* The ISR "GPDMA0_0_IRQHandler" in global_dma_conf.c checks the correct interrupt and calls the function "user_event_handler".
*
* For debugging purpose the the function "user_event_handler" disables the DMA, provide a breakpoint and enable the DMA again.
*
* Function reinit_ADC() is called as workaround for errata ADC_CM.001
0 Likes