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:
parent
1ce0745dd8
commit
b3969170d5
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user