circular buffer - empty or full

Thread Starter

bug13

Joined Feb 13, 2012
2,002
So I need to write a circular buffer, there is my logic, I think they are correct. But I just need someone to take a look for me, to see if they are actually correct.

Thanks guys!!

Code:
    typedef struct{
        uint8_t *data;
        uint8_t head;
        uint8_t tail;
        uint8_t size;                 // size of the *data
        uint8_t data_count;    // number of un-used data
    }circular_buffer_t;      

uint8_t isEmpty(circular_buffer_t *cb){
  // if  (data_count == 0), then return true
  //  or else return false
}

uint8_t isFull(circular_buffer_t *cb){
  // if (data_count == buffer size), then return true
  //  or else return false
}

void put(circular_buffer_t *cb){
  // add data
  // head++
  // check head for overflow
  // buffer data_counter++
}

uint8_t get(circular_buffer_t *cb){
  // read data
  // tail++
  // check tail for overflow
  // buffer data_counter--
}
 

Thread Starter

bug13

Joined Feb 13, 2012
2,002
My worries are accessing the structure in interrupt. Say I am reading one byte date, in the middle of it, there is an interrupt. Will that be a problem?

Should I disable interrupt when I am reading data in the main loop?

Or I better not use a structure???
 

Picbuster

Joined Dec 2, 2013
1,058
make an array
in interrupt routine
pointer modulo (size array)
put the data in array[pointer]
pointer++;

in main remember last read.
start read from last read +1 ( last read is always between 0 and array size.

picbuster
 

MrChips

Joined Oct 2, 2009
34,817
It depends on the different processes accessing the resource (buffer).
You can lock the resource while accessing it. The problem you have to deal with is resource contention.
If two processes are attempting to access the same resource simultaneously the result is resource contention resulting in deadly embrace.

BTW, I use an ARM processor (STM32F407) that implements circular buffers in hardware. The buffer can be filled using direct memory access (DMA) and is performed entirely in hardware without slowing down the code.
 

nsaspook

Joined Aug 27, 2009
16,325
Does it need to be thread-safe? (more than one producer and consumer) If that's true then you will need locks but most simple embedded applications will have only one producer in the interrupt thread and one consumer in the main thread so resource contention mutex-locking is not needed but protection of updates are needed. If count variable updates (changes happen with one uninterruptible CPU instruction sequence) are atomic then you don't interrupt protection.

It would be safer to use push/pop head and tail indexes instead of a count variable to eliminate update locking issues not related to multi-threads.
https://embedjournal.com/implementing-circular-buffer-embedded-c/

https://riot-os.org/api/tsrb_8h_source.html
https://github.com/RIOT-OS/RIOT/blob/master/sys/tsrb/tsrb.c
 

Thread Starter

bug13

Joined Feb 13, 2012
2,002
It depends on the different processes accessing the resource (buffer).
You can lock the resource while accessing it. The problem you have to deal with is resource contention.
If two processes are attempting to access the same resource simultaneously the result is resource contention resulting in deadly embrace.

BTW, I use an ARM processor (STM32F407) that implements circular buffers in hardware. The buffer can be filled using direct memory access (DMA) and is performed entirely in hardware without slowing down the code.
That's so true, and thanks for pointing this out. In my case I am just using a PIC18, and only one level of interrupt. I guess I am fine then. Although I really want to get in to ARM.

PS:
not relative to this top, any low cost arm board you can recommend? For getting into arm?
 

Thread Starter

bug13

Joined Feb 13, 2012
2,002
Does it need to be thread-safe? (more than one producer and consumer) If that's true then you will need locks but most simple embedded applications will have only one producer in the interrupt thread and one consumer in the main thread so resource contention mutex-locking is not needed but protection of updates are needed. If count variable updates (changes happen with one uninterruptible CPU instruction sequence) are atomic then you don't interrupt protection.

It would be safer to use push/pop head and tail indexes instead of a count variable to eliminate update locking issues not related to multi-threads.
https://embedjournal.com/implementing-circular-buffer-embedded-c/

https://riot-os.org/api/tsrb_8h_source.html
https://github.com/RIOT-OS/RIOT/blob/master/sys/tsrb/tsrb.c
In my case, just a simple embedded system with a PIC18. One level interrupt and then main loop.

Why do you think it would be safer to use push/pop head and tail indexes? Using a count variable look the same as using head and tail index to me, and it's easier to understand. Well at least in my case (one interrupt level and one main loop)
 

nsaspook

Joined Aug 27, 2009
16,325
In my case, just a simple embedded system with a PIC18. One level interrupt and then main loop.

Why do you think it would be safer to use push/pop head and tail indexes? Using a count variable look the same as using head and tail index to me, and it's easier to understand. Well at least in my case (one interrupt level and one main loop)
Why do I think it's safer? Because one day that easier to understand routine might be used by you on a system where the count variable is not safe without MT protection.
 

MrSoftware

Joined Oct 29, 2013
2,273
In regards to your ARM question; I've been using the Rigado BMD-350-EVAL board, which from the software side is identical to the Nordic pca10040, and all the Nordic examples should work on it as-is. It's ARM based (Nordic nrf52832) and has Bluetooth, NFC and some other cool stuff. You can use the free version of Keil uVision IDE (limited to 32k binary) for most things, or Eclipse/gcc after some setup. After using both I prefer uVision, but some of the BLE samples are too large for the free version and you have to use Eclipse/gcc or pay for uVision. I believe there is also a low cost implementation that relies on Microsoft Visual Studio, but I haven't tried it myself yet.

There is a new board that uses the brand new Nordic nrf52840, but I haven't used it myself yet.
 
Top