arch/avr: save RAMPZ register into thread context
On chips that have it, RAMPZ is part of the thread context and needs to be saved as well.
This commit is contained in:
parent
958b18f25e
commit
88a66f18e6
10 changed files with 96 additions and 10 deletions
|
|
@ -81,7 +81,13 @@
|
|||
|
||||
# define NR_IRQS 34
|
||||
# define AVR_PC_SIZE 16
|
||||
# define XCPTCONTEXT_REGS 37 /* Size of the register state save array (in bytes) */
|
||||
# define XCPTCONTEXT_REGS 38 /* Size of the register state save array (in bytes) */
|
||||
|
||||
# if defined(CONFIG_AVR_HAS_RAMPZ)
|
||||
# define AVR_HAS_RAMPZ
|
||||
# else
|
||||
# error CONFIG_AVR_HAS_RAMPZ is supposed to be set for this chip
|
||||
# endif
|
||||
|
||||
#elif defined(CONFIG_ARCH_CHIP_ATMEGA1284P)
|
||||
|
||||
|
|
@ -122,7 +128,13 @@
|
|||
|
||||
# define NR_IRQS 34
|
||||
# define AVR_PC_SIZE 16
|
||||
# define XCPTCONTEXT_REGS 37 /* Size of the register state save array (in bytes) */
|
||||
# define XCPTCONTEXT_REGS 38 /* Size of the register state save array (in bytes) */
|
||||
|
||||
# if defined(CONFIG_AVR_HAS_RAMPZ)
|
||||
# define AVR_HAS_RAMPZ
|
||||
# else
|
||||
# error CONFIG_AVR_HAS_RAMPZ is supposed to be set for this chip
|
||||
# endif
|
||||
|
||||
#elif defined(CONFIG_ARCH_CHIP_ATMEGA2560)
|
||||
|
||||
|
|
@ -185,7 +197,13 @@
|
|||
|
||||
# define NR_IRQS 58
|
||||
# define AVR_PC_SIZE 24
|
||||
# define XCPTCONTEXT_REGS 38 /* Size of the register state save array (in bytes) */
|
||||
# define XCPTCONTEXT_REGS 39 /* Size of the register state save array (in bytes) */
|
||||
|
||||
# if defined(CONFIG_AVR_HAS_RAMPZ)
|
||||
# define AVR_HAS_RAMPZ
|
||||
# else
|
||||
# error CONFIG_AVR_HAS_RAMPZ is supposed to be set for this chip
|
||||
# endif
|
||||
|
||||
#else
|
||||
#error "Unrecognized chip"
|
||||
|
|
|
|||
|
|
@ -72,16 +72,24 @@
|
|||
#define REG_R2 29
|
||||
#define REG_R1 30 /* r1 - the "zero" register */
|
||||
#define REG_R0 31 /* r0 */
|
||||
#define REG_SREG 32 /* Status register */
|
||||
#define REG_R25 33 /* r24-r25 */
|
||||
#define REG_R24 34
|
||||
|
||||
#if defined(AVR_HAS_RAMPZ)
|
||||
# define REG_RAMPZ 32 /* RAMPZ register for ELPM instruction */
|
||||
# define REG_OFFSET_RAMPZ 1
|
||||
#else
|
||||
# define REG_OFFSET_RAMPZ 0 /* MCU does not have RAMPZ */
|
||||
#endif
|
||||
|
||||
#define REG_SREG (32 + REG_OFFSET_RAMPZ) /* Status register */
|
||||
#define REG_R25 (33 + REG_OFFSET_RAMPZ) /* r24-r25 */
|
||||
#define REG_R24 (34 + REG_OFFSET_RAMPZ)
|
||||
|
||||
/* The program counter is automatically pushed when the interrupt occurs */
|
||||
|
||||
#define REG_PC0 35 /* PC */
|
||||
#define REG_PC1 36
|
||||
#define REG_PC0 (35 + REG_OFFSET_RAMPZ) /* PC */
|
||||
#define REG_PC1 (36 + REG_OFFSET_RAMPZ)
|
||||
#if AVR_PC_SIZE > 16
|
||||
# define REG_PC2 37
|
||||
# define REG_PC2 (37 + REG_OFFSET_RAMPZ)
|
||||
#endif
|
||||
|
||||
#define XCPTCONTEXT_SIZE XCPTCONTEXT_REGS
|
||||
|
|
@ -107,6 +115,9 @@ struct xcptcontext
|
|||
uint8_t saved_pc0;
|
||||
#if defined(REG_PC2)
|
||||
uint8_t saved_pc2;
|
||||
#endif
|
||||
#if defined(REG_RAMPZ)
|
||||
uint8_t saved_rampz;
|
||||
#endif
|
||||
uint8_t saved_sreg;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,16 +12,19 @@ choice
|
|||
|
||||
config ARCH_CHIP_ATMEGA128
|
||||
bool "ATMega128"
|
||||
select AVR_HAS_RAMPZ
|
||||
---help---
|
||||
Atmel ATMega128 8-bit AVR.
|
||||
|
||||
config ARCH_CHIP_ATMEGA1284P
|
||||
bool "ATMega1284P"
|
||||
select AVR_HAS_RAMPZ
|
||||
---help---
|
||||
Atmel ATMega1284P 8-bit AVR.
|
||||
|
||||
config ARCH_CHIP_ATMEGA2560
|
||||
bool "ATMega2560"
|
||||
select AVR_HAS_RAMPZ
|
||||
---help---
|
||||
Atmel ATMega2560 8-bit AVR.
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,9 @@
|
|||
* - If RAMPZ is not present, support for LPMX is assumed
|
||||
*/
|
||||
|
||||
#define HAVE_RAMPZ 1
|
||||
#ifdef AVR_HAS_RAMPZ
|
||||
# define HAVE_RAMPZ 1
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* External Symbols
|
||||
|
|
|
|||
|
|
@ -73,4 +73,8 @@ config AVR_HAS_MEMX_PTR
|
|||
of RAM needed to hold this static data.
|
||||
|
||||
endmenu # Atmel AVR Toolchain options
|
||||
|
||||
config AVR_HAS_RAMPZ
|
||||
bool
|
||||
|
||||
endif # ARCH_FAMILY_AVR
|
||||
|
|
|
|||
|
|
@ -107,6 +107,12 @@ void up_initial_state(struct tcb_s *tcb)
|
|||
xcp->regs[REG_PC2] = (uint8_t)((uintptr_t)tcb->start & 0xff);
|
||||
#endif
|
||||
|
||||
/* Set RAMPZ to zero, the default value (if the MCU has one) */
|
||||
|
||||
#if defined(REG_RAMPZ)
|
||||
xcp->regs[REG_RAMPZ] = 0;
|
||||
#endif
|
||||
|
||||
/* Enable or disable interrupts, based on user configuration */
|
||||
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
|
|
|
|||
|
|
@ -91,5 +91,10 @@ void up_dump_register(void *dumpregs)
|
|||
regs[REG_PC2], regs[REG_SPH],
|
||||
regs[REG_SPL], regs[REG_SREG]);
|
||||
#endif
|
||||
|
||||
#if defined(REG_RAMPZ)
|
||||
_alert("RAMPZ: %02x\n",
|
||||
regs[REG_RAMPZ]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,9 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||
tcb->xcp.saved_pc1 = up_current_regs()[REG_PC1];
|
||||
#if defined(REG_PC2)
|
||||
tcb->xcp.saved_pc2 = up_current_regs()[REG_PC2];
|
||||
#endif
|
||||
#if defined(REG_RAMPZ)
|
||||
tcb->xcp.saved_rampz = up_current_regs()[REG_RAMPZ];
|
||||
#endif
|
||||
tcb->xcp.saved_sreg = up_current_regs()[REG_SREG];
|
||||
|
||||
|
|
@ -168,6 +171,9 @@ void up_schedule_sigaction(struct tcb_s *tcb)
|
|||
tcb->xcp.saved_pc1 = tcb->xcp.regs[REG_PC1];
|
||||
#if defined(REG_PC2)
|
||||
tcb->xcp.saved_pc2 = tcb->xcp.regs[REG_PC2];
|
||||
#endif
|
||||
#if defined(REG_RAMPZ)
|
||||
tcb->xcp.saved_rampz = tcb->xcp.regs[REG_RAMPZ];
|
||||
#endif
|
||||
tcb->xcp.saved_sreg = tcb->xcp.regs[REG_SREG];
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@ void avr_sigdeliver(void)
|
|||
regs[REG_PC1] = rtcb->xcp.saved_pc1;
|
||||
#if defined(REG_PC2)
|
||||
regs[REG_PC2] = rtcb->xcp.saved_pc2;
|
||||
#endif
|
||||
#if defined(REG_RAMPZ)
|
||||
regs[REG_RAMPZ] = rtcb->xcp.saved_rampz;
|
||||
#endif
|
||||
regs[REG_SREG] = rtcb->xcp.saved_sreg;
|
||||
|
||||
|
|
|
|||
|
|
@ -148,6 +148,13 @@
|
|||
ori r25, (1 << SREG_I) /* Interrupts re-enabled on restore */
|
||||
push r25
|
||||
|
||||
/* Save RAMPZ if the MCU has it */
|
||||
|
||||
#ifdef AVR_HAS_RAMPZ
|
||||
in r25, _SFR_IO_ADDR(RAMPZ)
|
||||
push r25
|
||||
#endif
|
||||
|
||||
/* Save R0 -- the scratch register and the zero register
|
||||
* (which may not be zero). R1 must be zero for our purposes
|
||||
*/
|
||||
|
|
@ -296,6 +303,13 @@
|
|||
pop r1
|
||||
pop r0
|
||||
|
||||
/* Restore RAMPZ if the MCU has it */
|
||||
|
||||
#ifdef AVR_HAS_RAMPZ
|
||||
pop r24
|
||||
out _SFR_IO_ADDR(RAMPZ), r24
|
||||
#endif
|
||||
|
||||
/* Restore the status register (probably enabling interrupts) */
|
||||
|
||||
pop r24 /* Restore the status register */
|
||||
|
|
@ -392,6 +406,13 @@
|
|||
|
||||
adiw r26, 1
|
||||
|
||||
#ifdef AVR_HAS_RAMPZ
|
||||
/* Save RAMPZ if the MCU has it */
|
||||
|
||||
in r0, _SFR_IO_ADDR(RAMPZ)
|
||||
st X+, r0
|
||||
#endif
|
||||
|
||||
/* Save the status register
|
||||
* (probably not necessary since interrupts are disabled)
|
||||
*/
|
||||
|
|
@ -544,6 +565,13 @@
|
|||
|
||||
ld r0, x+
|
||||
|
||||
#ifdef AVR_HAS_RAMPZ
|
||||
/* Restore RAMPZ if the MCU has it */
|
||||
|
||||
ld r24, X+
|
||||
out _SFR_IO_ADDR(RAMPZ), r24
|
||||
#endif
|
||||
|
||||
/* The following control flow split is required to eliminate non-atomic
|
||||
* interrupt_enable - return sequence.
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue