This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS570LC4357: Memory barriers vs. read-backs for interrupt management

Part Number: TMS570LC4357

We've read over http://www.ti.com/lit/an/spna218/spna218.pdf and under the section "4.5.1 How Does it (Phantom Interrupts) Occur?" there is the text

" In this case, due to the imprecise timing of the VBUS write operation the interrupt service routine (ISR) could return before the CPU nIRQ or nFIQ interrupt request signal becomes inactive. ... When the peripheral interrupt pending flag is cleared by a read operation, the read instruction will return after at least 3 VBUS cycles and the CPU nIRQ or nFIQ interrupt request signal is already low when the interrupt service routine exits. Phantom interrupts will not occur in this situation."

My interpretation is that whenever we want to raise, clear, or mask an interrupt precisely we are guaranteed this will happen if we read back from the given register after writing it. But I'm not sure if memory barriers could accomplish the same thing because the given app note doesn't discuss them at all. For example here is simplified code we have for enabling an interrupt in the VIM:

// vimREG is volatile
void VimEnableInterrupt(uint32_t channel) {
  vimREG->REQMASKSET[channel / 32] = (uint32_t)1U << (channel % 32);
  (void)vimREG->REQMASKSET[channel / 32];
}

Note the readback at the end to guarantee that the write to vimREG will take effect by the end of this functions execution.

Would this code accomplish the same thing to guarantee that the write to vimREG will have taken effect by the end of the functions execution?

// vimREG is volatile
void VimEnableInterrupt(uint32_t channel) {
  vimREG->REQMASKSET[channel / 32] = (uint32_t)1U << (channel % 32);
  __asm__ __volatile__("dsb sy" ::: "memory");
}

I have a similar question about raising software interrupts. Currently we have the following code for raising a software interrupt:
#define portSYS_SSIR1_REG    ( * ( ( volatile portUInt32Type * ) 0xFFFFFFB0UL ) )
#define portSYS_SSIR1_SSKEY    ( 0x7500UL )
                        
  portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY;
  __asm volatile
  (  
    "  DSB    \n"  
    "  ISB    " 
    ::: "memory"); 

which doesn't read back from  portSYS_SSIR1_REG after writing to it, but does include a DSB. Assuming interrupts aren't masked, do we need to add a read-back from portSYS_SSIR1_REG to guarantee that an interrupt is raised immediately after the ISB is executed, or will there hypothetically be some delay in between the ISB and the interrupt being raised? Or is there something else entirely we need to do?

The two code samples above refer to specific modules, but does the sequence to guarantee a write has effected the active interrupts ever change depending on what module we're writing to? For example, enabling or disabling or clearing an interrupt in the VIM versus the DMA module versus  the GIO module. 

  • Hello Sarah,

    I apologize that we haven't responded earlier. I am taking some time to look into your question so I can be certain of the answer which is why there has been a delay and I wanted to touch base with you so you would know that your post did not get overlooked.
  • Hi Sarah,

    Again, I apologize for the delays in getting back to you. I had to do some research in the ARM architecture reference manual to get a full understanding of the operation of the memory barrier instructions.

    After my research, I found that the short answer to your question is no, a memory barrier cannot be used to perform the same task as the read back of the register. The reason for this is that the memory barrier enforces the sequencing of the read/write operations. However, the register memory is device type which means that although there is some variability in the timing of the write, the sequencing relative to the clearing of the IRQ and FIQ flags is neither a read nor write operation (this is more like a state machine state change).

    In other words, when an interrupt is asserted to the CPU and either IRQ or FIQ interrupt signals are asserted they are cleared 2-4 VBUS cycles after the peripheral interrupt signals are cleared or, to be clear, 2-4 cycles after the write completes. Since the memory barrier is simply controlling the sequencing of the reads and writes and not the timing, it really will not have the same effect as performing the read after write. The read of the written location will cause the CPU to be held off preventing any further execution until the write is completed regardless if the next instruction is a read, write or something else. This effectively minimizes the possibility of the ISR returning prior to the IRQ and FIQ interrupts being cleared.