Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.arch.embedded > #30830
| From | Dimiter_Popoff <dp@tgi-sci.com> |
|---|---|
| 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 | 2021-10-24 14:14 +0300 |
| Organization | TGI |
| Message-ID | <sl3f65$jdl$1@dont-email.me> (permalink) |
| References | <skvcnd$5dv$1@dont-email.me> <sl3d4h$17d3$1@gioia.aioe.org> |
On 10/24/2021 13:39, Johann Klammer wrote:
> On 10/23/2021 12:07 AM, pozz wrote:
>> Even I write software for embedded systems for more than 10 years, there's an argument that from time to time let me think for hours and leave me with many doubts.
>>
>> Consider a simple embedded system based on a MCU (AVR8 or Cortex-Mx). The software is bare metal, without any OS. The main pattern is the well known mainloop (background code) that is interrupted by ISR.
>>
>> Interrupts are used mainly for timings and for low-level driver. For example, the UART reception ISR move the last received char in a FIFO buffer, while the mainloop code pops new data from the FIFO.
>>
>>
>> static struct {
>> unsigned char buf[RXBUF_SIZE];
>> uint8_t in;
>> uint8_t out;
>> } rxfifo;
>>
>> /* ISR */
>> void uart_rx_isr(void) {
>> unsigned char c = UART->DATA;
>> rxfifo.buf[in % RXBUF_SIZE] = c;
>> rxfifo.in++;
>> // Reset interrupt flag
>> }
>>
>> /* Called regularly from mainloop code */
>> int uart_task(void) {
>> int c = -1;
>> if (out != in) {
>> c = rxfifo.buf[out % RXBUF_SIZE];
>> out++;
>> }
>> return -1;
>> }
>>
>>
>> From a 20-years old article[1] by Nigle Jones, this seems a situation where volatile must be used for rxfifo.in, because is modified by an ISR and used in the mainloop code.
>>
>> I don't think so, rxfifo.in is read from memory only one time in uart_task(), so there isn't the risk that compiler can optimize badly. Even if ISR is fired immediately after the if statement, this doesn't bring to a dangerous state: the just received data will be processed at the next call to uart_task().
>>
>> So IMHO volatile isn't necessary here. And critical sections (i.e. disabling interrupts) aren't useful too.
>>
>> However I'm thinking about memory barrier. Suppose the compiler reorder the instructions in uart_task() as follows:
>>
>>
>> c = rxfifo.buf[out % RXBUF_SIZE]
>> if (out != in) {
>> out++;
>> return c;
>> } else {
>> return -1;
>> }
>>
>>
>> Here there's a big problem, because compiler decided to firstly read rxfifo.buf[] and then test in and out equality. If the ISR is fired immediately after moving data to c (most probably an internal register), the condition in the if statement will be true and the register value is returned. However the register value isn't correct.
>>
>> I don't think any modern C compiler reorder uart_task() in this way, but we can't be sure. The result shouldn't change for the compiler, so it can do this kind of things.
>>
>> How to fix this issue if I want to be extremely sure the compiler will not reorder this way? Applying volatile to rxfifo.in shouldn't help for this, because compiler is allowed to reorder access of non volatile variables yet[2].
>>
>> One solution is adding a memory barrier in this way:
>>
>>
>> int uart_task(void) {
>> int c = -1;
>> if (out != in) {
>> memory_barrier();
>> c = rxfifo.buf[out % RXBUF_SIZE];
>> out++;
>> }
>> return -1;
>> }
>>
>>
>> However this approach appears to me dangerous. You have to check and double check if, when and where memory barriers are necessary and it's simple to skip a barrier where it's nedded and add a barrier where it isn't needed.
>>
>> So I'm thinking that a sub-optimal (regarding efficiency) but reliable (regarding the risk to skip a barrier where it is needed) could be to enter a critical section (disabling interrupts) anyway, if it isn't strictly needed.
>>
>>
>> int uart_task(void) {
>> ENTER_CRITICAL_SECTION();
>> int c = -1;
>> if (out != in) {
>> c = rxfifo.buf[out % RXBUF_SIZE];
>> out++;
>> }
>> EXIT_CRITICAL_SECTION();
>> return -1;
>> }
>>
>>
>> Another solution could be to apply volatile keyword to rxfifo.in *AND* rxfifo.buf too, so compiler can't change the order of accesses them.
>>
>> Do you have other suggestions?
>>
>>
>>
>> [1] https://barrgroup.com/embedded-systems/how-to/c-volatile-keyword
>> [2] https://blog.regehr.org/archives/28
> 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.
Although this thread is on how to wrestle a poor
language to do what you want, sort of how to use a hammer on a screw
instead of taking the screwdriver, there would be no need to
mask interrupts with C either.
======================================================
Dimiter Popoff, TGI http://www.tgi-sci.com
======================================================
http://www.flickr.com/photos/didi_tgi/
Back to comp.arch.embedded | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on pozz <pozzugno@gmail.com> - 2021-10-23 00:07 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Clifford Heath <no.spam@please.net> - 2021-10-23 13:40 +1100
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-22 22:09 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on pozz <pozzugno@gmail.com> - 2021-10-23 22:12 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-23 15:59 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on David Brown <david.brown@hesbynett.no> - 2021-10-23 18:09 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on pozz <pozzugno@gmail.com> - 2021-10-23 22:49 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on David Brown <david.brown@hesbynett.no> - 2021-10-24 13:02 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on pozz <pozzugno@gmail.com> - 2021-10-24 17:39 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on David Brown <david.brown@hesbynett.no> - 2021-10-24 18:37 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on pozz <pozzugno@gmail.com> - 2021-10-25 20:15 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on David Brown <david.brown@hesbynett.no> - 2021-10-25 20:54 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Richard Damon <Richard@Damon-Family.org> - 2021-10-25 20:31 -0400
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Johann Klammer <klammerj@NOSPAM.a1.net> - 2021-10-24 12:39 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Dimiter_Popoff <dp@tgi-sci.com> - 2021-10-24 14:14 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-24 12:54 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Dimiter_Popoff <dp@tgi-sci.com> - 2021-10-24 23:27 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-24 14:08 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Dimiter_Popoff <dp@tgi-sci.com> - 2021-10-25 00:50 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-24 15:47 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Dimiter_Popoff <dp@tgi-sci.com> - 2021-10-25 02:32 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-24 18:34 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on David Brown <david.brown@hesbynett.no> - 2021-10-25 09:41 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-10-25 10:56 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-25 01:19 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-10-25 11:52 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-25 02:50 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on David Brown <david.brown@hesbynett.no> - 2021-10-25 13:49 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-10-25 15:16 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-10-25 11:09 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-25 01:28 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-10-25 12:06 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-25 02:35 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Dimiter_Popoff <dp@tgi-sci.com> - 2021-10-25 16:04 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-10-25 18:34 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-25 10:43 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Dimiter_Popoff <dp@tgi-sci.com> - 2021-10-25 20:53 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-25 11:02 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on pozz <pozzugno@gmail.com> - 2021-10-25 19:52 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-25 11:10 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-10-25 21:33 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Dimiter_Popoff <dp@tgi-sci.com> - 2021-10-25 22:09 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Niklas Holsti <niklas.holsti@tidorum.invalid> - 2021-10-25 22:53 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Dimiter_Popoff <dp@tgi-sci.com> - 2021-10-25 23:02 +0300
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on David Brown <david.brown@hesbynett.no> - 2021-10-26 00:05 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on pozz <pozzugno@gmail.com> - 2021-10-25 23:46 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on David Brown <david.brown@hesbynett.no> - 2021-10-25 20:58 +0200
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Clifford Heath <no.spam@please.net> - 2021-10-26 08:43 +1100
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on antispam@math.uni.wroc.pl - 2021-10-25 21:32 +0000
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-25 15:24 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on antispam@math.uni.wroc.pl - 2021-10-27 00:20 +0000
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-26 17:52 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on antispam@math.uni.wroc.pl - 2021-10-27 05:22 +0000
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-29 15:36 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on antispam@math.uni.wroc.pl - 2021-10-31 22:54 +0000
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-10-31 20:37 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on antispam@math.uni.wroc.pl - 2021-11-11 04:34 +0000
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on Don Y <blockedofcourse@foo.invalid> - 2021-11-19 16:21 -0700
Re: How to write a simple driver in bare metal systems: volatile, memory barrier, critical sections and so on David Brown <david.brown@hesbynett.no> - 2021-10-25 08:57 +0200
csiph-web