简体   繁体   中英

Atmel driver and GCC memory barrier use case

While I was taking a look at some driver implementations from the Atmel Software Framework, I came across several cases where they used a memory barrier.

Barrier definition:

#define barrier()        asm volatile("" ::: "memory")

Example 1 (interrupt helper functions):

static inline void cpu_irq_restore(irqflags_t flags)
{
    barrier();
    SREG = flags;
}

This barrier makes sense to me. Since cpu_irq_restore gets implicitly inlined, it prevents the critical (from an execution order perspective) SREG assignment to be re-ordered from the actual function call location.

As a side note: SREG is defined as a special function register defined as:

#define _SFR_MEM8(mem_addr) (*(volatile uint8_t *)(mem_addr))

Example 2 (from AVR TWI driver):

static inline status_code_t twim_release(void)
{
    /* First wait for the driver event handler to indicate something
     * other than a transfer in-progress, then test the bus interface
     * for an Idle bus state.
     */
    while (OPERATION_IN_PROGRESS == transfer.status);

    while (! twim_idle(transfer.bus)) { barrier(); }

    status_code_t const status = transfer.status;

    transfer.locked = false;

    return status;
}

This second use case however, is not clear to me. In what way could the compiler optimize that code, so that it breaks without the barrier() ?

I think I understand the basic reasoning behind software memory barriers after reading this article .

What is the reasoning behind using the barrier in the second example?

The twim_idle function probably does something like read the value of a TWI-related special function register and check some bits in it. Without the barrier, the danger is that the compiler might optimize the reading of that register and move it to before the second loop. So then that second loop would behave like this:

bool idle = twim_idle(transfer.bus);
while (!idle);

This is an optimization that would make the loop faster and it would be valid for reads of normal variables, but it would obviously cause a problem in this case. Putting a barrier in the loop should prevent that optimization from happening.

In reality, you should not need that memory barrier because all the special function registers are qualified with the volatile keyword, so the compiler will not attempt to cache accesses to them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM