2022-09-13 04:51 AM
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
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
2022-09-13 04:52 AM
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
2022-09-13 04:55 AM
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?
2022-09-13 10:15 AM
2022-09-13 06:04 PM
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
2022-09-14 01:24 AM
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.
2022-09-14 01:50 AM
> 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
2022-09-14 03:14 AM
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