DMB, DSB, and ISB

DMB, DSB, and ISB

Data Memory Barrier, Data Synchronization Barrier, and Instruction Synchronization Barrier.

DMB

Data Memory Barrier acts as a memory barrier. It ensures that all explicit memory accesses that appear in program order before the DMB instruction are observed before any explicit memory accesses that appear in program order after the DMB instruction. It does not affect the ordering of any other instructions executing on the processor.

DSB

Data Synchronization Barrier acts as a special kind of memory barrier. No instruction in program order after this instruction executes until this instruction completes. This instruction completes when:

  • All explicit memory accesses before this instruction complete.

  • All Cache, Branch predictor and TLB maintenance operations before this instruction complete.

ISB

Instruction Synchronization Barrier flushes the pipeline in the processor, so that all instructions following the ISB are fetched from cache or memory, after the instruction has been completed. It ensures that the effects of context altering operations, such as changing the ASID, or completed TLB maintenance operations, or branch predictor maintenance operations, as well as all changes to the CP15 registers, executed before the ISB instruction are visible to the instructions fetched after the ISB.

 

volatile int flag=0; 
char buffer[10]; 
void foo(char c)
{     
      __ASM volatile ("dbm" : : : "memory");
      __disable_irq(); //disable IRQ as we use flag in ISR
    buffer[0]=c;
    flag=1;
      __ASM volatile ("dbm" : : : "memory");
      __enable_irq(); 
}


Uh, it depends on what your flag is, and it also varies from chip to chip.

In case that flag is stored in memory:

DSB is not needed here. An interrupt handler that would access flag would have to load it from memory first. Even if your previous write is still in progress the CPU will make sure that the load following the store will happen in the correct order.

If your flag is stored in peripheral memory:

Now it gets interesting. Lets assume flag is in some hardware peripheral. A write to it may make an interrupt pending or acknowledge an interrupt (aka clear a pending interrupt). Contrary to the memory example above this effect happens without the CPU having to read the flag first. So the automatic ordering of stores and loads won't help you. Also writes to flag may take effect with a surprisingly long delay due to different clock domains between the CPU and the peripheral.

So the following szenario can happen:

  • you write flag=1 to clear an handled interrupt.
  • you enable interrupts by calling __enable_irq()
  • interrupts get enabled, write to flag=1 is still pending.
  • wheee, an interrupt is pending and the CPU jumps to the interrupt handler.
  • flag=1 takes effect. You're now in an interrupt handler without anything to do.

Executing a DSB in front of __enable_irq() will prevent this problem because whatever is triggered by flag=1 will be in effect before __enable_irq() executes.

If you think that this case is purely academic: Nope, it's real.

Just think about a real-time clock. These usually runs at 32khz. If you write into it's peripheral space from a CPU running at 64Mhz it can take a whopping 2000 cycles before the write takes effect. Now for real-time clocks the data-sheet usually shows specific sequences that make sure you don't run into this problem.

The same thing can however happen with slow peripherals.

My personal anecdote happened when implementing power-saving late in a project. Everything was working fine. Then we reduced the peripheral clock speed of I²C and SPI peripherals to the lowest possible speed we could get away with. This can save lots of power and extend battery live. What we found out was that suddenly interrupts started to do unexpected things. They seem to fire twice each time wrecking havoc. Putting a DSB at the end of each affected interrupt handler fixed this because - you can guess - the lower clock speed caused us to leave the interrupt handlers before clearing the interrupt source was in effect due to the slow peripheral clock.

posted on 2022-04-13 20:57  荷树栋  阅读(326)  评论(0编辑  收藏  举报

导航