This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit fa7f81c34ee052164914837b098936dea60fcefe
Author: Kerogit <kr....@kerogit.eu>
AuthorDate: Tue May 27 01:33:38 2025 +0200

    arch/avr: fix up_saveusercontext
    
    The up_saveusercontext function leverages USER_SAVE macro,
    which is ordinarily used as a first half of the context switch.
    This macro is therefore unsuitable to be used standalone,
    it pops return address from the stack and does not return.
    
    This patch adds missing instructions to do what would otherwise
    be done by the second half of the context switch.
    
    Tested by compiling and verifying the disassembly - the function
    no longer falls through to the next function in the program memory,
    push/pop instructions are balanced and stack contents preserved
    
    Signed-off-by: Kerogit <kr....@kerogit.eu>
---
 arch/avr/src/avr/avr_saveusercontext.S | 21 +++++++++++++++++++++
 arch/avr/src/avr/excptmacros.h         |  6 ++++++
 2 files changed, 27 insertions(+)

diff --git a/arch/avr/src/avr/avr_saveusercontext.S 
b/arch/avr/src/avr/avr_saveusercontext.S
index 60fbe1b8c5..fb37b2cd4b 100644
--- a/arch/avr/src/avr/avr_saveusercontext.S
+++ b/arch/avr/src/avr/avr_saveusercontext.S
@@ -68,5 +68,26 @@ up_saveusercontext:
 
        USER_SAVE
 
+       /* Main purpose of USER_SAVE macro is to serve as a first half
+        * of a context switch. To be able to do that, it - among other
+        * things - pops return address from the stack. The other half
+        * of context switch procedure then reverses that and pushes
+        * (different) return address back to the stack and returns
+        *
+        * The same needs to be done here, albeit simplified (we are
+        * not restoring context, just need return address back on the stack
+        * to be able to return.)
+        *
+        * Return address is loaded to r18-r20 in USER_SAVE
+        */
+
+       push r18
+       push r19
+#if AVR_PC_SIZE > 16
+       push r20
+#endif /* AVR_PC_SIZE */
+
+       ret
+
        .endfunc
        .end
diff --git a/arch/avr/src/avr/excptmacros.h b/arch/avr/src/avr/excptmacros.h
index 4ee5d21170..d0973e175c 100644
--- a/arch/avr/src/avr/excptmacros.h
+++ b/arch/avr/src/avr/excptmacros.h
@@ -346,6 +346,12 @@
 
   /* Pop the return address from the stack (PC0 then PC1).
    *  R18:19 are Call-used
+   *
+   * NOTE: up_saveusercontext in avr_saveusercontext.S uses this macro
+   * and needs to reverse this by pushing the return address back
+   * to the stack. Contents of these two/three registers must not change
+   * throughout whole macro and all changes in registers used and/or
+   * instruction ordering need to be reflected in up_saveusercontext.
    */
 
 #if AVR_PC_SIZE > 16

Reply via email to