Author Topic: How does ST 32F4 know when an ISR has finished?  (Read 2322 times)

0 Members and 1 Guest are viewing this topic.

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4048
  • Country: nz
Re: How does ST 32F4 know when an ISR has finished?
« Reply #25 on: May 10, 2022, 12:55:18 pm »
@BruceHoult This function is not marked as "interrupt" in C(++). So it doesn't know that r3 is already pushed by hardware before IRQ handler entry.

But in normal ABI (non-interrupt) functions, r3 is anyway a function argument/scratch register that you are free to nuke without saving.
 
The following users thanked this post: hans

Offline hans

  • Super Contributor
  • ***
  • Posts: 1643
  • Country: nl
Re: How does ST 32F4 know when an ISR has finished?
« Reply #26 on: May 10, 2022, 05:01:13 pm »
Looks like it has everything to do with 8-byte stack alignment, as you said which is part of the ABI. If greater body of functions are included, then eventually GCC will switch to a push {lr} and sub sp, sp, #xx output.

For xx=4, it's more space efficient for the compiler to generate push {rx, lr}, where rx is r3 in this case, so that the stack is always 8-byte aligned. The extra push vs subtraction is as fast, so putting everything in 1 push is more space efficient.

As discussed in the GCC ticket, it looks like more modern Cortex-M3 cores don't really care about stack alignment and can have the STKALIGN bit set low. Then this r3 push/pop is unnecessary. On m0 and m7 it is necessary, as STKALIGN bit is fixed high. I read on m7 it is necessary because the AXI bus is 64-bit wide.

One thing that does come to mind is which I don't have an answer to.. what happens when you use this 'interrupt' prologue/epilogue while running any kind of generic C code, and say that code runs on the main sp where in the middle of a function body it is not required to keep a 4-byte stack alignment. Therefore any IRQ can occur while the instantaneous sp is not 8-byte aligned. Is this going to cause UB or faults? Or is that something that will be handled/guaranteed by the hardware or microcode upon entering the interrupt/exception context?  :-//
In the linked godbolt example, this is what the prologue code seems to be doing, regardless if any stack alignment is necessary further down in the function.

Edit: oof, GCC is getting confused: https://godbolt.org/z/T511Kxch8
Code: [Select]
TIM7_IrqHandler():
  mov r0, sp
  ldr r3, .L3
  movs r2, #0
  bic r1, r0, #7
  ldr r3, [r3]
  mov sp, r1
  push {r0}
  pop {r0}
  str r2, [r3]
  mov sp, r0
  bx lr
.L3:
  .word .LANCHOR0
sr:
  .word -889323520
:-//

Edit2: @newbrain Thanks for the explanation. Yes it seems the interrupt attribute is unnecessary then.
« Last Edit: May 10, 2022, 07:56:20 pm by hans »
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1721
  • Country: se
Re: How does ST 32F4 know when an ISR has finished?
« Reply #27 on: May 10, 2022, 07:02:28 pm »
As discussed in the GCC ticket, it looks like more modern Cortex-M3 cores don't really care about stack alignment and can have the STKALIGN bit set low. Then this r3 push/pop is unnecessary. On m0 and m7 it is necessary, as STKALIGN bit is fixed high. I read on m7 it is necessary because the AXI bus is 64-bit wide.

One thing that does come to mind is which I don't have an answer to.. what happens when you use this 'interrupt' prologue/epilogue while running any kind of generic C code, and say that code runs on the main sp where in the middle of a function body it is not required to keep a 4-byte stack alignment. Therefore any IRQ can occur while the instantaneous sp is not 8-byte aligned. Is this going to cause UB or faults? Or is that something that will be handled/guaranteed by the hardware or microcode upon entering the interrupt/exception context?  :-//
In the linked godbolt example, this is what the prologue code seems to be doing, regardless if any stack alignment is necessary further down in the function.
I think you are misinterpreting the meaning of STKALIGN bit:
When this is set to 1, the stack is automatically adjusted to be 64 bit aligned - Arm discourage 0 both for use and as a default value in a couple of places in the ARM.
So, nothing special is needed in an exception handling function (the interrupt attribute is totally redundant) for cores where it is RAO (Read As One).
From the Armv7-M ARM:
Quote
STKALIGN, bit[9] Determines whether the exception entry sequence guarantees 8-byte stack framealignment,
adjusting the SP if necessary before saving state:
0 Guaranteed SP alignment is 4-byte, no SP adjustment is performed.
1 8-byte alignment guaranteed, SP adjusted if necessary.
Whether this bit is RO or RW is IMPLEMENTATION DEFINED .
The reset value of this bit is IMPLEMENTATION DEFINED. Arm recommends that this bit
resets to 1.
And:
Quote
Operation of 8-byte stack alignment
On an exception entry when CCR.STKALIGN is set to 1, the exception entry sequence ensures that the stack pointer
in use before the exception entry has 8-byte alignment, by adjusting its alignment if necessary. When the processor
pushes the PSR value to the stack it uses bit[9] of the stacked PSR value to indicate whether it realigned the stack.
« Last Edit: May 10, 2022, 07:04:47 pm by newbrain »
Nandemo wa shiranai wa yo, shitteru koto dake.
 
The following users thanked this post: hans


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf