cancel
Showing results for 
Search instead for 
Did you mean: 

PWM on non PWM pin

I need to generate PWM on a non-PWM pin

I know one method is to use an ISR triggered by a timer, but because I need to run the PWM at 10kHz, this will put a huge load on the CPU just to toggle 1 pin.

I've seen examples of using DMA to send data to the BSRR e.g.

https://github.com/mnemocron/STM32_PatternDriver

But following this example, on my STM32F407, the DMA does not seem to send a single transfer to the BSRR register, as the pin does not change

0693W00000SvG8WQAV.png 

0693W00000SvG8gQAF.png 

   const int dimingTableSize = 100;

   uint32_t dimingPattern[dimingTableSize];

   memset(dimingPattern,0x00, dimingTableSize * sizeof(uint32_t));

   dimingPattern[0] = GPIO_PIN_8;// set pin 8

   dimingPattern[50] = GPIO_PIN_8 << 16;// reset pin 8

   HAL_DMA_Start(&hdma_tim2_ch2_ch4, (uint32_t)dimingPattern, (uint32_t)&(GPIOD->BSRR), dimingTableSize);

   HAL_TIM_Base_Start(&htim2);

   HAL_TIM_OC_Start(&htim2, TIM_CHANNEL_2);

   //TIM2->DIER |= (1 << 8);  // set UDE bit (update dma request enable)

   __HAL_TIM_ENABLE_DMA(&htim2, TIM_DMA_CC2);

I've tested the array and BSRR part simply using a for() loop to send the array, and the pin clearly toggles.

However using DMA, even if I set the first index in the array to set the pin, the pin remains reset, which indicates the DMA has done a single transfer

Can anyone see what I've done wrong.

BTW. I've tried other timers and other channels, but it didn't make any difference

7 REPLIES 7
Javier1
Principal

https://community.st.com/s/question/0D53W00000trZY8SAM/software-pwm-best-approach

i have tested this in f103 f072 f105 and f205, it should work in yours too

https://www.hackster.io/javier-munoz-saez/all-pins-as-pwm-at-the-same-time-baremetal-stm32-1df86f

we dont need to firmware by ourselves, lets talk
Javier1
Principal

also i just noticed your DMA is set peripheral to memory and it should be mem to peripheral.

you want the DMA to take values froma buffer and place them in the BSRR register of the GPIO peripheral dont you?

we dont need to firmware by ourselves, lets talk

You can't use DMA1 to transfer to/from GPIO in 'F4.

http://www.efton.sk/STM32/gotcha/g30.html

JW

Thanks

Using DMA1 was the problem.

I know in the images I posted that the DMA was also set to Peripheral to Memory, I had already tried the opposite direction, and that didn't work either

I also had to use Timer 1, because TIM1 or TIM8 seem to be the only timers that can trigger DMA2.

In my case I could not seem to use TIM8 becuase of a NVIC conflict, possibly with the UART.

Anyway. Timer 1, CH 1, no output to physical pin, is now working.

@STM

I think you should fix the bug in the STM32 Cube which allows use of Timers other than TIM1 and TIM8 for DMA to peripherals, because on the other timers appear to all use DMA1 which can't communicate with peripherals

DMA1 here can work with peripherals on APB1, notably the source of the request.

DMA2 primarily with APB2 peripherals, bus also via memory to memory modes to third party destinations like peripherals on AHB.

It's documented behaviour, that autogen tools miss the nuances of use cases is unfortunate.​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

> In my case I could not seem to use TIM8 becuase of a NVIC conflict, possibly with the UART.

I don't know what is "NVIC conflict". While TIM8 interrupt vectors are shared with TIM12/13, there's no shared TIM8 vector with any UART, and no UART/USART nor any DMA stream interrupt vector is shared with any other source. Read the NVIC chapter in RM.

There may be conflicts in usage of DMA2 streams, though; again, refer to the DMA chapter in RM.

> It's documented behaviour, that autogen tools miss the nuances of use cases is unfortunate.​

Any clicky or "library" or "abstraction" inevitably misses nuances ("abstraction" means "least common denominator" so it's by definition). In fact, they inevitably implement only a miniscule portion of possible functionality, the "usual" ones, arguably. My general recommendation is to use Cube/HAL as long as you can easily click functionality in CubeMX and if you plan anything beyond it, ditch it sooner than it eats into your skin.

Maybe TIM-triggered-GPIO is "usual" enough to deserve attention, though.

JW

I don't know why STM32 cube shows a conflict with NVIC on TIM8.

STM32 Cube does not seem to show exactly which interrupts are causing the conflict :(

I think considering how many other checks that the Cube does, I think it would be logical at least gives a warning, that it won't work to all peripherals.

I've also noticed that the FSMC does not seem to work with CC RAM.

I'm sure its all documented somewhere in the 1000 pages + of data sheets