1

In my firmware I write to MicroSD in a background task, and I've got a lot of higher-priorities interrupts enabled, some of which can take several milliseconds.

So the writing/reading from SPI can be interrupted at any moment, and for writes that may not be such a problem (if SPI behaves anything like UART), but during reads I'm afraid that my hardware SPI FIFO's will overflow if the task just happens to be interupted while the MicroSD card is sending a datablock.

Now the obvious solution would be to decrease the time that the higher priority interrupts take, but this seems very hard, because sometimes they have to wait on other peripherals too, and too prevent that I have to rewrite a lot of code that does polling now, to an interrupt-structure, which would make the overall code much more complicated.

I think in modern OSes this is solved by letting all those tasks run synchronously at the same priority, and give them all an equal time slice. But I don't have any mechanisms for threading, or an OS, so what would be the simplest way to solve this?

Maestro
  • 9,046
  • 15
  • 83
  • 116
  • Is it not possible to increase the process priority while you are reading data from the SPI? – Étienne Feb 02 '13 at 15:59
  • @EtienneCordonnier The device is a datalogger, which takes samples at a high frequency, so reading SPI should never interfere with the timing of the samples. But I may may be able to increase it's priority temporarily to just below the samping-interrupt. I'll give it a try, thanks. – Maestro Feb 02 '13 at 16:03
  • What processor? If ARM, put sampler on FIQ and SD card driver on IRQ? – Martin James Feb 02 '13 at 17:47
  • Also, why do your interrupts take several milliseconds? That's a huge amount of time for an interrupt handler! – Martin James Feb 02 '13 at 17:54
  • For efficient I/O, you really need an RTOS where the interrupt handlers can signal completion, especially with a file system that needs 512 byte reads/writes every time. Polling might seem simpler, and it is, but only for trivial systems with low I/O requirements. – Martin James Feb 03 '13 at 12:09

2 Answers2

4

write to MicroSD [...] hardware SPI FIFO's will overflow

You are the Master of the SPI: You control the SPI clock. The SPI Master will only generate a clock signal when it has a data frame to transfer - otherwise the clock is in idle state. This is also true for read operations: SPI always reads and writes at the same time.

In short, SPI will never overflow if you are the master. Hardware FIFOs do not change this fact.

Turbo J
  • 7,563
  • 1
  • 23
  • 43
  • Oh yes - that's true. Haven't used SPI since uC got 'proper' 4-bit SD-card controllers. +1 – Martin James Feb 02 '13 at 17:48
  • Okay, but if I introduce a long delay in the middle of a SPI transaction to the MicroSD, is there is still a chance the MicroSD cannot handle it, even if SPI does? Or are they prepared for this unusual situation? – Maestro Feb 02 '13 at 18:38
  • See [this answer](http://electronics.stackexchange.com/a/56884/1472) on electronics.stackexchange.com. The SPI clock can go down to 0 Hz. – Turbo J Feb 02 '13 at 19:32
  • @TurboJ- U shared a link to an answer to a question that was asked by the person asking this question. Lol – AlphaGoku May 06 '16 at 06:57
0

"I think in modern OSes this is solved by letting all those tasks run synchronously at the same priority, and give them all an equal time slice. But I don't have any mechanisms for threading, or an OS, so what would be the simplest way to solve this?"

multitasking in OS is not the same as interrupts.

I would layout the following:

SPI interrupt handlers for reading and writing. You've got the SPI FIFOs that you need to be aware of. You might get interrupts for overflow and "watermark" conditions. Be sure and handle these. Read your MCU user guide for specifics. Give your interrupt handlers their own circular queues in software. Size the queues appropriately given the size of the FIFO's (this is a choice based on hardware FIFO size, page size of the device you are reading/writing, and available memory.)

State machine module to be called from your application. This should have its own circular queues. The state machine should have functions to read and write data, as well as a "pump" function (i.e. a function that is called periodically from the main loop, aka "scheduled" from the main loop).

Your "tasks" that read and write from the SPI device state machine, should also be state machines, and they should also be able to handle not being able to write, or no data ready. In general, DO NOT BLOCK! Write your functions so that if what they need is not ready/available, they just quit, expecting to be called, aka "scheduled" at a later time.

So a general flow would be:

[task that wants to write] -> queue -> [Device state machine] -> queue -> [SPI interrupt] -> hardware queue -> [hardware] -> wire

wire -> [hardware -> hardware queue -> [SPI interrupt] -> queue -> [Device state machine] -> queue -> [task that wants to read]

Without specifics on your architecture, its hard to provide more details. But I've successfully used this pattern in many embedded device drivers.

Josh Petitt
  • 9,371
  • 12
  • 56
  • 104
  • I know this would be the optimal design, but im using the FatFS library which hasn't developed with interrupt-based SPI in mind. So when I call a function to write to disk, it will need to block because it needs the result of certain SPI commands, before it can decide what to do next. If I implemented SPI as interrupts instead of polling, the library functions would still block while waiting for the interrupt to fire, so I it seems I would gain nothing from it? – Maestro Feb 02 '13 at 18:53