2
\$\begingroup\$

I am working on a system which uses about 4 interrupts. I can clearly define a priority from one to the other. For example, I feed SPI transfers with DMA requests and operate a USB interface which drives the SPI data. To this end I have prioritized my interrupts as follows (ordered from highest to lowest priority)

  1. Systick
  2. EXTI for handshaking signals
  3. DMA streams
  4. USB

Everything works great for a while and then I start seeing some odd behavior that I have not been able to determine the cause of yet, but I am wondering/suspecting if its because I am allowing interrupts to pre-empt other ones at inopportune times.

So my question is, what sorts of issues should be considered when deciding if an interrupt should preempt another, or if it should just be given a high enough priority to tail-chain.

\$\endgroup\$
2
  • \$\begingroup\$ Can you specify what kind of odd behavior you are experiencing? Corrupts data? Stalls? Weird execution paths? \$\endgroup\$ – Mishyoshi Aug 14 '14 at 19:03
  • \$\begingroup\$ The behavior I am experiencing appears to be a corruption of the SPI peripheral. After a varying number of successful SPI transfers (driven by DMA) I have a TX that appears to be setup correctly (DMA parameters, SPI data register contains correct first byte, etc) but the data send over the line is corrupted. \$\endgroup\$ – Jared Aug 14 '14 at 19:16
4
\$\begingroup\$

In general, interrupt preemption may cause deadlocking problems: if an interruption waits on a resource that is locked/in use by another lower priority interruption, you program may stall.

Also, a higher priority interruption may well interrupt a task which should not be interrupted if not properly protected (critical sections). When not using interrupt preemption, disabling interrupts on a given level disables all interruptions. When nesting, you may have higher priority interruptions breaking code from lower priority interruptions/code in unexpected ways.

Frankly, unless you really need to prioritize a process over another, it is useless to mess with that. Since you look like your are only chaining interdependent processes, i would only call this asking for trouble.

\$\endgroup\$
8
  • \$\begingroup\$ The USB transfers (interrupt driven) require the completion of an SPI transfer to complete. Currently I initiate the SPI transfer in the USB ISR and wait for it to complete (a DMA ISR will execute). In this setup I am required to have the DMA ISR preempt the USB ISR. My question stems from trying to determine if its worth integrating the USB stack with my application more, or if this is a viable way of implementing my end goal. \$\endgroup\$ – Jared Aug 14 '14 at 19:15
  • 4
    \$\begingroup\$ Yes but question being: would it be simpler to use "ordinary non preempted interruptions" with a state machine instead of coding a state machine inside each ISR? It is usually very bad practice to wait in an ISR with preemption or not. Interruption preemption was mainly designed to allow a fast event to interrupt a slower one. Exemple: if you have an ISR which copy manually 1024 to a buffer or do some hardcore logic while you have a very high speed communication running in the background, you may want that high speed comm to interrupt and store a data byte in a buffer without waiting... \$\endgroup\$ – Mishyoshi Aug 14 '14 at 19:21
  • \$\begingroup\$ ...so you don't lose data. That being said, you may still use preempted interruption for what you are asking and I don't think it is the cause the your trouble. It may just bloat your code making the problem untraceable. \$\endgroup\$ – Mishyoshi Aug 14 '14 at 19:22
  • \$\begingroup\$ Perhaps. I understand your point, and that is more or less what I am attempting (the DMA transfers pre-empting the USB so that the next transfer can be started ASAP. Ultimately, I am running ST's USB stack which is interrupt driven, and to respond to data requests I need to perform SPI transfers. The ST stack has a state machine for its operations and I have one for my SPI transfers. The invalid response could as you say, be any number of things. For know I am trying to implement an abort-retry process which should make it more robust anyway. Thanks for your input. \$\endgroup\$ – Jared Aug 14 '14 at 19:25
  • \$\begingroup\$ If I understand you well, you somehow have: USB => DMA => SPI. In such case, you can use the USB interrupt from ST library to raise a flag or a state change or whatever you want. You buffer each usb packet if SPI is slower. Then your state machine in ordinary code takes an usb packet and forwards it to the SPI using DMA. When DMA interruption tell you that you are done, you release memory from packet and cycle your state machine to get next packet and initiate a new DMA transfer. I don't know what you are doing exactly, so I'm guessing, but that could be a way of doing things. \$\endgroup\$ – Mishyoshi Aug 14 '14 at 19:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.