cancel
Showing results for 
Search instead for 
Did you mean: 

How do you know the data transferred from Memory into peripheral has been fully sent VIA DMA into the real world.

CLeo.1
Senior II

I've always been curious to know if there was a method to find out the data transferred via the DMA into the peripheral has been sent out probably.

For example a Timer

All it does is

  1. Create an array with varying CCR1 values (Duty Cycles)
  2. Once done, enable the DMA to start transferring the CCR1 values from the array into the peripheral
  3. Then from here I monitor the DMA Transfer Complete flag, however this just tells you the DMA is done, but how do I know the peripheral is done sending out the data into the real world? if that makes any sense

Code:

Create the Array

uint32_t RGB = GREEN << 16 | RED << 8 | BLUE;
 
	wait();
 
	LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_4, ((offset * 24) + 50));
	for (uint32_t LED = 0; LED < offset; LED++) {
 
		if ((offset - 1) == LED) {
 
			for (int bit = 23 + ((int)LED * 24); bit >= 0 + ((int)LED * 24); bit--) {
 
				if ((RGB) & (1 << ((23 + (LED * 24)) - bit))) {
 
					WS28128B_BUFF[bit] = 0xC0;
				} else {
					WS28128B_BUFF[bit] = 0x60;
				}
			}
 
		} else {
 
			for (int bit = 23 + ((int)LED * 24); bit >= 0 + ((int)LED * 24); bit--) {
 
				WS28128B_BUFF[bit] = 0x60;
			}
		}
	}
 
	for (uint32_t RESET_LINE = (offset * 24); RESET_LINE < ((offset * 24) + 50); RESET_LINE++) {
		 WS28128B_BUFF[RESET_LINE] = 0x00;
	}

Enable DMA and Peripheral

LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_4);
	LL_TIM_EnableCounter(TIM15);
	WS2812B::block = true;

Once DMA Transfer Flag complete flag is done disable

extern "C" void DMA1_Stream4_IRQHandler() {
 
	LL_DMA_ClearFlag_TC4(DMA1);
	LL_TIM_DisableCounter(TIM15);
	WS2812B::block = false;
}

Can I trust the DMA flag, when its set for the data to be sent out to the real world or do I need to now rely on a flag within the TIMER peripheral to do that?

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

The DMA TC flag indicates the data has been transferred to the peripheral, but not that the peripheral is "done" with it. You would need to wait another timer update cycle for this to happen and there's no super clean way of doing it.

An alternative is to add an additional dummy byte at the end of the buffer that doesn't affect the stream (i.e. CCR value for 0% duty cycle) and interrupt during that byte (at the TC flag). Double check on a scope, you may need two dummy bytes.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

4 REPLIES 4
TDK
Guru

The DMA TC flag indicates the data has been transferred to the peripheral, but not that the peripheral is "done" with it. You would need to wait another timer update cycle for this to happen and there's no super clean way of doing it.

An alternative is to add an additional dummy byte at the end of the buffer that doesn't affect the stream (i.e. CCR value for 0% duty cycle) and interrupt during that byte (at the TC flag). Double check on a scope, you may need two dummy bytes.

If you feel a post has answered your question, please click "Accept as Solution".
CLeo.1
Senior II

Is there no more of a definitive way to know if the peripheral is "done"? For example for let say UART, cant really send empty bytes into it like you can with the TIMER.

Usually there is a way, but it's peripheral specific. UART has the BUSY or IDLE flag to do so.
If you feel a post has answered your question, please click "Accept as Solution".

Ah I see fair enough, or I guess the "TC" Flag in the UART. Thank you for the explanation