Skip to main content
VLajo.1
Associate
May 16, 2020
Solved

Hardfault after start Timer in DMA mode

  • May 16, 2020
  • 10 replies
  • 4655 views

hey!

I'm using timer 1 in OC mode with toggling the output. I also want to change the timer overflow value with the values predefined in the buffer.

I define buffer as:

uint16_t data[5] = { 50, 50, 100, 50, 50};

Then in main I call:

HAL_TIM_OC_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t *) data, 5);

Hardfault strikes inside HAL_TIM_OC_Start_DMA:

htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;

My question is how avoid this.

Attached Cube initialization of TIM and DMA.

Alternatively, maybe there is different approach. My goal is to get signal without interrupts that looks like this with exact frequency:

0 1 0 1 0 1 1 0 1 0 1

Thanks

This topic has been closed for replies.
Best answer by VLajo.1

Ok, now it works.

I start timer and OC separately like this and got desired pulse train:

 HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1);
 HAL_TIM_Base_Start_DMA(&htim1, (uint32_t *) data, 10);

Thanks everybody!

10 replies

waclawek.jan
Super User
May 16, 2020

Debug hardfault as usually - read out stack, find the instruction which caused the fault, its vicinity in disasm and related values in registers.

JW

VLajo.1
VLajo.1Author
Associate
May 16, 2020

Unfortunately it didn't give me much, I know where it happens and stack, still don't know why it happens. Thanks anyway!

waclawek.jan
Super User
May 16, 2020

So, where it happens and stack?

JW

berendi
Principal
May 16, 2020

HAL is difficult to figure out. You might get results sooner using the well documented register interface directly. The examples in AN4776 General-purpose timer cookbook are helpful.

Alternatively you can consider using a SPI port for the purpose, but the frequency choices are quite limited.

VLajo.1
VLajo.1Author
Associate
May 16, 2020

Yeah, I should go bare registers-path

TDK
May 16, 2020

Set up a circular DMA transfer to the GPIO->BSRR port you want to use. Trigger it with a timer at the desired frequency. You can set up most of that in CubeMX.

"If you feel a post has answered your question, please click ""Accept as Solution""."
VLajo.1
VLajo.1Author
Associate
May 16, 2020

I don't think I understand "DMA transfer to the GPIO->BSRR port". Is it memory -> memory transfer?

berendi
Principal
May 16, 2020

It would be still timed by a timer, but at even intervals, a word is copied from memory to a GPIO output register. Isn't worth​ the hassle in your case, it would be more useful when you wanted lots of outgoing pulses in parallel.

VLajo.1
VLajo.1AuthorBest answer
Associate
May 16, 2020

Ok, now it works.

I start timer and OC separately like this and got desired pulse train:

 HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1);
 HAL_TIM_Base_Start_DMA(&htim1, (uint32_t *) data, 10);

Thanks everybody!

berendi
Principal
May 16, 2020

Using HAL is always a hit-or-miss chance game.