Skip to main content
VLajo.1
Associate
May 16, 2020 11:27 AM UTC
Solved

Hardfault after start Timer in DMA mode

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.
VLajo.1
VLajo.1Best answer
Associate
May 16, 2020 7:24 PM UTC

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 1:35 PM UTC

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 5:15 PM UTC

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 5:31 PM UTC

So, where it happens and stack?

JW

berendi
Principal
May 16, 2020 2:15 PM UTC

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 5:11 PM UTC

Yeah, I should go bare registers-path

TDK
May 16, 2020 2:59 PM UTC

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 5:13 PM UTC

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

berendi
Principal
May 16, 2020 5:36 PM UTC

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 7:24 PM UTC

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 9:49 PM UTC

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