Recent

Author Topic: A circular / ring buffer for embedded  (Read 6516 times)

d.ioannidis

  • Full Member
  • ***
  • Posts: 221
    • Nephelae
A circular / ring buffer for embedded
« on: October 10, 2022, 01:11:21 pm »
Ηι,

  if you need a circular / ring buffer, I added the spsc_ringbuffer  in ccrause's fpc-avr github repo. It's very small, fast, lock free and even if it's in an AVR specific repo it's not only for AVR ( i think ... :) ).

  It's a single producer / single consumer ring buffer. That means that there must be only one reader and only one writer. The basis for this came from an article in Jack Ganssle's Embedded Muse: http://www.ganssle.com/tem/tem110.pdf and with hints from this forum thread ( thx Martin ! ) .

Have fun !

regards,
« Last Edit: October 10, 2022, 01:14:08 pm by d.ioannidis »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11763
  • FPC developer.
Re: A circular / ring buffer for embedded
« Reply #1 on: October 10, 2022, 03:19:24 pm »
Shouldn't at least some of those be inline?

d.ioannidis

  • Full Member
  • ***
  • Posts: 221
    • Nephelae
Re: A circular / ring buffer for embedded
« Reply #2 on: October 10, 2022, 03:54:02 pm »
Hi,

Shouldn't at least some of those be inline?

AFAIU, inline will have numerous copies of the same code at many places and I wanted it to be as small as possible .

I'll look again the asm tonight to see if I missed something .

regards,

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11763
  • FPC developer.
Re: A circular / ring buffer for embedded
« Reply #3 on: October 10, 2022, 04:07:33 pm »
AFAIU, inline will have numerous copies of the same code at many places and I wanted it to be as small as possible .

But the code might be smaller than the function overhead.

Quote
I'll look again the asm tonight to see if I missed something .

I don't do much AVR work, mostly dspic. (in C, not Pascal). Dspic-E and -Cs have a 4 cycle branch, so inlining wins back 3 cycles before even anything else is done.

d.ioannidis

  • Full Member
  • ***
  • Posts: 221
    • Nephelae
Re: A circular / ring buffer for embedded
« Reply #4 on: October 10, 2022, 11:44:14 pm »
Hi,


But the code might be smaller than the function overhead.


If all the methods are inlined, then if the amount of calls to readbyte and/or writebyte methods is more than > 2 in the project, the project size is increased more than if you didn't inline them. But if the amount of calls to readbyte and/or writebyte methods is <=2, then the project size is smaller than if you didn't inline them.  %)

Now I'm little puzzled on what I should use .... Maybe a define. some ifdef's and inform the user of the buffer library, for the pros and cons of enabling inline or not .


I don't do much AVR work, mostly dspic. (in C, not Pascal). Dspic-E and -Cs have a 4 cycle branch, so inlining wins back 3 cycles before even anything else is done.


If by branch you mean conditional branch, then AFAIK, on AVR is 1 cycle if condition is false and 2 cycles if the condition is true ( instruction pointer needs to be loaded with new target ). No much gain in this regard . If you mean call or rcall then it's 4 cycles ( for the mcu's with 16 bit PC that is ) as the Dspic-E you use .

regards,

AlexTP

  • Hero Member
  • *****
  • Posts: 2463
    • UVviewsoft
Re: A circular / ring buffer for embedded
« Reply #5 on: October 11, 2022, 12:20:28 am »
Unit code was read by me. Can be changed to have any buffer size, as  i see. but instead of "Inc(nnn)" we will need

Inc(nnn);
if nnn>=BufferLastOffset then nnn:= BufferStartOffset;

It must work with any size.
The xxxMask method won't be needed.

EDIT. Ops, then getting the buffer size as nWriteOffset-nReadOffset will be broken, sorry.
« Last Edit: October 11, 2022, 12:22:36 am by AlexTP »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11763
  • FPC developer.
Re: A circular / ring buffer for embedded
« Reply #6 on: October 11, 2022, 09:43:06 am »
I never really optimize on size, always on speed.

Typical firmwares are 20-30kb, while the smallest flash is 128k, and most have 512kb.

ccrause

  • Hero Member
  • *****
  • Posts: 945
Re: A circular / ring buffer for embedded
« Reply #7 on: October 11, 2022, 01:58:52 pm »
I don't do much AVR work, mostly dspic. (in C, not Pascal).
I never really optimize on size, always on speed.

Typical firmwares are 20-30kb, while the smallest flash is 128k, and most have 512kb.
AVR resources are a bit more constrained:
Maximum flash = 256 kB (atmega2560/1)
Maximum RAM = 16 kB (atmega1284 & AVR128DB)
Minimum flash = 512 bytes (attiny4/5)
Minimum RAM = 32 bytes RAM (attiny4/5/9/10)
No RAM :o: attiny26/28

Thus the use of inlining would depend on whether a particular application is flash, RAM and/or speed constrained.

