cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H747 (M7) – TIM3 CH4 PWM with DMA produces discontinuous/glitchy waveform for addressable LEDs

hello everybody

 

I am programming 10 addressable Leds with PWM with DMA using the M7 cortex of an STM32H747 in a custom board.
Characteristics:

  • Clocks: SysClk 480 MHz, TIM kernel clock 240 MHz
  • Timer: TIM3, Channel 4, internal clock
  • PWM base frequency: ~770 kHz (period ≈ 1.3 µs).
  • ARR: 312‑1 (312 ticks → 240 MHz/312 ≈ 769.23 kHz).
  • DMA: Peripheral = TIM3_CCR4, Memory in RAM_D2, half‑word alignment (16‑bit duty), MemInc enabled, PeriphInc disabled, Mode = Normal.

What works

If I run the timer alone (fixed duty), the PWM is correct and stable.

The problem

When I enable PWM + DMA, the waveform becomes random/discontinuous. On the oscilloscope I see “splits” and gaps; the PWM is not continuous. For example, the first 8 bits might be high and the following 16 low (intended to represent RED), but the stream breaks unpredictably. The data buffer looks correct when inspected in the debugger.

The configuration

massimoperdigo_1-1770313239202.jpeg

massimoperdigo_0-1770313226371.png
I am using channel 4 timer 3. with internal clock source.
and DMA is configured as:

massimoperdigo_2-1770313264550.png

where data width is half word since the pulse of the PWM generator channel 4 is 16 bit value.

Here is my code. All IRQs are activated.

#define NUMTOTALLEDS         10
#define NUMCOLORS            24 //< 8 BYTESxCOLOUR
#define STARTSAFEBUFFER      50 
#define ENDSAFEBUFFER        50 
 
// Placed in RAM_D2
uint16_t pwmData[NUMCOLORS*NUMTOTALLEDS+STARTSAFEBUFFER+ENDSAFEBUFFER];

const 
uint16_t ALLRED [340] = {
// Start safe buffer
PWM_RESET, PWM_RESET, PWM_RESET ...
// 8 bits high + 8 bits low + 8 bits low (Red, gren, blue)
PWM_HIGH, PWM_HIGH, PWM_HIGH, PWM_HIGH, PWM_HIGH, PWM_HIGH, PWM_HIGH, PWM_HIGH, PWM_LOW, PWM_LOW, PWM_LOW, PWM_LOW, PWM_LOW, PWM_LOW, PWM_LOW, PWM_LOW, PWM_LOW, PWM_LOW, PWM_LOW, PWM_LOW, PWM_LOW, PWM_LOW, PWM_LOW, PWM_LOW,
// End safe buffer
... PWM_RESET, PWM_LOW, PWM_LOW};

// First of all i cpy a static buffer with all the information to fill 10 leds in red
memcpy(pwmData, ALLRED, sizeof(pwmData));

// Then
 if (HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_4 , (uint32_t *)pwmData, sizeof(pwmData)) == HAL_OK) {
// It returns Ok always
}

// Callback
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
    HAL_TIM_PWM_Stop_DMA(&htim3, TIM_CHANNEL_4);
}

Everything is normal to me, but this is what my oscilloscope gets:

massimoperdigo_3-1770313742894.jpeg

with zoom (the first 8 bits are high, and the 16 folowing are low, meaning red colour (RGB)):

massimoperdigo_4-1770313840348.png

My problem is that the PWM is random, and never correct.
What can I do?
Thanks in advance,

3 REPLIES 3
Slawekkac
Associate II

Hi,

Change in configuration in DMA for Memory from HalfWord to Byte. Do not change for Peripheral. Also change buffer pwmData and ALLRED from uint16_t to uint8_t.

Best Regards.

Yeah,

i tried so, however i do not why (maybe is a bug) both memory an peripheral must have the same length. I mean, the GUI forces the memory size to be equal to peripheral…

 

Hi,

Change in the generated code, not in GUI. Only for test.