SPI interface freezes within the DMA ISR - [SOLVED] -

External hardware connected to the STM32 board
stevestrong
Posts: 1954
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany
Contact:

Re: SPI interface freezes within the DMA ISR

Post by stevestrong » Thu Dec 29, 2016 12:59 pm

@pito
Thanks, I am well aware of those information, but none of them discusses the system hangup by SPI register accesses within DMA ISR! And exactly this is what happens in my case. I cannot get the result of checking BSY flag, the system suddenly hangs...

@zmemw16
I cannot image why should the DMA trigger 2 interrupts at the same time.
But, anyway, even if it would so, why freezes the system when I access any SPI register within the ISR?

What kind of severe exception could occur?
If I manage to debug with STLink, how exactly can I detect the exception cause?

User avatar
ahull
Posts: 1672
Joined: Mon Apr 27, 2015 11:04 pm
Location: Sunny Scotland
Contact:

Re: SPI interface freezes within the DMA ISR

Post by ahull » Thu Dec 29, 2016 1:29 pm

Not sure if this helps, but you might like to look at -> https://github.com/leaflabs/libmaple/bl ... rrupts.txt
3.3: Interrupts not handled by libmaple (isrs.S)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Though libmaple does provide some IRQ handlers, it doesn't define one
for every available interrupt. This is true for various reasons: maybe
the peripheral or interrupt isn't supported yet, maybe there's no
useful default behavior, etc.

In this case, it would be wasteful to have a separate function for
each unhandled interrupt. To handle this, there's a single file that
deals with all unhandled interrupts. Its name is isrs.S, and it lives
in the same directory as the corresponding vector_table.S. For
example, for Maple, the file is libmaple/stm32f1/performance/isrs.S.

These aren't complicated; read the source to see how they work.

4. Adding your own interrupt handlers
-------------------------------------

When adding an interrupt handler (or overriding a default one), you
need to decide whether you want it for a particular program, or if
what you're writing is general-purpose enough that it should live in
libmaple itself.
...
- Andy Hull -

User avatar
Rick Kimball
Posts: 1069
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: SPI interface freezes within the DMA ISR

Post by Rick Kimball » Thu Dec 29, 2016 4:56 pm

stevestrong wrote: What kind of severe exception could occur?
Maybe you have blown out the stack, maybe there is a watchdog timeout, maybe a memory fault with a bad pointer to _currentSetting?, a bus fault?, a usage fault?
stevestrong wrote: If I manage to debug with STLink, how exactly can I detect the exception cause?
You should be able to wait for the problem to occur and then in the debugger pause and see where you are. (pause in the eclipse ide, ctrl-c in a command line arm-none-eabi-gdb session). If it is trapped on an exception it should show you which one. However, it might be in the "default_handler" code, you might have to make a unique function for each of the fault handlers so you can see which one it really is.

You could set a break point just before the offending instructions, validate that the SP looks reasonable, validate the _currentSetting points at something reasonable. Then use the assembler step instruction (ni in arm-none-eabi-gdb) to step through each statement until you lock up.

-rick
-rick

stevestrong
Posts: 1954
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany
Contact:

SPI interface freezes within the DMA ISR - [SOLVED] -

Post by stevestrong » Thu Dec 29, 2016 8:57 pm

I think I solved the problem.

In the error case, I used the following line to attach the interrupt for DMA:

Code: Select all

dma_attach_interrupt(_currentSetting->spiDmaDev,  _currentSetting->spiTxDmaChannel, (void(*)())(&SPIClass::dmaSendIrq));
This was necessary because, if the ISR function was not an SPIClass member, the compiler didn't recognized the used variables being members of the SPIClass.
The compiler generated the following warning:

Code: Select all

warning: converting from 'void (SPIClass::*)()' to 'void (*)()' [-Wpmf-conversions]

dma_attach_interrupt(_currentSetting->spiDmaDev,  _currentSetting->spiTxDmaChannel, (void(*)())(&SPIClass::dmaSendIrq));
And me, of course, I neglected the warning, thinking that it cannot be something serious if it is "only" a warning. I never though that this could cause any issues.
However, it seems that this was somehow actually causing my trouble.

Now I defined some extra variables to replace those from the SPIClass, I removed the ISR from the SPIClass, and the compiler then has accepted this ISR declaration line:

Code: Select all

dma_attach_interrupt(_currentSetting->spiDmaDev,  _currentSetting->spiTxDmaChannel, dmaSendIrq);
without any warning!
Also, although I added some extra code lines to initialize the additional variables, the code size decreased by some hundreds of bytes... Why? I cannot explain.

Anyway, the code seems to work now flawlessly, no more problems with SPI register accessing.

This should be a teaching for those who tend to ignore not-understood compiler/linker warnings.
Me, I learned my lesson.

User avatar
RogerClark
Posts: 7545
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: SPI interface freezes within the DMA ISR - [SOLVED] -

Post by RogerClark » Thu Dec 29, 2016 9:33 pm

@stevstrong

I came across the same problem myself ( but I can remember what code I was tryng to write)

From what I remember, its not possible to assign a pointer to a function to call a function inside a class.

It may be possible to use a static ( global ) callback function inside the SPI class, but it would be common to all instances of the class. ( but you would need to double check this)

There are probably other work-arounds to this, as its a well known problem. But I dont think there is an ideal solution.

Post Reply