Skip to content

Commit 72bb476

Browse files
GhMarwenarchigup
authored andcommitted
portable: aarch64_sre: Add support for vApplicationFPUSafeIRQHandler
The application writer needs to name their IRQ handler as: 1. vApplicationIRQHandler if the IRQ handler does not use FPU registers. 2. vApplicationFPUSafeIRQHandler is the IRQ handler uses FPU registers. When the application uses vApplicationFPUSafeIRQHandler, a default implementation of vApplicationIRQHandler is used which stores FPU registers and then calls vApplicationFPUSafeIRQHandler. Note that recent versions of GCC may use FP/SIMD registers to optimize 16-bytes copy and especially when using va_start()/va_arg() functions (e.g printing some thing in IRQ handlers may trigger usage of FPU registers) This implementation is heavily inspired by both the ARM_CA9 port and the ARM_CRx_No_GIC port done in [1] [1] #1113 Signed-off-by: Marouen Ghodhbane <marouen.ghodhbane@nxp.com>
1 parent 630cfb5 commit 72bb476

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed

portable/GCC/ARM_AARCH64_SRE/port.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,27 @@
133133
*/
134134
extern void vPortRestoreTaskContext( void );
135135

136+
/*
137+
* If the application provides an implementation of vApplicationIRQHandler(),
138+
* then it will get called directly without saving the FPU registers on
139+
* interrupt entry, and this weak implementation of
140+
* vApplicationFPUSafeIRQHandler() is just provided to remove linkage errors -
141+
* it should never actually get called so its implementation contains a
142+
* call to configASSERT() that will always fail.
143+
*
144+
* If the application provides its own implementation of
145+
* vApplicationFPUSafeIRQHandler() then the implementation of
146+
* vApplicationIRQHandler() provided in portASM.S will save the FPU registers
147+
* before calling it.
148+
*
149+
* Therefore, if the application writer wants FPU registers to be saved on
150+
* interrupt entry their IRQ handler must be called
151+
* vApplicationFPUSafeIRQHandler(), and if the application writer does not want
152+
* FPU registers to be saved on interrupt entry their IRQ handler must be
153+
* called vApplicationIRQHandler().
154+
*/
155+
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) __attribute__((weak) );
156+
136157
/*-----------------------------------------------------------*/
137158

138159
/* A variable is used to keep track of the critical section nesting. This
@@ -495,3 +516,9 @@ UBaseType_t uxPortSetInterruptMask( void )
495516

496517
#endif /* configASSERT_DEFINED */
497518
/*-----------------------------------------------------------*/
519+
520+
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR )
521+
{
522+
( void ) ulICCIAR;
523+
configASSERT( ( volatile void * ) NULL );
524+
}

portable/GCC/ARM_AARCH64_SRE/portASM.S

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,8 +414,82 @@ Exit_IRQ_No_Context_Switch:
414414

415415
ERET
416416

417+
/******************************************************************************
418+
* If the application provides an implementation of vApplicationIRQHandler(),
419+
* then it will get called directly without saving the FPU registers on
420+
* interrupt entry, and this weak implementation of
421+
* vApplicationIRQHandler() will not get called.
422+
*
423+
* If the application provides its own implementation of
424+
* vApplicationFPUSafeIRQHandler() then this implementation of
425+
* vApplicationIRQHandler() will be called, save the FPU registers, and then
426+
* call vApplicationFPUSafeIRQHandler().
427+
*
428+
* Therefore, if the application writer wants FPU registers to be saved on
429+
* interrupt entry their IRQ handler must be called
430+
* vApplicationFPUSafeIRQHandler(), and if the application writer does not want
431+
* FPU registers to be saved on interrupt entry their IRQ handler must be
432+
* called vApplicationIRQHandler().
433+
*****************************************************************************/
434+
435+
.align 8
436+
.weak vApplicationIRQHandler
437+
.type vApplicationIRQHandler, %function
438+
vApplicationIRQHandler:
439+
/* Save LR and FP on the stack */
440+
STP X29, X30, [SP, #-0x10]!
441+
442+
/* Save FPU registers (32 128-bits + 2 64-bits configuration and status registers) */
443+
STP Q0, Q1, [SP,#-0x20]!
444+
STP Q2, Q3, [SP,#-0x20]!
445+
STP Q4, Q5, [SP,#-0x20]!
446+
STP Q6, Q7, [SP,#-0x20]!
447+
STP Q8, Q9, [SP,#-0x20]!
448+
STP Q10, Q11, [SP,#-0x20]!
449+
STP Q12, Q13, [SP,#-0x20]!
450+
STP Q14, Q15, [SP,#-0x20]!
451+
STP Q16, Q17, [SP,#-0x20]!
452+
STP Q18, Q19, [SP,#-0x20]!
453+
STP Q20, Q21, [SP,#-0x20]!
454+
STP Q22, Q23, [SP,#-0x20]!
455+
STP Q24, Q25, [SP,#-0x20]!
456+
STP Q26, Q27, [SP,#-0x20]!
457+
STP Q28, Q29, [SP,#-0x20]!
458+
STP Q30, Q31, [SP,#-0x20]!
459+
460+
/* Even though upper 32 bits of FPSR and FPCR are reserved, save and restore the whole 64 bits to keep 16-byte SP alignement. */
461+
MRS X9, FPSR
462+
MRS X10, FPCR
463+
STP X9, X10, [SP, #-0x10]!
417464

465+
/* Call the C handler. */
466+
BL vApplicationFPUSafeIRQHandler
467+
468+
/* Restore FPU registers */
469+
470+
LDP X9, X10, [SP], #0x10
471+
LDP Q30, Q31, [SP], #0x20
472+
LDP Q28, Q29, [SP], #0x20
473+
LDP Q26, Q27, [SP], #0x20
474+
LDP Q24, Q25, [SP], #0x20
475+
LDP Q22, Q23, [SP], #0x20
476+
LDP Q20, Q21, [SP], #0x20
477+
LDP Q18, Q19, [SP], #0x20
478+
LDP Q16, Q17, [SP], #0x20
479+
LDP Q14, Q15, [SP], #0x20
480+
LDP Q12, Q13, [SP], #0x20
481+
LDP Q10, Q11, [SP], #0x20
482+
LDP Q8, Q9, [SP], #0x20
483+
LDP Q6, Q7, [SP], #0x20
484+
LDP Q4, Q5, [SP], #0x20
485+
LDP Q2, Q3, [SP], #0x20
486+
LDP Q0, Q1, [SP], #0x20
487+
MSR FPSR, X9
488+
MSR FPCR, X10
418489

490+
/* Restore FP and LR */
491+
LDP X29, X30, [SP], #0x10
492+
RET
419493

420494
.align 8
421495
pxCurrentTCBConst: .dword pxCurrentTCB

0 commit comments

Comments
 (0)