I am seeing stack corruption running a Cortex M4 that seems to be related to interrupting multicycle instructions.
The interrupt occurs during a STMDB sp!, {r4, r5, r6, r7, r8, r9, sl, lr}
The ICI bits at the time of the interrupt equal 7. This means that the STM was partially completed, and should be resumed starting at r7.
However, if I look at the stack at the time of the interrupt, I see 4 words were written by the interrupted STM, namely r4, r5, r6, and r7. This means that
r7 will be written again when the processor resumes the STMDB instruction.
This does not happen all the time. But it forces me to disable interruption of multicycle instructions.
Hi paulgiangrossi,
you wrote that you used this instruction: STMDB sp!, {r4, r5, r6, r7, r8, r9, sl, lr}.In case of STMDB the accesses happen in order of decreasing register numbers. There is a rule, that the highest numbered register is always placed to the highest memory address and so on. (According to this rule your instruction is the same that for example: STMDB sp!, {r7-r9, lr, r5-r6, sl, r4})I think that actually lr, sl, r9 and r8 were stacked. The next register in the decreasing queue is r7 which is correctly stored in the ICI bits.
Could it happen that you didn't compared your registers with your stack precisely?
let me confirm that your RTL simulation was done with the FPGA model including the bus system? Like daith, I have a suspicion the system bus (e.g. AHB?) of FPGA might have some troubles.
Best regards,Yasuhiko Koumoto.
I've not seen a close to
about some R4 problem which may be similar. Well I'm not sure what on earth is happening there really but if it really does boil down to the same thing then there's some bug which hasnt been winkled out yet.
Unable to reproduce this problem in RTL simulation. It is reproducible
on an FPGA prototype. The project resolution is to disable multi-cycle
instruction interrupts via the Auxiliary Control Register.
The ARM support case is closed. It is most likely something with our
implementation.
Hi Yasuhiko,
We are still investigating. I will publish results once we have
determined what the problem is.
Best,
Paul Giangrossi
please tell me a detailed conclusion of this problem. I am very interested in it. As the results, was it a bug?
It's may be an idiot response but, an assembler code generated with GCC can indeed present complexities due to many non- necessary instructions. This is by no means a problem related to the processor. I understand that you are looking to encode access your stack inline later ... Do not get can get the same result using the library GCC, in order to keep the same line of programming?
Interrupt handler does not modify r4-r11. r7 has not been modified by the exception handler.
I'm sorry for late reply. Do you say that the re-start address of the STM was incorrect after returning an ISR? If it is true, It should be a problem. Could you change the Cortex-M4 part? It might be a defective product.
I believe this could happen if you're in a multithreaded environment, and a context-switch is happening in the middle of the STM instruction. However, it would happen only if there is an error in the context-switcher.
Normally (if your context switcher is as simple as it can be), this would not happen, though.
Hi Paul, I have simulated the test case as you described the details, but the processor is behaving normally. Please review the waveforms attached in the support case. The STM was interrupted at the point where it stacked r7. The EPSR correctly indicated that r8 would be the continuation point on return from exception, and that is exactly what happened.
Hi Paul, I see your company has a technical support entitlement and you have submitted this issue as a support case, so I suggest we continue the investigations in that channel where we can more openly discuss non-public technical details with you. I am just setting up the scenario you have described in my simulation testbench.
Hi Paulgiangrossi,
You shouldn't need to be doing that. As the other contributors mentioned, there are a few circumstances in which accesses will be repeated, but these are nevertheless harmless. (If the target address was volatile, the compiler should not have accessed it with a multiple access.) For normal memory, repeating the write of the same register to the same address is acceptable behavior. However, you seem to be saying that a register has been written to two different addresses, ie. stacked twice in consecutive locations.
This is not a known errata for the processor, and I am pretty sure it would have been seen in validation if it were generally true. So it follows that you have hit an unusual corner case in some respect. Can you tell us something more about the chip you are using? Do you know anything about the memory system, for example what wait-states it presents? Where is your stack located in memory? How are you observing the incorrect stack frame contents? Can you tell us about what that interrupt handler does? Does it interfere with the stack pointer in any way?
You must ensure that if r4, r5,.., r11 are modified by the exception handler, they should be stacked at the beginning of this handler and de-stacked at the end of it, because they are not automatically saved by the processor.
As in your case r7 has been altered by the exception handler, the value that will be stacked is the new (wrong) r7. But the problem is not limited to multiple Load/Store instructions, it will also happen with any instruction which uses r7 after the exception.
You should re-write the exception handler and be sure to restore r4,..,r9 to their original values before leaving the handler.
This is assembly code generated from GCC. Most functions push registers on the stack, and this results in many STMs with the stack as the destination. If a register is stored twice on the push because of an interrupt, and only popped once on the pop, the stack is corrupt and the program invariably crashes. This is the behavior I am seeing. It is very problematic.
View all questions in Cortex-M / M-Profile forum