Author Topic: Single DMA burst STM32 and HAL  (Read 7668 times)

0 Members and 1 Guest are viewing this topic.

Offline Twistx77Topic starter

  • Regular Contributor
  • *
  • Posts: 147
  • Country: 00
Single DMA burst STM32 and HAL
« on: February 23, 2017, 11:02:14 pm »
Hi,
I'm to ST MCUs. I'm using a Timer and DMA to produce a variable PWM signal.  So the idea is to start a DMA burst to load the pwm values in each period of the timer. It works well but it doesn't stop, it does the burst perfectly but then it keeps sending the last value instead of stop. The DMA is configured as Normal (Not circular). This is the configuraction:

Code: [Select]
dma_tim3_ch1_trig.Instance = DMA1_Channel4;
    hdma_tim3_ch1_trig.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_tim3_ch1_trig.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_tim3_ch1_trig.Init.MemInc = DMA_MINC_ENABLE;
    hdma_tim3_ch1_trig.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_tim3_ch1_trig.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_tim3_ch1_trig.Init.Mode = DMA_NORMAL;//DMA_CIRCULAR;
    hdma_tim3_ch1_trig.Init.Priority = DMA_PRIORITY_HIGH;

 if (HAL_DMA_Init(&hdma_tim3_ch1_trig) != HAL_OK)
    {
      Error_Handler();
    }

    /* Several peripheral DMA handle pointers point to the same DMA handle.
     Be aware that there is only one channel to perform all the requested DMAs. */
    __HAL_LINKDMA(htim_pwm,hdma[TIM_DMA_ID_CC1],hdma_tim3_ch1_trig);
    __HAL_LINKDMA(htim_pwm,hdma[TIM_DMA_ID_TRIGGER],hdma_tim3_ch1_trig);

   

I'm using a STM32F0 with HAL libraríes and the LED toggle in the main function works as expected.

Code: [Select]

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f0xx_hal.h"
#include "usb_device.h"


ADC_HandleTypeDef hadc;

I2C_HandleTypeDef hi2c1;

TIM_HandleTypeDef htim3;
DMA_HandleTypeDef hdma_tim3_ch1_trig;


/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_ADC_Init(void);
static void MX_I2C1_Init(void);
static void MX_TIM3_Init(void);

void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);

int main(void)
{

  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC_Init();
  MX_I2C1_Init();
  MX_TIM3_Init();
  MX_USB_DEVICE_Init();

  uint8_t buffer[10] = {10,20,30,40,50}
  HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1, (uint32_t *) buffer,5);


while(1){

  HAL_Delay(100);
  HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);

}

}

I tried debugging and I get the Interrupt when the transfer is finished.

Do I need to clear a flag or something in the interrupt routine?

Thanks!

 

Offline Short Circuit

  • Frequent Contributor
  • **
  • Posts: 439
  • Country: nl
Re: Single DMA burst STM32 and HAL
« Reply #1 on: February 24, 2017, 12:53:20 am »
Does it keep sending the last value, or is it just the timer which continues running the PWM at the last known value? Because the latter is to be expected...
If you want the PWM to stop, you can disable the timer in the DMA completion interrupt.
 
The following users thanked this post: Twistx77

Offline Twistx77Topic starter

  • Regular Contributor
  • *
  • Posts: 147
  • Country: 00
Re: Single DMA burst STM32 and HAL
« Reply #2 on: February 24, 2017, 10:43:58 am »
Does it keep sending the last value, or is it just the timer which continues running the PWM at the last known value? Because the latter is to be expected...
If you want the PWM to stop, you can disable the timer in the DMA completion interrupt.

Thanks!! I assumed it stopped the Timer once the DMA transfer was completed because before I had a problem in my code and it stopped the DMA transfer because of an error and it stopped the Timer too.

