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: */
#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_R2_OFFS (2*XCPT_RR2)
#define XCPT_R3_OFFS (2*XCPT_RR2+1)
@ -261,14 +261,14 @@
#define XCPT_R13_OFFS (2*XCPT_RR12+1)
#define XCPT_R14_OFFS (2*XCPT_R1R4)
#define XCPT_R15_OFFS (2*XCPT_R1R4+1)
#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_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_RP_OFFS (2*XCPT_I) /* Offset 20: Register pointer */
#define XCPT_FLAGS_OFFS (2*XCPT_I+1) /* Offset 21: FLAGS */
#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_UNUSED_OFFS (2*XCPT_IRQCTL) /* Offset 16: Unused (zero) */
#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_SPL_OFFS (2*XCPT_SP+1) /* Offset 19: SP[0:7] */
#define XCPT_RP_OFFS (2*XCPT_RPFLAGS) /* Offset 20: Register pointer */
#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_PCL_OFFS (2*XCPT_PC+1) /* Offset 23: PC[0:7] */
#define XCPTCONTEXT_SIZE (2*XCPTCONTEXT_REGS)

View File

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

View File

@ -41,7 +41,9 @@
#include <sys/types.h>
#include <string.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include "chip/chip.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;
@ -85,9 +87,9 @@ void up_initial_state(_TCB *tcb)
memset(xcp, 0, sizeof(struct xcptcontext));
#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
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_PC] = (chipreg_t)tcb->start;
}

View File

@ -101,23 +101,21 @@ _z8_restorecontext:
* 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 r3, r7
ld r4, #16 /* r4 = number of bytes to copy */
cp r2, #0
jr z, _z8_restore2
_z8_restore1:
ldx r0, @rr2
ld @r1, r0
inc r1
_z8_restore:
ldx r5, @rr2
ldx @rr0, r5
incw rr0
incw rr2
djnz r4, _z8_restore1
djnz r4, _z8_restore
/* Set the new stack pointer */
_z8_restore2:
ldx r0, XCPT_SPH_OFFS(rr6)
ldx r1, XCPT_SPL_OFFS(rr6)
ldx sph, r0
@ -130,9 +128,10 @@ _z8_restore2:
push r1
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
* 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 */
srp #%e0 /* Does not effect flags */
ldx rp, r2 /* Does not effect flags */
ret /* Does not effect flags */
_z8_returnenabled:
@ -159,7 +158,7 @@ _z8_returnenabled:
/* 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 */
ret /* Does not effect flags */

View File

@ -52,50 +52,52 @@
* External References / External Definitions
**************************************************************************/
xref _up_doirq:ROM
#if defined(ENCORE_VECTORS)
xdef _z8_wdt_handler
xdef _z8_trap_handler
xdef _z8_wdt_handler
xdef _z8_trap_handler
if EZ8_TIMER3=1
xdef _z8_timer2_handler
xdef _z8_timer2_handler
endif
xdef _z8_timer1_handler
xdef _z8_timer0_handler
xdef _z8_timer1_handler
xdef _z8_timer0_handler
if EZ8_UART0=1
xdef _z8_uart0rx_handler
xdef _z8_uart0tx_handler
xdef _z8_uart0rx_handler
xdef _z8_uart0tx_handler
endif
if EZ8_I2C=1
xdef _z8_i2c_handler
xdef _z8_i2c_handler
endif
if EZ8_SPI=1
xdef _z8_spi_handler
xdef _z8_spi_handler
endif
if EZ8_ADC=1
xdef _z8_adc_handler
xdef _z8_adc_handler
endif
xdef _z8_p7ad_handler
xdef _z8_p6ad_handler
xdef _z8_p5ad_handler
xdef _z8_p4ad_handler
xdef _z8_p3ad_handler
xdef _z8_p2ad_handler
xdef _z8_p1ad_handler
xdef _z8_p0ad_handler
xdef _z8_p7ad_handler
xdef _z8_p6ad_handler
xdef _z8_p5ad_handler
xdef _z8_p4ad_handler
xdef _z8_p3ad_handler
xdef _z8_p2ad_handler
xdef _z8_p1ad_handler
xdef _z8_p0ad_handler
if EZ8_TIMER4=1
xdef _z8_timer3_handler
xdef _z8_timer3_handler
endif
if EZ8_UART1=1
xdef _z8_uart1rx_handler
xdef _z8_uart1tx_handler
xdef _z8_uart1rx_handler
xdef _z8_uart1tx_handler
endif
if EZ8_DMA=1
xdef _z8_dma_handler
xdef _z8_dma_handler
endif
if EZ8_PORT1=0
xdef _z8_c3_handler
xdef _z8_c2_handler
xdef _z8_c1_handler
xdef _z8_c0_handler
xdef _z8_c3_handler
xdef _z8_c2_handler
xdef _z8_c1_handler
xdef _z8_c0_handler
endif
/**************************************************************************/
@ -233,13 +235,14 @@ endif
**************************************************************************/
ENTER : MACRO val
pushx rp /* Save the current RP value in the stack */
srp #%f0 /* Load the interrupt register pointer */
ld r0, #val /* Pass the new value in r0
jr _z8_common_handler /* The rest of the handling is common */
ENDMAC ENTER
LEAVE : MACRO
srp #%e0 /* Restore the user register pointer */
popx rp /* Restore the user register pointer */
iret /* And return from interrupt */
ENDMAC LEAVE
@ -738,6 +741,119 @@ _z8_wotrap_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
/**************************************************************************

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 */
regs[XCPT_PC] = (uint16)up_sigdeliver;
regs[XCPT_PC] = (chipreg_t)up_sigdeliver;
regs[XCPT_I] = 0;
}