cancel
Showing results for 
Search instead for 
Did you mean: 

DMA line output is one more cycle than expected

MDrac.1
Associate III

Hi,

I'm trying to control multiple PWM signals simultanously using DMA (used for controlling LED drivers). However I'm having an issue I can't seem to trace, one of the lines puts out an additional PWM signal cycle that shouldn't be there, this is weird since all the lines are basically using the same routines and interrupt functions. I've added screenshots that should explain it better. The output is associated with Tim1_Ch1, DMA2_St1 which isn't the lowest priority of the used streams (so it can't be due to some interference delay).

My code can be found here: https://github.com/maksimdrachov/F429-UCS5603A

(All the most relevant functions can be found in /Core/Src/ucs5603a.c)

Anyone an idea what could be the cause of this?

3 REPLIES 3

Explain the logic behind that waveform. What is supposed to stop the PWMs?

JW

MDrac.1
Associate III

Well, it's this concept but applied to a slightly different LED driver so the timings are different.

Normally as the output for each sequential LED driver is put out the LedCounter increases and eventually it puts the PWM signal to zero thereby 'stopping' the transmission of data.

void Set_PwmData(uint8_t LedData_p[][4], uint32_t * PWM_Data_p, uint8_t * LedCounter, uint16_t PwmCounter, TIM_HandleTypeDef *htim, uint32_t Channel)
{
	uint64_t color;
 
	if (*LedCounter < MAX_LED)
	{
		color = ((LedData_p[*LedCounter][1]<<24) | (LedData_p[*LedCounter][2]<<12) | (LedData_p[*LedCounter][3]));
		for (int i=35; i >=0; i--)
		{
			PWM_Data_p[PwmCounter] = PWM_LO << ( (color&(1<<i)) > 0 );
			PwmCounter++;
		}
	}
	else
	{
		if (*LedCounter < MAX_LED+3)
		{
			for (int i = 35; i>=0; i--)
			{
				PWM_Data_p[PwmCounter] = 0;
				PwmCounter++;
			}
		}
		else
		{
			*LedCounter = 0;
			HAL_TIM_PWM_Stop_DMA(htim, Channel);
		}
	}
}

This works correctly for every line, except one, which I find quite confusing since they are all using the same functions (and should all output the same amount of data). Therefore I don't think it's the code that's wrong (also I've used the same code for another similar LED driver which worked correctly, only thing that changed is 8bit->12bit for setting the current more accurately). Before when I was having a similar problem it was caused by the interrupt functions not executing fast enough and therefore some lines not being put to zero as quick as necessary (this was solved by turning on the optimisation level). This is not the case here because then the lowest priority line would be the one that shows irregularities, but this line isn't lowest priority. So I'm unsure what could cause this kind of behavior anymore?

> This is not the case here because then the lowest priority line would be the one that shows irregularities,

Not necessarily.

The standard debugging techique in cases like this is to toggle a GPIO pin in the related ISR and observe together with the output waveform.

You may also want to consider using the DMAR/DCR mechanism, where a single DMA triggered by Update event can update all 4 CCRx registers at once.

JW