AVR port: Support for devices with large program space, context-switch the RAMPZ and EIND registers.

This commit is contained in:
Kelvin Lawson
2010-02-21 17:38:56 +00:00
parent 0fd53909b0
commit 9a72c96305
2 changed files with 58 additions and 1 deletions

View File

@@ -113,6 +113,28 @@ archContextSwitch:
push r28
push r29
/**
* On devices with large program space we also save RAMPZ, EIND.
* Note that GCC 4.3 and later to actually save RAMPZ when called
* via an interrupt handler, which means that we end up stacking
* RAMPZ twice. However we do need to save RAMPZ for cooperative
* context switches where we are called via a function call rather
* than an ISR (at this time GCC does not save RAMPZ before function
* calls). This has the added benefit that we continue to support
* GCC < 4.3, but with the added overhead of the double-stacking for
* newer versions of GCC.
*
* An alternative method that would work for GCC >= 4.3 only would be
* to detect whether we were called from an interrupt handler and not
* save RAMPZ under those circumstances.
*/
#ifdef __AVR_3_BYTE_PC__
in r0,_SFR_IO_ADDR(RAMPZ)
push r0
in r0,_SFR_IO_ADDR(EIND)
push r0
#endif
/**
* Save the final stack pointer to the TCB. The parameter pointing to
* the old TCB is still untouched in R25-R24. We have saved R16/R17
@@ -145,12 +167,15 @@ archContextSwitch:
* <R17>
* <R28>
* <R29>
* <RAMPZ> (Only certain devices)
* <EIND> (Only certain devices)
*
* The stack frame if this was a preemptive switch looks as follows:
*
* <R1> // saved by ISR
* <R0> //
* <SREG> //
* <RAMPZ> // (Only certain devices)
* <R18> //
* <R19> //
* || //
@@ -167,6 +192,8 @@ archContextSwitch:
* <R17>
* <R28>
* <R29>
* <RAMPZ> (Only certain devices)
* <EIND> (Only certain devices)
*
*
* In addition, the thread's stack pointer (after context-save) is
@@ -203,6 +230,17 @@ archContextSwitch:
out _SFR_IO_ADDR(SPL),r16 /* Set our stack pointer to the new thread's */
out _SFR_IO_ADDR(SPH),r17 /* stack pointer, from its TCB. */
/**
* On devices with large program space we also restore RAMPZ, EIND.
*/
#ifdef __AVR_3_BYTE_PC__
pop r0
in r0,_SFR_IO_ADDR(EIND)
pop r0
in r0,_SFR_IO_ADDR(RAMPZ)
push r0
#endif
/**
* Restore registers R2-R17, R28-R29.
*/
@@ -321,6 +359,17 @@ archFirstThreadRestore:
out _SFR_IO_ADDR(SPL),r16 /* Set our stack pointer to the new thread's */
out _SFR_IO_ADDR(SPH),r17 /* stack pointer, from its TCB. */
/**
* On devices with large program space we also restore RAMPZ, EIND.
*/
#ifdef __AVR_3_BYTE_PC__
pop r0
in r0,_SFR_IO_ADDR(EIND)
pop r0
in r0,_SFR_IO_ADDR(RAMPZ)
push r0
#endif
/**
* Restore registers R2-R17, R28-R29.
*/

View File

@@ -250,6 +250,14 @@ void archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top, void (*entry_poi
*stack_ptr-- = 0x00; /* R28 */
*stack_ptr-- = 0x00; /* R29 */
/**
* On devices with large program space we also context switch RAMPZ, EIND.
*/
#ifdef __AVR_3_BYTE_PC__
*stack_ptr-- = 0x00; /* RAMPZ */
*stack_ptr-- = 0x00; /* EIND */
#endif
/**
* All thread context has now been initialised. Save the current
* stack pointer to the thread's TCB so it knows where to start
@@ -344,4 +352,4 @@ ISR (TIMER1_COMPA_vect)
ISR (BADISR_vect)
{
/* Empty */
}
}