Flesh out Z8Encore\! interrupt context switches

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@685 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2008-02-15 14:28:54 +00:00
parent 1ce0745dd8
commit b3969170d5
6 changed files with 171 additions and 54 deletions

View File

@ -245,7 +245,7 @@
/* Byte offsets: */ /* Byte offsets: */
#define XCPT_R0_OFFS (2*XCPT_RR0) /* Offset 0-15: R0-R15 */ #define XCPT_R0_OFFS (2*XCPT_RR0) /* Offset 0-15: R0-R15 */
#define XCPT_R1_OFFS (2*XCPT_RR0+1) #define XCPT_R1_OFFS (2*XCPT_RR0+1)
#define XCPT_R2_OFFS (2*XCPT_RR2) #define XCPT_R2_OFFS (2*XCPT_RR2)
#define XCPT_R3_OFFS (2*XCPT_RR2+1) #define XCPT_R3_OFFS (2*XCPT_RR2+1)
@ -261,14 +261,14 @@
#define XCPT_R13_OFFS (2*XCPT_RR12+1) #define XCPT_R13_OFFS (2*XCPT_RR12+1)
#define XCPT_R14_OFFS (2*XCPT_R1R4) #define XCPT_R14_OFFS (2*XCPT_R1R4)
#define XCPT_R15_OFFS (2*XCPT_R1R4+1) #define XCPT_R15_OFFS (2*XCPT_R1R4+1)
#define XCPT_UNUSED_OFFS (2*XCPT_IRQCTL) /* Offset 16: Unused (zero) */ #define XCPT_UNUSED_OFFS (2*XCPT_IRQCTL) /* Offset 16: Unused (zero) */
#define XCPT_IRQCTL_OFFS (2*XCPT_IRQCTL+1) /* offset 17: IRQCTL register */ #define XCPT_IRQCTL_OFFS (2*XCPT_IRQCTL+1) /* offset 17: IRQCTL register */
#define XCPT_SPH_OFFS (2*XCPT_SP) /* Offset 18: SP[8:15] */ #define XCPT_SPH_OFFS (2*XCPT_SP) /* Offset 18: SP[8:15] */
#define XCPT_SPL_OFFS (2*XCPT_SP+1) /* Offset 19: SP[0:7] */ #define XCPT_SPL_OFFS (2*XCPT_SP+1) /* Offset 19: SP[0:7] */
#define XCPT_RP_OFFS (2*XCPT_I) /* Offset 20: Register pointer */ #define XCPT_RP_OFFS (2*XCPT_RPFLAGS) /* Offset 20: Register pointer */
#define XCPT_FLAGS_OFFS (2*XCPT_I+1) /* Offset 21: FLAGS */ #define XCPT_FLAGS_OFFS (2*XCPT_RPFLAGS+1) /* Offset 21: FLAGS */
#define XCPT_PCH_OFFS (2*XCPT_PC) /* Offset 22: PC[8:15] */ #define XCPT_PCH_OFFS (2*XCPT_PC) /* Offset 22: PC[8:15] */
#define XCPT_PCL_OFFS (2*XCPT_PC+1) /* Offset 23: PC[0:7] */ #define XCPT_PCL_OFFS (2*XCPT_PC+1) /* Offset 23: PC[0:7] */
#define XCPTCONTEXT_SIZE (2*XCPTCONTEXT_REGS) #define XCPTCONTEXT_SIZE (2*XCPTCONTEXT_REGS)

View File

