2018-11-30 01:40 AM
Dear all,
I'm checking if a variable assignement is atomic or not. I know that are many stuff on this subject but I need to approach from a low level perspective to better know what happen under the scene and then have better control of my code.
To do that I'm looking the dissassembler window during the debugging stage, I'm using the IAR IDE v8.32.1 but my question is not related to this specific IDE/Compiler.
A variable with name Nstep_total is update under ISR and is also declared to be volatile, here below my declaration:
volatile int32_t Nstep_total = 0; // Updated under ISR
Under the ISR code I've to write the Nstep_total variable and into the main code I have only to perform a read. This operation is made by means of a temporary variable called Nstep_total_tmp definited into my main code as.
int32_t Nstep_total_tmp = 0; // Temporary variable used to store the Nstep_total
in other words, instead to use directly the Nstep_total variable in my calculations, I simply do an assignement to another variable and then I'll use this temporary variable value for my purpose.
What I need to discover is if this assigment is performed as atomic or not in order to avoid any strange code behaviour.
Here below I written the piece of code that perform the assignement of the Nstep_total to the temporary Nstep_total_tmp variable.
Nstep_total_tmp = Nstep_total;
0x80011b8: 0x4843 LDR.N R0, [PC, #0x10c] ; Nstep_total
0x80011ba: 0x6800 LDR R0, [R0]
0x80011bc: 0x0005 MOVS R5, R0
Into the assembly window I can see a LDR.N instruction, from the IAR Asembler guide I can read:
"By specifying a 16-bit version explicitly with the LDR.N instruction, a 16-bit instruction is always generated. This may lead to the constant being placed in the literal pool, even though a 32-bit instruction could have loaded the value directly using MOV or MVN."
so the meaning of this instruction would be load a 16 bit address into the register R0, address is contained into the location ad address PC+0x10c, performing this sum with PC=0x80011b8 give 0x80012c4, checking at this address I can see:
...
0x80012b8: 0x2000008c DC32 cSPIN_rx_data
0x80012bc: 0x2000000c DC32 cSPIN_RegsStruct
0x80012c0: 0x004fffff DC32 0x4fffff (5242879)
0x80012c4: 0x2000009a DC32 button3
0x80012c8: 0x2000007c DC32 Nstep_total
0x80012cc: 0x20000084 DC32 Delta_step
0x80012d0: 0x20000080 DC32 Nstep_current
0x80012d4: 0x20000088 DC32 Delta_step_tmp
0x80012d8: 0x2000000a DC32 Dir_old
...
the correct variable should be Nstep_total which is at the next place, may be I've to consider the PC +4 byte instead the value where the breakpoint is? Someone can please let me know some about this point?
After that the Nstep_total value is loaded into the R0 general purpose register, the LDR instruction is able to load in a single cycle a 32 bit of data so from this it appear to me that this operation should be atomic, I'm thinking correctly?
The next instruction (MOVS) take the content of the R0 general purpose register and move it into the Nstep_total_tmp temporary variable then, If I correctly understand the code, the assignement performed by the LDR instruction is atomic and then I should be fully protected from any side effect in my code from the copresence of ISR variable writing and the main access to the Nstep_total variable.
I'm doing right or I've missed something?
Thank for your time!
Best regards
Fabio
Solved! Go to Solution.
2018-11-30 06:15 AM
PC points to the instruction going to be executed next.
2018-11-30 01:51 AM
Yes, reading an aligned variable of up to 4 byte length is atomic on a 32 bit CPU.
2018-11-30 02:44 AM
Thank you @Uwe Bonnes ,
could you please let me know also about the apparent discrepance between the PC + 0x10c and the real address of my variable? There are 4 bytes in difference..
Thank!
BR
Fabio
2018-11-30 06:15 AM
PC points to the instruction going to be executed next.