cancel
Showing results for 
Search instead for 
Did you mean: 

LDR instruction after STR outputs old data when reading from timer peripheral

liampwll
Associate III

I have a bit of code as follows:

str   r3, [r0, #68]
ldr   r3, [r0, #68]

where [r0, #68] is TIM20.BDTR on a STM32G474. I would expect that the LDR would output the same data that was just stored, however it seems that out outputs the previous data. I also tried putting a DMB between the two instructions but the same result still occurred. Inserting 5 DMB instructions seems to cause a long enough delay that the correct data is returned.

This obviously has the potential to be problematic in a few scenarios, but I can't find any documentation from ST on this behaviour, so does anyone know if such documentation exists?

1 ACCEPTED SOLUTION

Accepted Solutions
STOne-32
ST Employee

Hi @liampwll ,

That is the best workaround :

 80128b4:       6c43            ldr     r3, [r0, #68]   @ 0x44
 80128b6:       6c43            ldr     r3, [r0, #68]   @ 0x44

Just doing a dummy Read back after the first store !  the second LDR will have the right store value.

Cheers,

STOne-32.

View solution in original post

5 REPLIES 5
liampwll
Associate III

Never mind, it turns out this is just another case of a key detail being buried in an obscure part of the reference manual:

Because MOE falling edge can be asynchronous, a resynchronization circuit has been inserted between the actual signal (acting on the outputs) and the synchronous control bit (accessed in the TIMx_BDTR register). It results in some delays between the asynchronous and the synchronous signals. In particular, if MOE is set to 1 whereas it was low, a delay must be inserted (dummy instruction) before reading it correctly. This is because the write acts on the asynchronous signal whereas the read reflects the synchronous signal.

- RM0440 Rev 8 28.3.18

However, this still seems to be wrong as a single DMB does not seem to be a long enough delay, so does anyone know what the actual required delay is?

STOne-32
ST Employee

Dear @liampwll ,

 

That register is on APB2 bus, interpretation of cycle is based on it’s own cycles . So if for example the AHBtoAPB2 ratio clock is 4 . One APB2 cycle means 4 AHB or CPU cycles etc. 
DMB is acting only at CPU Cortex / AHB cycle to wait till the Internal Cortex-M prefetch is flushed  and can not help to wait the APBs mapped registers thru the Bridges .  Do you know your AHB/APB2 configuration? And if inline with inserting dummy Reads after the STORE ? 
Let us know .

STOne-32

liampwll
Associate III

They're both /1 (HPRE = 0, PPRE = 0). The following works as expected rather than using a DMB, so something about DMB causes an issue even though it should cause at least a single cycle wait as far as I'm aware:

 

 80128ac:       6c43            ldr     r3, [r0, #68]   @ 0x44
 80128ae:       f443 4300       orr.w   r3, r3, #32768  @ 0x8000
 80128b2:       6443            str     r3, [r0, #68]   @ 0x44
 80128b4:       6c43            ldr     r3, [r0, #68]   @ 0x44
 80128b6:       6c43            ldr     r3, [r0, #68]   @ 0x44
 80128b8:       041b            lsls    r3, r3, #16

 

 

STOne-32
ST Employee

Hi @liampwll ,

That is the best workaround :

 80128b4:       6c43            ldr     r3, [r0, #68]   @ 0x44
 80128b6:       6c43            ldr     r3, [r0, #68]   @ 0x44

Just doing a dummy Read back after the first store !  the second LDR will have the right store value.

Cheers,

STOne-32.

liampwll
Associate III

@STOne-32 Could you suggest to the docs team that the register definitions really need some sort of indication when a read is not guaranteed to be equal to the previous write? Even if it's just an asterisk next to the field name without any further details, it would be incredibly helpful to not get caught out by things like this.