Search code examples
interruptstm32race-conditionfifocritical-section

Interrupt safe "FIFO" for DSP on STM32 MCU


I have an adc that reads values on an interrupt and stores them in a FIFO.

In the main programm I wanted to read the whole FIFO just like a regular array and do FFT and stuff. After a little bit of thinking I realized that the interrupt could occur during the reading process and that the data wouldn't be accurate anymore.

Can this be done without disabling the interrupt ?

I only found examples for push,pop FIFOs and although I could use one, I guess, I wanted to know if this is possible.

Here is my code:

#define SP_FIFO_SIZE 4096
#define SP_BITMASK_SIZE (SP_FIFO_SIZE - 1)

struct sp_fifo_struct{
    uint16_t array[SP_FIFO_SIZE];
    uint16_t pointer;
};

typedef volatile struct sp_fifo_struct sp_fifo;

void sp_fifo_push(sp_fifo * fifo, uint16_t value){
    fifo->array[fifo->pointer] = value;
    fifo->pointer = ((fifo->pointer + 1) & SP_BITMASK_SIZE);
}

void sp_fifo_read(sp_fifo * fifo, float32_t array[]){
    for(uint16_t i = 0; i < SP_FIFO_SIZE; i++){
        array[i] = (float32_t) fifo->array[((fifo->pointer + i) & SP_BITMASK_SIZE)];
    }
}

Solution

  • You certainly need to mutex lock your fifo in this instance. This isn't the case only when you can guarantee atomic reads/writes of the data into the queue. Additionally, incrementing/decrementing your indexing variable may or may not be atomic depending on your hardware platform and datatype.

    As far as the data processing, I don't know the format of your data, so it's hard to say. I assume you have fixed length data. If that's the case, your fifo could be a queue of structs (definition of your fixed length data) instead of individual bytes. This would ensure that read/writes of the queue are "atomic" in the sense that you are always grabbing one "data point" (however you define that).