.... Maybe a define. some ifdef's and inform the user of the buffer library, for the pros and cons of enabling inline or not .
A define to control the use of inline seems like an acceptable option so that the user has some choice.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5672
  • Compiler Developer
Re: A circular / ring buffer for embedded
« Reply #8 on: October 12, 2022, 07:35:16 am »
We really should adjust {$Inline} so that it works like in Delphi: at the call site. So that the user themselves can control that inlining is off while the code that is called is compiled with inline (and assuming the compiler would indeed inline it).  ::)

ccrause

  • Hero Member
  • *****
  • Posts: 945
Re: A circular / ring buffer for embedded
« Reply #9 on: October 12, 2022, 08:09:27 am »
We really should adjust {$Inline} so that it works like in Delphi: at the call site. So that the user themselves can control that inlining is off while the code that is called is compiled with inline (and assuming the compiler would indeed inline it).  ::)
This seems like a really good idea!

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11763
  • FPC developer.
Re: A circular / ring buffer for embedded
« Reply #10 on: October 12, 2022, 09:40:37 am »
AVR resources are a bit more constrained:
Maximum flash = 256 kB (atmega2560/1)
Maximum RAM = 16 kB (atmega1284 & AVR128DB)
Minimum flash = 512 bytes (attiny4/5)
Minimum RAM = 32 bytes RAM (attiny4/5/9/10)
No RAM :o: attiny26/28

How useful is a HLL like Pascal on the tiny ?

We really should adjust {$Inline} so that it works like in Delphi: at the call site. So that the user themselves can control that inlining is off while the code that is called is compiled with inline (and assuming the compiler would indeed inline it).  ::)

Definitely.

Thaddy

  • Hero Member
  • *****
  • Posts: 15643
  • Censorship about opinions does not belong here.
Re: A circular / ring buffer for embedded
« Reply #11 on: October 12, 2022, 10:30:45 am »
Just let it overflow with {$R-}. Need power of two, of course and the correct bit size.
Code: Pascal  [Select][+][-]
  1. program ringbuffer;
  2. {$R-}
  3. var
  4.     b:byte = 0;
  5. begin
  6.   repeat
  7.     writeln(b);
  8.     inc(b);
  9.   until 0=1;// silly, replace with signal hi/lo....
  10. end.
Audio buffers trick.... That's how I used it in the past... And it is a 256 ringbuffer which is perfect for embedded.

« Last Edit: October 12, 2022, 10:46:21 am by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

ccrause

  • Hero Member
  • *****
  • Posts: 945
Re: A circular / ring buffer for embedded
« Reply #12 on: October 12, 2022, 10:45:37 am »
AVR resources are a bit more constrained:
Maximum flash = 256 kB (atmega2560/1)
Maximum RAM = 16 kB (atmega1284 & AVR128DB)
Minimum flash = 512 bytes (attiny4/5)
Minimum RAM = 32 bytes RAM (attiny4/5/9/10)
No RAM :o: attiny26/28

How useful is a HLL like Pascal on the tiny ?
I assume with "tiny" you are referring to the bottom of the range little/no RAM controllers, since most of the tiny series is relatively capable.  One can implement some basic ideas in Pascal, especially if the main functionality consists of configuring peripherals. An example is a blinky project with no RAM requirement, all the logic is handled by the timer peripheral.  Other than removing the RTL startup code, I don't think you can reduce the code size (for this example) more by switching to assembler (and I have an idea to add a compiler switch to drop the startup code).

But using Pascal would not give the user full control over storing variables just in registers, so to squeeze the very last bit of resources out of the controller would require abandoning the ABI (and Pascal) and only working in low level assembler.

Thaddy

  • Hero Member
  • *****
  • Posts: 15643
  • Censorship about opinions does not belong here.
Re: A circular / ring buffer for embedded
« Reply #13 on: October 12, 2022, 10:47:54 am »
@ccrause
Read my reply. That is usually how it is done and very lightweight.
If I smell bad code it usually is bad code and that includes my own code.

d.ioannidis

  • Full Member
  • ***
  • Posts: 221
    • Nephelae
Re: A circular / ring buffer for embedded
« Reply #14 on: October 12, 2022, 10:57:28 am »
Hi,

AVR resources are a bit more constrained:
Maximum flash = 256 kB (atmega2560/1)
Maximum RAM = 16 kB (atmega1284 & AVR128DB)
Minimum flash = 512 bytes (attiny4/5)
Minimum RAM = 32 bytes RAM (attiny4/5/9/10)
No RAM :o: attiny26/28

How useful is a HLL like Pascal on the tiny ?


  well the ATtiny10 has 1024 bytes of flash. With each instruction taking up 16 bits (2 bytes), you have about 512 instruction words available.  Writing in assembly gives you full control over these 512 words , but it also means slightly lesser readability (some people may disagree with me on this). That is why I usually prefer writing using Free pascal .

  But FYI I'm not an embedded programmer ( using C# in my day job ), only a hobbyist who loves free pascal and electronics .

regards,

 

TinyPortal © 2005-2018