@ -83,7 +83,7 @@ void up_sigdeliver(void)
{ {
#ifndef CONFIG_DISABLE_SIGNALS #ifndef CONFIG_DISABLE_SIGNALS
FAR _TCB *rtcb = (_TCB*)g_readytorun.head; FAR _TCB *rtcb = (_TCB*)g_readytorun.head;
uint16 regs[XCPTCONTEXT_REGS]; chipret_t regs[XCPTCONTEXT_REGS];
sig_deliver_t sigdeliver; sig_deliver_t sigdeliver;
/* Save the errno. This must be preserved throughout the signal handling /* Save the errno. This must be preserved throughout the signal handling

View File

@ -41,7 +41,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h> #include <string.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/sched.h>
#include "chip/chip.h" #include "chip/chip.h"
#include "up_internal.h" #include "up_internal.h"
@ -77,7 +79,7 @@
* *
****************************************************************************/ ****************************************************************************/
void up_initial_state(_TCB *tcb) void up_initial_state(FAR _TCB *tcb)
{ {
struct xcptcontext *xcp = &tcb->xcp; struct xcptcontext *xcp = &tcb->xcp;
@ -85,9 +87,9 @@ void up_initial_state(_TCB *tcb)
memset(xcp, 0, sizeof(struct xcptcontext)); memset(xcp, 0, sizeof(struct xcptcontext));
#ifndef CONFIG_SUPPRESS_INTERRUPTS #ifndef CONFIG_SUPPRESS_INTERRUPTS
xcp->regs[XCPT_IRQCTL] = %0080; /* IRQE bit will enable interrupts */ xcp->regs[XCPT_IRQCTL] = 0x0080; /* IRQE bit will enable interrupts */
#endif #endif
xcp->regs[XCPT_RPFLAGS] = %e000; /* RP=%e0 */ xcp->regs[XCPT_RPFLAGS] = 0xe000; /* RP=%e0 */
xcp->regs[XCPT_SP] = (chipreg_t)tcb->adj_stack_ptr; xcp->regs[XCPT_SP] = (chipreg_t)tcb->adj_stack_ptr;
xcp->regs[XCPT_PC] = (chipreg_t)tcb->start; xcp->regs[XCPT_PC] = (chipreg_t)tcb->start;
} }

View File

@ -101,23 +101,21 @@ _z8_restorecontext:
* address * address
*/ */
ld r1, #%e0 /* r1 = destination address */ clr r0 /* rr0 = destination address */
ldx r1, XCPT_RP_OFFS(rr6)
ld r2, r6 /* rr2 = source address */ ld r2, r6 /* rr2 = source address */
ld r3, r7 ld r3, r7
ld r4, #16 /* r4 = number of bytes to copy */ ld r4, #16 /* r4 = number of bytes to copy */
cp r2, #0
jr z, _z8_restore2
_z8_restore1: _z8_restore:
ldx r0, @rr2 ldx r5, @rr2
ld @r1, r0 ldx @rr0, r5
inc r1 incw rr0
incw rr2 incw rr2
djnz r4, _z8_restore1 djnz r4, _z8_restore
/* Set the new stack pointer */ /* Set the new stack pointer */
_z8_restore2:
ldx r0, XCPT_SPH_OFFS(rr6) ldx r0, XCPT_SPH_OFFS(rr6)
ldx r1, XCPT_SPL_OFFS(rr6) ldx r1, XCPT_SPL_OFFS(rr6)
ldx sph, r0 ldx sph, r0
@ -130,9 +128,10 @@ _z8_restore2:
push r1 push r1
push r0 push r0
/* Recover the flags settings.. but don't restore the flags yet */ /* Recover the flags and RP settings.. but don't restore them yet */
ldx r1, XCPT_FLAGS_OFFS(rr6) ldx r1, XCPT_FLAGS_OFFS(rr0)
ldx r2, XCPT_RP_OFFS(rr0)
/* Determine whether interrupts must be enabled on return. This /* Determine whether interrupts must be enabled on return. This
* would be nicer to do below, but later we will need to preserve * would be nicer to do below, but later we will need to preserve
@ -149,7 +148,7 @@ _z8_restore2:
/* Restore the user register page and return with interrupts disabled */ /* Restore the user register page and return with interrupts disabled */
srp #%e0 /* Does not effect flags */ ldx rp, r2 /* Does not effect flags */
ret /* Does not effect flags */ ret /* Does not effect flags */
_z8_returnenabled: _z8_returnenabled:
@ -159,7 +158,7 @@ _z8_returnenabled:
/* Restore the user register page, re-enable interrupts and return */ /* Restore the user register page, re-enable interrupts and return */
srp #%e0 /* Does not effect flags */ ldx rp, r2 /* Does not effect flags */
ei /* Does not effect flags */ ei /* Does not effect flags */
ret /* Does not effect flags */ ret /* Does not effect flags */

View File

@ -52,50 +52,52 @@
* External References / External Definitions * External References / External Definitions
**************************************************************************/ **************************************************************************/
xref _up_doirq:ROM
#if defined(ENCORE_VECTORS) #if defined(ENCORE_VECTORS)
xdef _z8_wdt_handler xdef _z8_wdt_handler
xdef _z8_trap_handler xdef _z8_trap_handler
if EZ8_TIMER3=1 if EZ8_TIMER3=1
xdef _z8_timer2_handler xdef _z8_timer2_handler
endif endif
xdef _z8_timer1_handler xdef _z8_timer1_handler
xdef _z8_timer0_handler xdef _z8_timer0_handler
if EZ8_UART0=1 if EZ8_UART0=1
xdef _z8_uart0rx_handler xdef _z8_uart0rx_handler
xdef _z8_uart0tx_handler xdef _z8_uart0tx_handler
endif endif
if EZ8_I2C=1 if EZ8_I2C=1
xdef _z8_i2c_handler xdef _z8_i2c_handler
endif endif
if EZ8_SPI=1 if EZ8_SPI=1
xdef _z8_spi_handler xdef _z8_spi_handler
endif endif
if EZ8_ADC=1 if EZ8_ADC=1
xdef _z8_adc_handler xdef _z8_adc_handler
endif endif
xdef _z8_p7ad_handler xdef _z8_p7ad_handler
xdef _z8_p6ad_handler xdef _z8_p6ad_handler
xdef _z8_p5ad_handler xdef _z8_p5ad_handler
xdef _z8_p4ad_handler xdef _z8_p4ad_handler
xdef _z8_p3ad_handler xdef _z8_p3ad_handler
xdef _z8_p2ad_handler xdef _z8_p2ad_handler
xdef _z8_p1ad_handler xdef _z8_p1ad_handler
xdef _z8_p0ad_handler xdef _z8_p0ad_handler
if EZ8_TIMER4=1 if EZ8_TIMER4=1
xdef _z8_timer3_handler xdef _z8_timer3_handler
endif endif
if EZ8_UART1=1 if EZ8_UART1=1
xdef _z8_uart1rx_handler xdef _z8_uart1rx_handler
xdef _z8_uart1tx_handler xdef _z8_uart1tx_handler
endif endif
if EZ8_DMA=1 if EZ8_DMA=1
xdef _z8_dma_handler xdef _z8_dma_handler
endif endif
if EZ8_PORT1=0 if EZ8_PORT1=0
xdef _z8_c3_handler xdef _z8_c3_handler
xdef _z8_c2_handler xdef _z8_c2_handler
xdef _z8_c1_handler xdef _z8_c1_handler
xdef _z8_c0_handler xdef _z8_c0_handler
endif endif
/**************************************************************************/ /**************************************************************************/
@ -233,13 +235,14 @@ endif
**************************************************************************/ **************************************************************************/
ENTER : MACRO val ENTER : MACRO val
pushx rp /* Save the current RP value in the stack */
srp #%f0 /* Load the interrupt register pointer */ srp #%f0 /* Load the interrupt register pointer */
ld r0, #val /* Pass the new value in r0 ld r0, #val /* Pass the new value in r0
jr _z8_common_handler /* The rest of the handling is common */ jr _z8_common_handler /* The rest of the handling is common */
ENDMAC ENTER ENDMAC ENTER
LEAVE : MACRO LEAVE : MACRO
srp #%e0 /* Restore the user register pointer */ popx rp /* Restore the user register pointer */
iret /* And return from interrupt */ iret /* And return from interrupt */
ENDMAC LEAVE ENDMAC LEAVE
@ -738,6 +741,119 @@ _z8_wotrap_handler:
**************************************************************************/ **************************************************************************/
_z8_common_handler: _z8_common_handler:
/* Pass the address of the IRQ stack frame */
ldx r2, sph /* rr2 = stack pointer */
ldx r3, spl
push r3 /* Pass as a parameter */
push r2
/* Pass the IRQ number */
push r0
/* Process the interrupt */
call _up_doirq /* Call the IRQ handler */
/* Release arguments from the stack */
pop r4 /* Discard the IRQ argument */
pop r2 /* Recover the stack pointer parameter */
pop r3
/* If a interrupt level context switch occurred, then the
* return value will be the same as the input value
*/
cp r0, r2 /* Same as the return value? */
jr nz, _z8_switch
cp r1, r3
jr z, _z8_noswitch
/* A context switch occurs. Restore the use context.
* rr0 = pointer to context structgure.
*/
_z8_switch:
/* Destroy the interrupt return information on the stack */
pop r4 /* Destroy saved RP */
pop r4 /* Destroy saved flags */
pop r4 /* Destroy saved return address */
pop r4
/* Copy all registers into the user register area. */
clr r2 /* rr2 = destination address */
ldx r3, XCPT_RP_OFFS(rr0)
ld r4, r0 /* rr4 = source address */
ld r5, r1
ld r6, #16 /* r6 = number of bytes to copy */
_z8_restore:
ldx r7, @rr4
ldx @rr2, r7
incw rr2
incw rr4
djnz r6, _z8_restore
/* Set the new stack pointer */
ldx r2, XCPT_SPH_OFFS(rr0)
ldx r3, XCPT_SPL_OFFS(rr0)
ldx sph, r2
ldx spl, r3
/* Push the return address onto the stack */
ldx r2, XCPT_PCH_OFFS(rr0)
ldx r3, XCPT_PCL_OFFS(rr0)
push r3
push r2
/* Recover the flags and RP settings.. but don't restore them yet */
ldx r3, XCPT_FLAGS_OFFS(rr0)
ldx r4, XCPT_RP_OFFS(rr0)
/* Determine whether interrupts must be enabled on return. This
* would be nicer to do below, but later we will need to preserve
* the condition codes in the flags.
*/
ldx r2, XCPT_IRQCTL_OFFS(rr0)
tm r2, #%80
jr nz, _z8_returnenabled
/* Restore the flag settings */
ldx flags, r3
/* Restore the user register page and return with interrupts disabled.
* Note that we cannot use the iret instruction because it unconditionally
* re-enabled interrupts
*/
ldx rp, r4 /* Does not effect flags */
ret /* Does not effect flags */
_z8_returnenabled:
/* Restore the flag settings */
ldx flags, r1
/* Restore the user register page, re-enable interrupts and return.
* Note that we cannot use the iret instruction because it unconditionally
* re-enabled interrupts
*/
ldx rp, r4 /* Does not effect flags */
ei /* Does not effect flags */
ret /* Does not effect flags */
_z8_noswitch:
LEAVE LEAVE
/************************************************************************** /**************************************************************************

View File

@ -79,7 +79,7 @@ void z80_sigsetup(FAR _TCB *tcb, sig_deliver_t sigdeliver, FAR chipreg_t *regs)
/* Then set up to vector to the trampoline with interrupts disabled */ /* Then set up to vector to the trampoline with interrupts disabled */
regs[XCPT_PC] = (uint16)up_sigdeliver; regs[XCPT_PC] = (chipreg_t)up_sigdeliver;
regs[XCPT_I] = 0; regs[XCPT_I] = 0;
} }