Path: csiph.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Niklas Holsti Newsgroups: comp.arch.embedded Subject: Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Date: Mon, 25 Oct 2021 21:33:44 +0300 Organization: Tidorum Ltd Lines: 62 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-15; format=flowed Content-Transfer-Encoding: 7bit X-Trace: individual.net i5cva3ddKlQmuL3JwhV9MQbxZp5khCkaeeaL9iLlmQo19ckWNo Cancel-Lock: sha1:SLJIku5NBREkzVnLFloyUHF5nYE= User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0) Gecko/20100101 Thunderbird/78.14.0 In-Reply-To: Content-Language: en-US Xref: csiph.com comp.arch.embedded:30861 On 2021-10-25 20:52, pozz wrote: > Il 25/10/2021 17:34, Niklas Holsti ha scritto: >> On 2021-10-25 16:04, Dimiter_Popoff wrote: >>> On 10/25/2021 11:09, Niklas Holsti wrote: >>>> On 2021-10-24 23:27, Dimiter_Popoff wrote: >>>>> On 10/24/2021 22:54, Don Y wrote: >>>>>> On 10/24/2021 4:14 AM, Dimiter_Popoff wrote: >>>>>>>> Disable interrupts while accessing the fifo. you really have to. >>>>>>>> alternatively you'll often get away not using a fifo at all, >>>>>>>> unless you're blocking for a long while in some part of the code. >>>>>>> >>>>>>> Why would you do that. The fifo write pointer is only modified by >>>>>>> the interrupt handler, the read pointer is only modified by the >>>>>>> interrupted code. Has been done so for times immemorial. >>>>>> >>>>>> The OPs code doesn't differentiate between FIFO full and empty. (I suspect something is not quite right with the attributions of the quotations above -- Dimiter probably did not suggest disabling interrupts -- but no matter.) [snip] > When I have a small (<256) power-of-two (16, 32, 64, 128) buffer (and > this is the case for a UART receiving ring-buffer), I like to use this > implementation that works and doesn't waste any element. > > However I know this isn't the best implementation ever and it's a pity > the thread emphasis has been against this implementation (that was used > as *one* implementation just to have an example to discuss on). > > The main point was the use of volatile (and other techniques) to > guarantee a correct compiler output, whatever legal (respect the C > standard) optimizations the compiler thinks to do. > > It seems to me the arguments againts or for volatile are completely > indipendent from the implementation of ring-buffer. Of course "volatile" is needed, in general, whenever anything is written in one thread and read in another. The issue, I think, is when "volatile" is _enough_. I feel that detection of a full buffer (FIFO overflow) is required for a proper ring buffer implementation, and that has implications for the data structure needed, and that has implications for whether critical sections are needed. If the FIFO implementation is based on just two pointers (read and write), and each pointer is modified by just one of the two threads (main thread = reader, and interrupt handler = writer), and those modifications are both "volatile" AND atomic (which has not been discussed so far, IIRC...), then one can do without a critical region. But then detection of a full buffer needs one "wasted" element in the buffer. To avoid the wasted element, one could add a "full"/"not full" Boolean flag. But that flag would be modified by both threads, and should be modified atomically together with the pointer modifications, which (I think) means that a critical section is needed.