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