Now I stop the timer when the DMA transfer finished but I still have a small problem. When I stop the timer the output rests at a HIGH level. I tried to set the timers configuration with  sConfigOC.OCIdleState = TIM_OCIDLESTATE_SET; and sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; and none of them keeps the output low when the timer has stoppped.

I need to look it better but that would be helpful if you know how I could fix that.

Thank you!
 

Offline Buriedcode

  • Super Contributor
  • ***
  • Posts: 1610
  • Country: gb
Re: Single DMA burst STM32 and HAL
« Reply #3 on: February 24, 2017, 12:30:46 pm »
Perhaps in your 'DMA complete' interrupt you could enable the interrupt for 'timer compare match'.  I am unfamiliar with the STM32, so I'm using generic names here. 

What I mean is, I assume the timer PWM operates like most modules on most micros - output set on timer = 0, and cleared on match to PWM period value.  Often there is an interrupt available for that match. And you can enable this when your DMA completes.  And this interrupt will fire when the PWM output goes from high, to low - and then you can disable the timer... and one would assume it will keep the output low.  Alternatively, have this interrupt enabled all the time, but use a software flag/register that is set when the DMA is complete.  This means the match interrupt will always fire, but just checks this flag, if the flag is 0, it disables the timer.

Either that or disable the timer output before turning the timer off?
 

Offline Twistx77Topic starter

  • Regular Contributor
  • *
  • Posts: 147
  • Country: 00
Re: Single DMA burst STM32 and HAL
« Reply #4 on: February 24, 2017, 01:58:22 pm »
Perhaps in your 'DMA complete' interrupt you could enable the interrupt for 'timer compare match'.  I am unfamiliar with the STM32, so I'm using generic names here. 

What I mean is, I assume the timer PWM operates like most modules on most micros - output set on timer = 0, and cleared on match to PWM period value.  Often there is an interrupt available for that match. And you can enable this when your DMA completes.  And this interrupt will fire when the PWM output goes from high, to low - and then you can disable the timer... and one would assume it will keep the output low.  Alternatively, have this interrupt enabled all the time, but use a software flag/register that is set when the DMA is complete.  This means the match interrupt will always fire, but just checks this flag, if the flag is 0, it disables the timer.

Either that or disable the timer output before turning the timer off?

Hi,

I basically did the first thing you propose. I assumed it would keep the output low but that is not the case. So the option I have left is the last one you propose but I imagine there must be a simpler way. Like changing the GPIO funtion to a standard IO and then changing it back before sending a second burst with the DMA.

Lets see if someone with more experience with STM32 architecture can give me a hint :).

 

Offline rheb1026

  • Regular Contributor
  • *
  • Posts: 101
  • Country: us
Re: Single DMA burst STM32 and HAL
« Reply #5 on: February 24, 2017, 04:30:57 pm »
Check the PWM mode in the PWM configuration. I had this issue before, too. I can't remember off the top of my head, but one combination of settings idles high and the other idles low
 

Offline Twistx77Topic starter

  • Regular Contributor
  • *
  • Posts: 147
  • Country: 00
Re: Single DMA burst STM32 and HAL
« Reply #6 on: February 24, 2017, 08:02:29 pm »
Check the PWM mode in the PWM configuration. I had this issue before, too. I can't remember off the top of my head, but one combination of settings idles high and the other idles low

I have tried everything I can think of in the configuration. I even tried using different timers but I can't seem to get it leave a low output value when stopped. 

If you can remember please let me know :)

Thanks!
 

Offline Twistx77Topic starter

  • Regular Contributor
  • *
  • Posts: 147
  • Country: 00
Re: Single DMA burst STM32 and HAL
« Reply #7 on: February 24, 2017, 08:16:49 pm »
I found a posible solution, although I don't know if it is the best.

I configured the PIN used by the timer as Pull Down instead of " No Pull Down and No Pull Up".

Now I have to check if it will affect the signals quality.

If anyone know a better way please let me know :)
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf