Can't link DMA descriptors with Atmel Start

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

 

I'm starting a new project. I decided to go for Atmel Start but it seems that there a "bug" in the DMA driver.

 

According to the SAMC21 datasheet, the DMA has 2 areas (descriptor and write back) for descriptors. The first descriptor of each available channel is stored in descriptor area. Therefore, in case I need 2 descriptors for one DMA channel, I just need to link the first one with one I created anywhere in RAM with the proper memory alignment. However, this is not possible with Atmel Start as it uses another channel's descriptor to do so and therefore this channel cannot be used anymore. In ASF 3.49, it was possible:

 

Atmel Start code to link a descriptor:

int32_t _dma_set_next_descriptor(const uint8_t current_channel, const uint8_t next_channel)
{
	hri_dmacdescriptor_write_DESCADDR_reg(&_descriptor_section[current_channel],
	                                      (uint32_t)&_descriptor_section[next_channel]);

	return ERR_NONE;
}

Here you can see that it uses "_descriptor_section[next_channel]" variable to link to the first descriptor which means that this "next_channel" (whatever value it has) cannot be used anymore otherwise the newly set descriptor will be overwritten.

 

ASF code to link a descriptor:

enum status_code dma_add_descriptor(struct dma_resource *resource,
		DmacDescriptor* descriptor)
{
	DmacDescriptor* desc = resource->descriptor;

	if (resource->job_status == STATUS_BUSY) {
		return STATUS_BUSY;
	}

	/* Look up for an empty space for the descriptor */
	if (desc == NULL) {
		resource->descriptor = descriptor;
	} else {
		/* Looking for end of descriptor link */
		while(desc->DESCADDR.reg != 0) {
			desc = (DmacDescriptor*)(desc->DESCADDR.reg);
		}

		/* Set to the end of descriptor list */
		desc->DESCADDR.reg = (uint32_t)descriptor;
	}

	return STATUS_OK;
}

as you can see if no descriptor is set, it sets it as the first one. It will be copied into "descritor_section" when DMA transfer is started. If first descriptor is set, it finds the last one and links the new one with it.

 

In my project I need 8 DMA channels with 2 linked descriptors. With Atmel Start, this setup is not possible however it is with ASF 3.49. How to make the required setup possible with Atmel Start?

 

Thanks for you help

Hugo

Last Edited: Tue. Jan 25, 2022 - 07:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suppose you could still use that flawed API provided the array here 

/* Section containing first descriptors for all DMAC channels */
COMPILER_ALIGNED(16)
DmacDescriptor _descriptor_section[DMAC_CH_NUM] SECTION_DMAC_DESCRIPTOR;

is made big enough for your use case, so 16 rather than DMAC_CH_NUM (which is 12 for C21 I think).

next_channel

in the range 8-15 would then be used for the 2:nd descriptor. Or just write your own version of set_next_descriptor that takes an address rather than an index.
/Lars
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Lars,

 

Thanks for your answer but I wanted to avoid modifying the ASF4 source code which will be overwritten if I need to modify my Atmel Start project and reimport it to apply the modifications.

 

I don't think I have another option but modifying the ASF4 source code but if someone has another idea I'm open. Otherwise, is there a possibility to suggest modifications of the ASF4 framework to Microchip so they make this modification themselves which will make it available to everyone and will avoid modified ASF4 source code to be overwritten on reimport of an Atmel Start project?

 

Thanks,

Hugo