2021-09-17 07:38 AM
Hi there,
First time working with DMA here and I'm getting data loss when the frequency of a PWM signal is varied during the DMA reading. The DMA request is triggered by a 16MHz clock. I'm using DMA2 on STM32f429zi.
The DMA direction is peripheral to memory, where I try to read the whole GPIO port E to memory. The data loss is clearly visible in the beginning of the DMA reading when the PWM frequency is changed. If I comment out the code with the varying of PWM frequency (see part of the code below), there is no visible data loss in the DMA reading.
You can see in the attached image that the upper plot loses data points of the sine wave (4 points per period) and in the lower plot there is no data loss.
As I understand, DMA should work independently and not be affected by CPU, but for me it seems to not be the case. Could this be due to working with a too high clock frequency? Or am I missing something else? I'm really stuck on this problem, any help is appreciated.
Regards,
Linda
/*------------------- Comment out when not changing PWM frequency --------------------------------------------------------------------*/
// /* Start 40 MHz */
// TIM3->CCR1 = 1; // 40 MHz
/*------------------------------------------------------------------------------------------------------------------------------------*/
/* Start DMA for ping signal with length BUFFER_SIZE (PA9 (channel 2) is clockout+ of ADC, sampling on falling edge of PA9) */
if (HAL_DMA_Start_IT(htim1.hdma[TIM_DMA_ID_CC2], (uint32_t)&(GPIOF->IDR), (uint32_t)&aDST_Buffer, BUFFER_SIZE) != HAL_OK)
{
/* Transfer Error */
Error_Handler();
}
/*------------------- Comment out when not changing PWM frequency --------------------------------------------------------------------*/
// /* Continue while timer is lower than 1,3 us */
// while (__HAL_TIM_GET_COUNTER(&htim5) - timer_val1 < 13)
// {
// }
// /* Start ping, 4 MHz */
// TIM3->ARR = 20; // period
// TIM3->CCR1 = 9; // pulse
// timer_val1 = __HAL_TIM_GET_COUNTER(&htim5);
// while (__HAL_TIM_GET_COUNTER(&htim5) - timer_val1 < 9) // 5 pulses
// {
// }
//
// TIM3->ARR = 1; // 40Mhz
// TIM3->CCR1 = 1;
// while (__HAL_TIM_GET_COUNTER(&htim5) - timer_val1 < 25)
// {
// }
/*------------------------------------------------------------------------------------------------------------------------------------*/
2021-09-17 08:29 AM
> The data loss is clearly visible in the beginning of the DMA reading when the PWM frequency is changed
How is it clearly visible? Am I supposed to know what's on the IDR lines here? Why is the reading negative?
Trying to perform a DMA transfer at 40 Msps is unlikely to work. I imagine the limit on the STM32F4 is somewhere shy of 10 Msps.
2021-09-20 02:19 AM
The data transferred from the IDR line is a sine wave signal, where there should be 4 samples per period. The data loss is seen when there's only 3 samples per period, believing that one sample point is lost. The reading is negative since it's signed bits sent directly from the ADC.
The DMA transfer is performed at 16MHz. The weird thing is that the DMA reading seems to work only when nothing else is done in the code in the same time.
2021-09-20 04:06 AM
> The DMA request is triggered by a 16MHz clock. I'm using DMA2 on STM32f429zi.
How do you trigger DMA2 from TIM3?
Output PWM from some suitable channel from the timer which triggers the DMA, and observe to see the effect of changing ARR.
> DMA should work independently and not be affected by CPU
It *is* affected by bus collisions, though. The DMA does not operate in "vacuum".
JW
2021-09-20 06:42 AM
Might be able to increase speed a bit by setting it to half-word transfers and enabling the FIFO. You're just running into bandwidth issues though.
2021-09-20 08:32 AM
DMA2 is triggered by an input capture signal from the ADC, not TIM3. TIM3 is just generating a PWM.