Hello,
There are two types of linking channels: on Minor loop or on Major loop completion.
Basically, for this example, you need to link channels every time that 1 result from ADC is obtained, in this case, channel will be linked to move the next data to be converted, so you will need to user the Minoor Loop linking method.
This linking mode is configured in CITER/BITER registers:

In this case, in your previous example, you were setting ELINK mask but LINKCH was set to zero, so, in every minor loop, you were triggering channel 0. That is why you needed to use channel 0 + other channel to get this example working.
This can be solved by using two MACROs that defines the channels to be used and then write to CITER/BITER registers as follows (pay special attention to LINKCH field):
DMA0->TCD[SECOND_DMA_CHANNEL].CITER_ELINKYES = DMA_CITER_ELINKYES_ELINK_MASK |
DMA_CITER_ELINKYES_LINKCH(FIRST_DMA_CHANNEL) |
DMA_CITER_ELINKYES_CITER(0x0C);
DMA0->TCD[SECOND_DMA_CHANNEL].BITER_ELINKYES = DMA_BITER_ELINKYES_ELINK_MASK |
DMA_BITER_ELINKYES_LINKCH(FIRST_DMA_CHANNEL) |
DMA_BITER_ELINKYES_BITER(0x0C);
I adapted your project to use any DMA channel that is defined in FIRST_DMA_CHANNEL and SECOND_DMA_CHANNEL. I am attaching full dma.c file.
I hope this can help you!
Regards,
Isaac