mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 21:36:28 +08:00
8051 integration
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@59 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -42,7 +42,7 @@
|
|||||||
CONFIG_ARCH=pjrc-8051
|
CONFIG_ARCH=pjrc-8051
|
||||||
CONFIG_ARCH_8052=y
|
CONFIG_ARCH_8052=y
|
||||||
CONFIG_ARCH_PJRC=y
|
CONFIG_ARCH_PJRC=y
|
||||||
CONFIG_8051_LEDS=n
|
CONFIG_8051_LEDS=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# General OS setup
|
# General OS setup
|
||||||
|
|||||||
@@ -90,28 +90,52 @@
|
|||||||
#define FRAME_RETLS 0
|
#define FRAME_RETLS 0
|
||||||
#define FRAME_RETMS 1
|
#define FRAME_RETMS 1
|
||||||
|
|
||||||
/* Then a full context save area which can be indexed with
|
/* Then a partial context context save area that can be
|
||||||
* the following definitions (relative to the beginning of
|
* indexed with the following definitions (relative to the
|
||||||
* the initial frame.
|
* beginning of the initial frame.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define FRAME_ACC 2
|
#define FRAME_ACC 2
|
||||||
#define FRAME_IE 3
|
#define FRAME_IE 3
|
||||||
#define FRAME_DPL 4
|
#define FRAME_DPL 4
|
||||||
#define FRAME_DPH 5
|
#define FRAME_DPH 5
|
||||||
#define FRAME_B 6
|
|
||||||
#define FRAME_R2 7
|
|
||||||
#define FRAME_R3 8
|
|
||||||
#define FRAME_R4 9
|
|
||||||
#define FRAME_R5 10
|
|
||||||
#define FRAME_R6 11
|
|
||||||
#define FRAME_R7 12
|
|
||||||
#define FRAME_R0 13
|
|
||||||
#define FRAME_R1 14
|
|
||||||
#define FRAME_PSW 15
|
|
||||||
#define FRAME_BP 16
|
|
||||||
|
|
||||||
#define FRAME_SIZE 17
|
#define FRAME_SIZE 6
|
||||||
|
|
||||||
|
/* The remaining registers are not saved on the stack (due
|
||||||
|
* to the limited stack size of the 8051/2) but in an array
|
||||||
|
* in the TCB:
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define REGS_B 0
|
||||||
|
#define REGS_R2 1
|
||||||
|
#define REGS_R3 2
|
||||||
|
#define REGS_R4 3
|
||||||
|
#define REGS_R5 4
|
||||||
|
#define REGS_R6 5
|
||||||
|
#define REGS_R7 6
|
||||||
|
#define REGS_R0 7
|
||||||
|
#define REGS_R1 8
|
||||||
|
#define REGS_PSW 9
|
||||||
|
#define REGS_BP 10
|
||||||
|
|
||||||
|
#define REGS_SIZE 11
|
||||||
|
|
||||||
|
/* Note that the stack pointer is not saved. Rather, the
|
||||||
|
* size of the saved stack frame is saved in the 'nbytes'
|
||||||
|
* field. Since that stack begins at a fixed location, the
|
||||||
|
* top-of-stack pointer can be derived from the saved size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* These are offsets into struct xcptcontext that can be
|
||||||
|
* used from assembly language to access the structure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define XCPT_NBYTES 0
|
||||||
|
#define XCPT_STACK 1
|
||||||
|
#define XCPT_REGS (STACK_SIZE+1)
|
||||||
|
|
||||||
|
#define XCPT_SIZE (STACK_SIZE+REGS_SIZE+1)
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Public Types
|
* Public Types
|
||||||
@@ -122,8 +146,26 @@
|
|||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
struct xcptcontext
|
struct xcptcontext
|
||||||
{
|
{
|
||||||
|
/* This is the number of valid bytes currently saved in
|
||||||
|
* stack[]. Since that stack begins at a fixed location,
|
||||||
|
* the top-of-stack pointer can be derived from this size.
|
||||||
|
*/
|
||||||
|
|
||||||
ubyte nbytes;
|
ubyte nbytes;
|
||||||
|
|
||||||
|
/* This is the saved stack. Space is allocated for the
|
||||||
|
* entire 256 byte IRAM (minus register and bit usage at
|
||||||
|
* the beginning).
|
||||||
|
*/
|
||||||
|
|
||||||
ubyte stack[STACK_SIZE];
|
ubyte stack[STACK_SIZE];
|
||||||
|
|
||||||
|
/* These are save 8051/2 registers. These are saved
|
||||||
|
* separately from the stack to increase the effective
|
||||||
|
* stack size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ubyte regs[REGS_SIZE];
|
||||||
};
|
};
|
||||||
#endif /* __ASSEMBLY */
|
#endif /* __ASSEMBLY */
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ xdata at 0xF903 ubyte p82c55_def_config;
|
|||||||
#define LED_STARTED 0
|
#define LED_STARTED 0
|
||||||
#define LED_HEAPALLOCATE 1
|
#define LED_HEAPALLOCATE 1
|
||||||
#define LED_IRQSENABLED 2
|
#define LED_IRQSENABLED 2
|
||||||
#define LED_UNUSED1 3
|
#define LED_IDLE 3
|
||||||
#define LED_UNUSED2 4
|
#define LED_UNUSED2 4
|
||||||
#define LED_INIRQ 5
|
#define LED_INIRQ 5
|
||||||
#define LED_ASSERTION 6
|
#define LED_ASSERTION 6
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ void up_block_task(FAR _TCB *tcb, tstate_t task_state)
|
|||||||
* Just copy the current registers into the OLD rtcb.
|
* Just copy the current registers into the OLD rtcb.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
up_savestack(&tcb->xcp, g_irqtos);
|
up_saveirqcontext(&tcb->xcp);
|
||||||
|
|
||||||
/* Restore the exception context of the rtcb at the (new) head
|
/* Restore the exception context of the rtcb at the (new) head
|
||||||
* of the g_readytorun task list.
|
* of the g_readytorun task list.
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ static void _up_putcolon(void) __naked
|
|||||||
{
|
{
|
||||||
_asm
|
_asm
|
||||||
mov a, #0x3a
|
mov a, #0x3a
|
||||||
lcall PM2_ENTRY_COUT
|
ljmp PM2_ENTRY_COUT
|
||||||
_endasm;
|
_endasm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ static void _up_dump8(__code char *ptr, ubyte b)
|
|||||||
#ifdef CONFIG_FRAME_DUMP
|
#ifdef CONFIG_FRAME_DUMP
|
||||||
void up_dumpstack(void)
|
void up_dumpstack(void)
|
||||||
{
|
{
|
||||||
NEAR ubyte *start = (NEAR ubyte *)(UP_STACK_BASE & 0xf0);
|
NEAR ubyte *start = (NEAR ubyte *)(STACK_BASE & 0xf0);
|
||||||
NEAR ubyte *end = (NEAR ubyte *)SP;
|
NEAR ubyte *end = (NEAR ubyte *)SP;
|
||||||
ubyte i;
|
ubyte i;
|
||||||
|
|
||||||
@@ -138,7 +138,16 @@ void up_dumpstack(void)
|
|||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
_up_putspace();
|
_up_putspace();
|
||||||
_up_puthex(*start);
|
if (start < (NEAR ubyte *)(STACK_BASE) ||
|
||||||
|
start > end)
|
||||||
|
{
|
||||||
|
_up_putspace();
|
||||||
|
_up_putspace();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_up_puthex(*start);
|
||||||
|
}
|
||||||
start++;
|
start++;
|
||||||
}
|
}
|
||||||
_up_putnl();
|
_up_putnl();
|
||||||
@@ -153,11 +162,52 @@ void up_dumpstack(void)
|
|||||||
#ifdef CONFIG_FRAME_DUMP
|
#ifdef CONFIG_FRAME_DUMP
|
||||||
void up_dumpframe(FAR struct xcptcontext *context)
|
void up_dumpframe(FAR struct xcptcontext *context)
|
||||||
{
|
{
|
||||||
FAR ubyte *start = &context->stack[context->nbytes - FRAME_SIZE];
|
#ifdef CONFIG_FRAME_DUMP_SHORT
|
||||||
_up_dump16(" RET ", start[FRAME_RETMS], start[FRAME_RETLS]);
|
FAR ubyte *stack = &context->stack[context->nbytes - FRAME_SIZE];
|
||||||
_up_dump8(" IE ", start[FRAME_IE]);
|
FAR ubyte *regs = context->regs;
|
||||||
_up_dump16(" DPTR ", start[FRAME_DPH], start[FRAME_DPL]);
|
|
||||||
_up_dump8(" PSW ", start[FRAME_PSW]);
|
_up_dump16(" RET ", stack[FRAME_RETMS], stack[FRAME_RETLS]);
|
||||||
|
_up_dump8 (" IE ", stack[FRAME_IE]);
|
||||||
|
_up_dump16(" DPTR ", stack[FRAME_DPH], stack[FRAME_DPL]);
|
||||||
|
_up_dump8 (" PSW ", regs[REGS_PSW]);
|
||||||
|
_up_dump8 (" SP ", context->nbytes + (STACK_BASE-1));
|
||||||
|
#else
|
||||||
|
FAR ubyte *stack = &context->stack[context->nbytes - FRAME_SIZE];
|
||||||
|
FAR ubyte *regs = context->regs;
|
||||||
|
ubyte i, j, k;
|
||||||
|
|
||||||
|
_up_dump8 (" NBYTES ", context->nbytes);
|
||||||
|
|
||||||
|
for (i = 0; i < context->nbytes; i += 8)
|
||||||
|
{
|
||||||
|
_up_puthex(i);
|
||||||
|
_up_putcolon();
|
||||||
|
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
{
|
||||||
|
k = i + j;
|
||||||
|
_up_putspace();
|
||||||
|
if (k >= context->nbytes)
|
||||||
|
{
|
||||||
|
_up_putspace();
|
||||||
|
_up_putspace();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_up_puthex(context->stack[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_up_putnl();
|
||||||
|
}
|
||||||
|
|
||||||
|
_up_puts(" REGS:");
|
||||||
|
for (i = 0; i < REGS_SIZE; i++)
|
||||||
|
{
|
||||||
|
_up_putspace();
|
||||||
|
_up_puthex(context->regs[i]);
|
||||||
|
}
|
||||||
|
_up_putnl();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
************************************************************/
|
************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include "up_internal.h"
|
#include "up_internal.h"
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
|
|||||||
@@ -57,12 +57,14 @@
|
|||||||
|
|
||||||
.globl _g_irqtos
|
.globl _g_irqtos
|
||||||
.globl _g_irqcontext
|
.globl _g_irqcontext
|
||||||
|
.globl _g_irqregs
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
************************************************************/
|
************************************************************/
|
||||||
|
|
||||||
.globl _irq_dispatch
|
.globl _irq_dispatch
|
||||||
|
.globl _up_restoreregisters
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Program entry points
|
* Program entry points
|
||||||
@@ -157,33 +159,31 @@ _up_interrupt:
|
|||||||
push ie
|
push ie
|
||||||
clr ea
|
clr ea
|
||||||
|
|
||||||
/* Now push the remaining registers with interrupt disabled */
|
/* Save the remaining registers with interrupts disabled
|
||||||
|
*
|
||||||
|
* a, ie, and dptr go on the stack.
|
||||||
|
*/
|
||||||
|
|
||||||
push dpl
|
push dpl
|
||||||
push dph
|
push dph
|
||||||
push b
|
|
||||||
push ar2
|
|
||||||
push ar3
|
|
||||||
push ar4
|
|
||||||
push ar5
|
|
||||||
push ar6
|
|
||||||
push ar7
|
|
||||||
push ar0
|
|
||||||
push ar1
|
|
||||||
push psw
|
|
||||||
clr psw
|
|
||||||
push _bp
|
|
||||||
|
|
||||||
/* Save the IRQ number in r3 */
|
/* Other registers go into the IRQ register save area */
|
||||||
|
|
||||||
|
push acc
|
||||||
|
mov dptr, #_g_irqregs
|
||||||
|
lcall _up_saveregisters
|
||||||
|
|
||||||
|
/* Show interrupt status on the LEDs */
|
||||||
|
|
||||||
#ifdef CONFIG_8051_LEDS
|
#ifdef CONFIG_8051_LEDS
|
||||||
push acc
|
|
||||||
mov dpl, #LED_INIRQ
|
mov dpl, #LED_INIRQ
|
||||||
lcall _up_ledon
|
lcall _up_ledon
|
||||||
pop ar2
|
|
||||||
#else
|
|
||||||
mov r2, a
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Save the IRQ number in r2 */
|
||||||
|
|
||||||
|
pop ar2
|
||||||
|
|
||||||
/* Mark that we are in an interrupt and provide the top
|
/* Mark that we are in an interrupt and provide the top
|
||||||
* of stack pointer to the context switching logic.
|
* of stack pointer to the context switching logic.
|
||||||
*/
|
*/
|
||||||
@@ -197,7 +197,7 @@ _up_interrupt:
|
|||||||
* structure.
|
* structure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mov dptr,#_g_irqcontext
|
mov dptr, #_g_irqcontext
|
||||||
clr a
|
clr a
|
||||||
movx @dptr,a
|
movx @dptr,a
|
||||||
inc dptr
|
inc dptr
|
||||||
@@ -238,8 +238,17 @@ _up_interrupt:
|
|||||||
movx a, @dptr
|
movx a, @dptr
|
||||||
mov r3, a
|
mov r3, a
|
||||||
|
|
||||||
orl a, r2
|
orl a, r2
|
||||||
jz 00003$
|
jnz 00001$
|
||||||
|
|
||||||
|
/* No context switch is pending. Restore registers
|
||||||
|
* from the interrupt register save area.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mov dptr, #_g_irqregs
|
||||||
|
sjmp 00004$
|
||||||
|
|
||||||
|
00001$: /****************************************************/
|
||||||
|
|
||||||
/* A context switch is pending, clear g_irqcontext */
|
/* A context switch is pending, clear g_irqcontext */
|
||||||
|
|
||||||
@@ -285,6 +294,8 @@ _up_interrupt:
|
|||||||
/* Save r2-3 = &context->stack */
|
/* Save r2-3 = &context->stack */
|
||||||
|
|
||||||
inc dptr
|
inc dptr
|
||||||
|
push dpl
|
||||||
|
push dph
|
||||||
mov r2, dpl
|
mov r2, dpl
|
||||||
mov r3, dph
|
mov r3, dph
|
||||||
|
|
||||||
@@ -293,9 +304,10 @@ _up_interrupt:
|
|||||||
mov r0, #STACK_BASE
|
mov r0, #STACK_BASE
|
||||||
|
|
||||||
/* Top of the copy loop */
|
/* Top of the copy loop */
|
||||||
00001$:
|
00002$:
|
||||||
dec r4
|
mov a, r4 /* a = bytes left to transfer */
|
||||||
jz 00002$
|
dec r4 /* (for next time through the loop) */
|
||||||
|
jz 00003$ /* Jump if a = 0 (done) */
|
||||||
|
|
||||||
/* Fetch the next byte from context->stack */
|
/* Fetch the next byte from context->stack */
|
||||||
|
|
||||||
@@ -316,38 +328,69 @@ _up_interrupt:
|
|||||||
/* Increment the IRAM pointer */
|
/* Increment the IRAM pointer */
|
||||||
|
|
||||||
inc r0
|
inc r0
|
||||||
sjmp 00001$
|
sjmp 00002$
|
||||||
|
|
||||||
/* Set the new stack pointer */
|
/* The entire stack has been copied from XRAM into
|
||||||
|
* IRAM. Set the new stack pointer
|
||||||
00002$:
|
|
||||||
mov sp, r5
|
|
||||||
|
|
||||||
#ifdef CONFIG_INTERRUPT_FRAME_DUMP
|
|
||||||
lcall _up_dumpstack
|
|
||||||
#endif
|
|
||||||
/* Then restore the context from the stack and return
|
|
||||||
* from the interrupt
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
00003$:
|
00003$:
|
||||||
#ifdef CONFIG_8051_LEDS
|
|
||||||
mov dpl, #LED_INIRQ
|
|
||||||
lcall _up_ledoff
|
|
||||||
#endif
|
|
||||||
pop _bp
|
|
||||||
pop psw
|
|
||||||
pop ar1
|
|
||||||
pop ar0
|
|
||||||
pop ar7
|
|
||||||
pop ar6
|
|
||||||
pop ar5
|
|
||||||
pop ar4
|
|
||||||
pop ar3
|
|
||||||
pop ar2
|
|
||||||
pop b
|
|
||||||
pop dph
|
pop dph
|
||||||
pop dpl
|
pop dpl
|
||||||
pop ie
|
mov sp, r5
|
||||||
|
|
||||||
|
#ifdef CONFIG_INTERRUPT_FRAME_DUMP
|
||||||
|
push dpl
|
||||||
|
push dph
|
||||||
|
lcall _up_dumpstack
|
||||||
|
pop dpl
|
||||||
|
pop dph
|
||||||
|
#endif
|
||||||
|
/* Get the pointer to the register save area */
|
||||||
|
|
||||||
|
mov a, #FRAME_SIZE
|
||||||
|
add a, dpl
|
||||||
|
mov dpl, a
|
||||||
|
clr a
|
||||||
|
addc a, dph
|
||||||
|
mov dph, a
|
||||||
|
|
||||||
|
00004$: /****************************************************/
|
||||||
|
|
||||||
|
/* Restore the context from the register save area
|
||||||
|
* and return from the interrupt. At this point, dptr
|
||||||
|
* holds the pointer to the memory region that holds
|
||||||
|
* the register save area. This could be either
|
||||||
|
* g_irqregs (no context switch) or &g_irqcontext->regs
|
||||||
|
* (context switch).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_8051_LEDS
|
||||||
|
push dpl
|
||||||
|
push dph
|
||||||
|
mov dpl, #LED_INIRQ
|
||||||
|
lcall _up_ledoff
|
||||||
|
pop dpl
|
||||||
|
pop dph
|
||||||
|
#endif
|
||||||
|
/* Restore registers from the register save area */
|
||||||
|
|
||||||
|
lcall _up_restoreregisters
|
||||||
|
|
||||||
|
/* Restore registers from the stack and return */
|
||||||
|
|
||||||
|
pop dph
|
||||||
|
pop dpl
|
||||||
|
|
||||||
|
/* Restore the interrupt state per the stored IE value */
|
||||||
|
|
||||||
|
pop acc
|
||||||
|
jb acc.7,00005$
|
||||||
|
clr ie.7
|
||||||
|
sjmp 00006$
|
||||||
|
00005$:
|
||||||
|
setb ie.7
|
||||||
|
|
||||||
|
00006$:
|
||||||
pop acc
|
pop acc
|
||||||
reti
|
reti
|
||||||
|
|||||||
@@ -50,6 +50,10 @@
|
|||||||
* Private Data
|
* Private Data
|
||||||
************************************************************/
|
************************************************************/
|
||||||
|
|
||||||
|
#if defined(CONFIG_8051_LEDS) && defined(CONFIG_8051_BRINGUP)
|
||||||
|
static ubyte g_ledtoggle = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
************************************************************/
|
************************************************************/
|
||||||
@@ -75,5 +79,16 @@
|
|||||||
|
|
||||||
void up_idle(void)
|
void up_idle(void)
|
||||||
{
|
{
|
||||||
|
#if defined(CONFIG_8051_LEDS) && defined(CONFIG_8051_BRINGUP)
|
||||||
|
g_ledtoggle++;
|
||||||
|
if (g_ledtoggle == 0x80)
|
||||||
|
{
|
||||||
|
up_ledon(LED_IDLE);
|
||||||
|
}
|
||||||
|
else if (g_ledtoggle == 0x00)
|
||||||
|
{
|
||||||
|
up_ledoff(LED_IDLE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,16 @@
|
|||||||
|
|
||||||
ubyte g_irqtos;
|
ubyte g_irqtos;
|
||||||
|
|
||||||
|
/* Registers are saved in the following global array during
|
||||||
|
* interrupt processing. If a context switch is performed
|
||||||
|
* during the interrupt handling, these registers will be
|
||||||
|
* copied into the TCB again (NOTE: We could save a copy
|
||||||
|
* if the interrupt handling logic saved the registers
|
||||||
|
* directly into (_TCB*)g_readytorun.head->xcp.regs).
|
||||||
|
*/
|
||||||
|
|
||||||
|
ubyte g_irqregs[REGS_SIZE];
|
||||||
|
|
||||||
/* If during execution of an interrup handler, a context
|
/* If during execution of an interrup handler, a context
|
||||||
* switch must be performed, the follwing will be set to
|
* switch must be performed, the follwing will be set to
|
||||||
* to that address of the relevant context structure. The
|
* to that address of the relevant context structure. The
|
||||||
@@ -69,6 +79,13 @@ ubyte g_irqtos;
|
|||||||
|
|
||||||
FAR struct xcptcontext *g_irqcontext;
|
FAR struct xcptcontext *g_irqcontext;
|
||||||
|
|
||||||
|
/* It is faster to look up 8-bit shifts in this table than
|
||||||
|
* to comput them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const ubyte g_ntobit[8] =
|
||||||
|
{ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
************************************************************/
|
************************************************************/
|
||||||
|
|||||||
@@ -75,6 +75,7 @@
|
|||||||
void up_initial_state(FAR _TCB *tcb)
|
void up_initial_state(FAR _TCB *tcb)
|
||||||
{
|
{
|
||||||
FAR ubyte *frame = tcb->xcp.stack;
|
FAR ubyte *frame = tcb->xcp.stack;
|
||||||
|
FAR ubyte *regs = tcb->xcp.regs;
|
||||||
|
|
||||||
/* This is the form of initial stack frame
|
/* This is the form of initial stack frame
|
||||||
*
|
*
|
||||||
@@ -96,10 +97,21 @@ void up_initial_state(FAR _TCB *tcb)
|
|||||||
frame[FRAME_RETLS] = (((uint16)tcb->start) & 0xff);
|
frame[FRAME_RETLS] = (((uint16)tcb->start) & 0xff);
|
||||||
frame[FRAME_RETMS] = (((uint16)tcb->start) >> 8);
|
frame[FRAME_RETMS] = (((uint16)tcb->start) >> 8);
|
||||||
|
|
||||||
/* The context save area follows the return address. */
|
/* The context save area for registers a, ie, and dpstr
|
||||||
|
* follows the return address in the stack frame.
|
||||||
|
*/
|
||||||
|
|
||||||
frame[FRAME_IE] = 0x80;
|
frame[FRAME_IE] = 0x80;
|
||||||
frame[FRAME_PSW] = 0;
|
|
||||||
|
|
||||||
tcb->xcp.nbytes = FRAME_SIZE;
|
/* Save the number of bytes in the frame (which will be used
|
||||||
|
* to intialize the stack pointer when the task is started).
|
||||||
|
*/
|
||||||
|
|
||||||
|
tcb->xcp.nbytes = FRAME_SIZE;
|
||||||
|
|
||||||
|
/* Initialize the remaining register save area which is
|
||||||
|
* outside of the stack save area.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tcb->xcp.regs[REGS_PSW] = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
#include <arch/irq.h>
|
||||||
#ifdef CONFIG_ARCH_PJRC
|
#ifdef CONFIG_ARCH_PJRC
|
||||||
# include "pjrc.h"
|
# include "pjrc.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -51,10 +52,13 @@
|
|||||||
|
|
||||||
/* Bring-up debug configurations */
|
/* Bring-up debug configurations */
|
||||||
|
|
||||||
#define CONFIG_FRAME_DUMP 1 /* Enabled stack/frame dumping logic */
|
#define CONFIG_8051_BRINGUP 1 /* Enables some bringup features */
|
||||||
#define CONFIG_SUPPRESS_INTERRUPTS 1 /* Do not enable interrupts */
|
#define CONFIG_FRAME_DUMP 1 /* Enable stack/frame dumping logic */
|
||||||
#define CONFIG_SWITCH_FRAME_DUMP 1 /* Dump frames from normal switches */
|
#undef CONFIG_FRAME_DUMP_SHORT /* Terse frame dump output */
|
||||||
|
#define CONFIG_SUPPRESS_INTERRUPTS 1 /* Do not enable interrupts */
|
||||||
|
#define CONFIG_SWITCH_FRAME_DUMP 1 /* Dump frames from normal switches */
|
||||||
#undef CONFIG_INTERRUPT_FRAME_DUMP /* Dump frames from interrupt switches */
|
#undef CONFIG_INTERRUPT_FRAME_DUMP /* Dump frames from interrupt switches */
|
||||||
|
#define CONFIG_LED_DEBUG 1 /* Enabled debug output from LED logic */
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Public Types
|
* Public Types
|
||||||
@@ -75,6 +79,16 @@
|
|||||||
|
|
||||||
extern ubyte g_irqtos;
|
extern ubyte g_irqtos;
|
||||||
|
|
||||||
|
/* Registers are saved in the following global array during
|
||||||
|
* interrupt processing. If a context switch is performed
|
||||||
|
* during the interrupt handling, these registers will be
|
||||||
|
* copied into the TCB again (NOTE: We could save a copy
|
||||||
|
* if the interrupt handling logic saved the registers
|
||||||
|
* directly into (_TCB*)g_readytorun.head->xcp.regs).
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern ubyte g_irqregs[REGS_SIZE];
|
||||||
|
|
||||||
/* If during execution of an interrup handler, a context
|
/* If during execution of an interrup handler, a context
|
||||||
* switch must be performed, the follwing will be set to
|
* switch must be performed, the follwing will be set to
|
||||||
* to that address of the relevant context structure. The
|
* to that address of the relevant context structure. The
|
||||||
@@ -84,6 +98,12 @@ extern ubyte g_irqtos;
|
|||||||
|
|
||||||
extern FAR struct xcptcontext *g_irqcontext;
|
extern FAR struct xcptcontext *g_irqcontext;
|
||||||
|
|
||||||
|
/* It is faster to look up 8-bit shifts in this table than
|
||||||
|
* to comput them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern const ubyte g_ntobit[8];
|
||||||
|
|
||||||
#endif /* __ASSEMBLY */
|
#endif /* __ASSEMBLY */
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
@@ -95,11 +115,13 @@ extern FAR struct xcptcontext *g_irqcontext;
|
|||||||
#if CONFIG_MM_REGIONS > 1
|
#if CONFIG_MM_REGIONS > 1
|
||||||
extern void up_addregion(void);
|
extern void up_addregion(void);
|
||||||
#endif
|
#endif
|
||||||
extern void up_delay(ubyte milliseconds) __naked;
|
extern void up_delay(ubyte milliseconds) __naked;
|
||||||
extern void up_irqinitialize(void);
|
extern void up_irqinitialize(void);
|
||||||
extern void up_restorecontext(FAR struct xcptcontext *context) _naked;
|
extern void up_restorecontext(FAR struct xcptcontext *context) _naked;
|
||||||
|
extern void up_restoreregisters(FAR ubyte *regs) _naked;
|
||||||
extern ubyte up_savecontext(FAR struct xcptcontext *context) __naked;
|
extern ubyte up_savecontext(FAR struct xcptcontext *context) __naked;
|
||||||
extern void up_savestack(FAR struct xcptcontext *context, ubyte tos);
|
extern void up_saveregisters(FAR ubyte *regs) _naked;
|
||||||
|
extern void up_saveirqcontext(FAR struct xcptcontext *context);
|
||||||
extern void up_timerinit(void);
|
extern void up_timerinit(void);
|
||||||
|
|
||||||
/* Defined in up_assert.c */
|
/* Defined in up_assert.c */
|
||||||
@@ -116,8 +138,8 @@ extern void up_dumpframe(FAR struct xcptcontext *context);
|
|||||||
|
|
||||||
#ifdef CONFIG_8051_LEDS
|
#ifdef CONFIG_8051_LEDS
|
||||||
extern void up_ledinit(void);
|
extern void up_ledinit(void);
|
||||||
extern void up_ledon(int led);
|
extern void up_ledon(ubyte led);
|
||||||
extern void up_ledoff(int led);
|
extern void up_ledoff(ubyte led);
|
||||||
#else
|
#else
|
||||||
# define up_ledinit()
|
# define up_ledinit()
|
||||||
# define up_ledon(led)
|
# define up_ledon(led)
|
||||||
|
|||||||
@@ -43,6 +43,8 @@
|
|||||||
#include <8052.h>
|
#include <8052.h>
|
||||||
#include "up_internal.h"
|
#include "up_internal.h"
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
extern int g_nints;
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
************************************************************/
|
************************************************************/
|
||||||
@@ -69,7 +71,7 @@
|
|||||||
|
|
||||||
void up_irqinitialize(void)
|
void up_irqinitialize(void)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_SUPPRESS_INTERRUPTS
|
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||||
/* Disable all interrupts */
|
/* Disable all interrupts */
|
||||||
|
|
||||||
IE = 0;
|
IE = 0;
|
||||||
@@ -122,7 +124,7 @@ void up_disable_irq(int irq)
|
|||||||
{
|
{
|
||||||
if ((unsigned)irq < NR_IRQS)
|
if ((unsigned)irq < NR_IRQS)
|
||||||
{
|
{
|
||||||
IE |= (1 << irq);
|
IE &= ~(g_ntobit[irq]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,6 +140,6 @@ void up_enable_irq(int irq)
|
|||||||
{
|
{
|
||||||
if ((unsigned)irq < NR_IRQS)
|
if ((unsigned)irq < NR_IRQS)
|
||||||
{
|
{
|
||||||
IE &= ~(1 << irq);
|
IE |= g_ntobit[irq];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,16 +45,75 @@
|
|||||||
* Definitions
|
* Definitions
|
||||||
************************************************************/
|
************************************************************/
|
||||||
|
|
||||||
|
#define RESET_KLUDGE_NEEDED 1
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
************************************************************/
|
************************************************************/
|
||||||
|
|
||||||
static uint32 g_ledstate;
|
static ubyte g_ledstate;
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
************************************************************/
|
************************************************************/
|
||||||
|
|
||||||
|
#if defined(CONFIG_LED_DEBUG) && defined(CONFIG_8051_LEDS)
|
||||||
|
static void _up_puthex(ubyte hex) __naked
|
||||||
|
{
|
||||||
|
hex; /* To avoid unreferenced argument warning */
|
||||||
|
_asm
|
||||||
|
mov a, dpl
|
||||||
|
ljmp PM2_ENTRY_PHEX
|
||||||
|
_endasm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _up_putch(ubyte ch) __naked
|
||||||
|
{
|
||||||
|
_asm
|
||||||
|
mov a, dpl
|
||||||
|
ljmp PM2_ENTRY_COUT
|
||||||
|
_endasm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _up_putnl(void) __naked
|
||||||
|
{
|
||||||
|
_asm
|
||||||
|
ljmp PM2_ENTRY_NEWLINE
|
||||||
|
_endasm;
|
||||||
|
}
|
||||||
|
|
||||||
|
# define _up_showledinit() \
|
||||||
|
_up_putch('I'); \
|
||||||
|
_up_puthex(g_ledstate); _up_putch(':'); \
|
||||||
|
_up_puthex(p82c55_port_e); _up_putnl();
|
||||||
|
|
||||||
|
# define _up_showledreset() \
|
||||||
|
_up_putch('R'); \
|
||||||
|
_up_puthex(led); _up_putch(':'); \
|
||||||
|
_up_puthex(g_ledstate); _up_putch(':'); \
|
||||||
|
_up_puthex(p82c55_port_e); _up_putnl();
|
||||||
|
|
||||||
|
# define _up_showledon() \
|
||||||
|
_up_putch('+'); \
|
||||||
|
_up_puthex(led); _up_putch(':'); \
|
||||||
|
_up_puthex(g_ledstate); _up_putch(':'); \
|
||||||
|
_up_puthex(p82c55_port_e); _up_putnl();
|
||||||
|
|
||||||
|
# define _up_showledoff() \
|
||||||
|
_up_putch('-'); \
|
||||||
|
_up_puthex(led); _up_putch(':'); \
|
||||||
|
_up_puthex(g_ledstate); _up_putch(':'); \
|
||||||
|
_up_puthex(p82c55_port_e); _up_putnl();
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# define _up_showledinit()
|
||||||
|
# define _up_showledreset()
|
||||||
|
# define _up_showledon()
|
||||||
|
# define _up_showledoff()
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Public Funtions
|
* Public Funtions
|
||||||
************************************************************/
|
************************************************************/
|
||||||
@@ -68,38 +127,71 @@ void up_ledinit(void)
|
|||||||
{
|
{
|
||||||
/* Set all ports as outputs */
|
/* Set all ports as outputs */
|
||||||
|
|
||||||
p82c55_abc_config = 128;
|
|
||||||
p82c55_def_config = 128;
|
p82c55_def_config = 128;
|
||||||
|
|
||||||
/* Turn LED 1-7 off; turn LED 0 on */
|
/* Turn LED 1-7 off; turn LED 0 on */
|
||||||
|
|
||||||
g_ledstate = 0x000000fe;
|
g_ledstate = 0xfe;
|
||||||
p82c55_port_e = g_ledstate;
|
p82c55_port_e = g_ledstate;
|
||||||
|
|
||||||
|
_up_showledinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Name: up_ledon
|
* Name: up_ledon
|
||||||
************************************************************/
|
************************************************************/
|
||||||
|
|
||||||
void up_ledon(int led)
|
void up_ledon(ubyte led)
|
||||||
{
|
{
|
||||||
|
#ifdef RESET_KLUDGE_NEEDED
|
||||||
|
/* I don't understand why this happens yet, but sometimes
|
||||||
|
* it is necessary to reconfigure port E.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (g_ledstate != p82c55_port_e)
|
||||||
|
{
|
||||||
|
_up_showledreset();
|
||||||
|
p82c55_def_config = 128;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Clear the bit in port E corresponding to LED to turn it on */
|
||||||
|
|
||||||
if (led < 8)
|
if (led < 8)
|
||||||
{
|
{
|
||||||
g_ledstate &= ~(1 << led);
|
g_ledstate &= ~(g_ntobit[led]);
|
||||||
p82c55_port_e = g_ledstate;
|
p82c55_port_e = g_ledstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_up_showledon();
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Name: up_ledoff
|
* Name: up_ledoff
|
||||||
************************************************************/
|
************************************************************/
|
||||||
|
|
||||||
void up_ledoff(int led)
|
void up_ledoff(ubyte led)
|
||||||
{
|
{
|
||||||
|
#ifdef RESET_KLUDGE_NEEDED
|
||||||
|
/* I don't understand why this happens yet, but sometimes
|
||||||
|
* it is necessary to reconfigure port E.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (g_ledstate != p82c55_port_e)
|
||||||
|
{
|
||||||
|
_up_showledreset();
|
||||||
|
p82c55_def_config = 128;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set the bit in port E corresponding to LED to turn it off */
|
||||||
|
|
||||||
if (led < 8)
|
if (led < 8)
|
||||||
{
|
{
|
||||||
g_ledstate |= (1 << led);
|
g_ledstate |= g_ntobit[led];
|
||||||
p82c55_port_e = g_ledstate;
|
p82c55_port_e = g_ledstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_up_showledoff();
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_8051_LEDS */
|
#endif /* CONFIG_8051_LEDS */
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ void up_release_pending(void)
|
|||||||
* Just copy the current registers into the OLD rtcb.
|
* Just copy the current registers into the OLD rtcb.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
up_savestack(&rtcb->xcp, g_irqtos);
|
up_saveirqcontext(&rtcb->xcp);
|
||||||
|
|
||||||
/* Restore the exception context of the rtcb at the (new) head
|
/* Restore the exception context of the rtcb at the (new) head
|
||||||
* of the g_readytorun task list.
|
* of the g_readytorun task list.
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ void up_reprioritize_rtr(FAR _TCB *tcb, ubyte priority)
|
|||||||
* Just copy the current registers into the OLD rtcb.
|
* Just copy the current registers into the OLD rtcb.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
up_savestack(&tcb->xcp, g_irqtos);
|
up_saveirqcontext(&tcb->xcp);
|
||||||
|
|
||||||
/* Restore the exception context of the rtcb at the (new) head
|
/* Restore the exception context of the rtcb at the (new) head
|
||||||
* of the g_readytorun task list.
|
* of the g_readytorun task list.
|
||||||
|
|||||||
@@ -68,6 +68,66 @@
|
|||||||
* Public Functions
|
* Public Functions
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* Name: up_restoreregisters
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Restore the saved registers from the context save area. This function
|
||||||
|
* is called from up_restorecontext (below) and also from interrupt
|
||||||
|
* handling logic.
|
||||||
|
*
|
||||||
|
* Note that this function does not restore:
|
||||||
|
* a, dptr, ie - these are saved in the stack area
|
||||||
|
* sp - this can be inferred from g_irqtos or struct xcptontext.nbytes.
|
||||||
|
*
|
||||||
|
* Inputs:
|
||||||
|
* context - the context register array from which to restore the
|
||||||
|
* register values
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
void up_restoreregisters(FAR ubyte *regs) _naked
|
||||||
|
{
|
||||||
|
_asm
|
||||||
|
movx a, @dptr
|
||||||
|
mov b, a
|
||||||
|
inc dptr
|
||||||
|
movx a, @dptr
|
||||||
|
mov r2, a
|
||||||
|
inc dptr
|
||||||
|
movx a, @dptr
|
||||||
|
mov r3, a
|
||||||
|
inc dptr
|
||||||
|
movx a, @dptr
|
||||||
|
mov r4, a
|
||||||
|
inc dptr
|
||||||
|
movx a, @dptr
|
||||||
|
mov r5, a
|
||||||
|
inc dptr
|
||||||
|
movx a, @dptr
|
||||||
|
mov r6, a
|
||||||
|
inc dptr
|
||||||
|
movx a, @dptr
|
||||||
|
mov r7, a
|
||||||
|
inc dptr
|
||||||
|
movx a, @dptr
|
||||||
|
mov r0, a
|
||||||
|
inc dptr
|
||||||
|
movx a, @dptr
|
||||||
|
mov r1, a
|
||||||
|
inc dptr
|
||||||
|
movx a, @dptr
|
||||||
|
mov psw, a
|
||||||
|
inc dptr
|
||||||
|
movx a, @dptr
|
||||||
|
mov _bp, a
|
||||||
|
ret
|
||||||
|
_endasm;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Name: up_restorecontext
|
* Name: up_restorecontext
|
||||||
*
|
*
|
||||||
@@ -95,6 +155,10 @@ void up_restorecontext(FAR struct xcptcontext *context) __naked
|
|||||||
ar0 = 0x00
|
ar0 = 0x00
|
||||||
ar1 = 0x01
|
ar1 = 0x01
|
||||||
|
|
||||||
|
/* Dump the contents of the saved frame before it is copied back
|
||||||
|
* to memory/registers.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_SWITCH_FRAME_DUMP
|
#ifdef CONFIG_SWITCH_FRAME_DUMP
|
||||||
push dpl
|
push dpl
|
||||||
push dph
|
push dph
|
||||||
@@ -109,14 +173,17 @@ void up_restorecontext(FAR struct xcptcontext *context) __naked
|
|||||||
|
|
||||||
clr ea
|
clr ea
|
||||||
|
|
||||||
/* Register usage in the following:
|
/* The following logic will copy the stack from the
|
||||||
|
* context save structure into IRAM. We cannot use
|
||||||
|
* the stack in anyway during this copy. Instead,
|
||||||
|
* we will use registers as follows:
|
||||||
*
|
*
|
||||||
* R0 - Holds working the 8-bit IRAM pointer
|
* R0 - Holds the working 8-bit IRAM pointer
|
||||||
* R1 - Not used
|
* R1 - Not used
|
||||||
* R2-3 - Holds the working 16-bit XRAM pointer
|
* R2-3 - Holds the working 16-bit XRAM pointer
|
||||||
* R4 - Holds the working byte count
|
* R4 - Holds the working byte count
|
||||||
* R5 - Holds the new stack pointer
|
* R5 - Holds the new stack pointer
|
||||||
* R6-7 - Not used
|
* R6-7 - Saved context pointer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Fetch r4 = context->nbytes */
|
/* Fetch r4 = context->nbytes */
|
||||||
@@ -129,26 +196,32 @@ void up_restorecontext(FAR struct xcptcontext *context) __naked
|
|||||||
add a, #(STACK_BASE-1)
|
add a, #(STACK_BASE-1)
|
||||||
mov r5, a
|
mov r5, a
|
||||||
|
|
||||||
/* Save r2-3 = &context->stack */
|
/* Save r2-3 and r6-r7 = &context->stack */
|
||||||
|
|
||||||
inc dptr
|
inc dptr
|
||||||
mov r2, dpl
|
mov r2, dpl
|
||||||
mov r3, dph
|
mov r3, dph
|
||||||
|
mov r6, dpl
|
||||||
|
mov r7, dph
|
||||||
|
|
||||||
/* Set r0 = stack base address */
|
/* Set r0 = stack base address */
|
||||||
|
|
||||||
mov r0, #STACK_BASE
|
mov r0, #STACK_BASE
|
||||||
|
|
||||||
/* Top of the copy loop */
|
/* Top of the copy loop -- we cannot use the stack
|
||||||
|
* again until we finish the copy and set the new
|
||||||
|
* stack pointer (saved in r5)
|
||||||
|
*/
|
||||||
00001$:
|
00001$:
|
||||||
dec r4
|
mov a, r4 /* a = bytes left to transfer */
|
||||||
jz 00002$
|
dec r4 /* (for next time through the loop) */
|
||||||
|
jz 00002$ /* Jump if a = 0 (done) */
|
||||||
|
|
||||||
/* Fetch the next byte from context->stack */
|
/* Fetch the next byte from context->stack */
|
||||||
|
|
||||||
mov dpl, r2
|
mov dpl, r2
|
||||||
mov dph, r3
|
mov dph, r3
|
||||||
movx a,@dptr
|
movx a, @dptr
|
||||||
|
|
||||||
/* Increment the XRAM pointer */
|
/* Increment the XRAM pointer */
|
||||||
|
|
||||||
@@ -166,26 +239,40 @@ void up_restorecontext(FAR struct xcptcontext *context) __naked
|
|||||||
sjmp 00001$
|
sjmp 00001$
|
||||||
00002$:
|
00002$:
|
||||||
|
|
||||||
/* Set the new stack pointer */
|
/* Set the new stack pointer and recover the
|
||||||
|
* context->stack pointer.
|
||||||
|
*/
|
||||||
|
|
||||||
mov sp, r5
|
mov sp, r5
|
||||||
|
mov dpl, r6
|
||||||
|
mov dph, r7
|
||||||
|
|
||||||
|
/* Dump the stack contents after they have
|
||||||
|
* been restored to IRAM
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_SWITCH_FRAME_DUMP
|
#ifdef CONFIG_SWITCH_FRAME_DUMP
|
||||||
|
push dpl
|
||||||
|
push dph
|
||||||
lcall _up_dumpstack
|
lcall _up_dumpstack
|
||||||
|
pop dph
|
||||||
|
pop dpl
|
||||||
#endif
|
#endif
|
||||||
/* Then restore the context from the stack */
|
/* Get the pointer to the register save area */
|
||||||
|
|
||||||
|
mov a, #FRAME_SIZE
|
||||||
|
add a, dpl
|
||||||
|
mov dpl, a
|
||||||
|
clr a
|
||||||
|
addc a, dph
|
||||||
|
mov dph, a
|
||||||
|
|
||||||
|
/* Restore registers from the register save area */
|
||||||
|
|
||||||
|
lcall _up_restoreregisters
|
||||||
|
|
||||||
|
/* Restore registers from the new stack */
|
||||||
|
|
||||||
pop _bp
|
|
||||||
pop psw
|
|
||||||
pop ar1
|
|
||||||
pop ar0
|
|
||||||
pop ar7
|
|
||||||
pop ar6
|
|
||||||
pop ar5
|
|
||||||
pop ar4
|
|
||||||
pop ar3
|
|
||||||
pop ar2
|
|
||||||
pop b
|
|
||||||
pop dph
|
pop dph
|
||||||
pop dpl
|
pop dpl
|
||||||
|
|
||||||
@@ -197,8 +284,8 @@ void up_restorecontext(FAR struct xcptcontext *context) __naked
|
|||||||
sjmp 00004$
|
sjmp 00004$
|
||||||
00003$:
|
00003$:
|
||||||
setb ie.7
|
setb ie.7
|
||||||
00004$:
|
|
||||||
|
|
||||||
|
00004$:
|
||||||
pop acc
|
pop acc
|
||||||
ret
|
ret
|
||||||
_endasm;
|
_endasm;
|
||||||
|
|||||||
@@ -65,10 +65,134 @@
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* Name: up_savestack
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Save the entire interrupt stack contents in the provided context
|
||||||
|
* structure.
|
||||||
|
*
|
||||||
|
* Inputs:
|
||||||
|
* context - the context structure in which to save the stack info
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* - Interrupts are disabled
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
static void up_savestack(FAR struct xcptcontext *context, ubyte tos)
|
||||||
|
{
|
||||||
|
/* Copy the current stack frame from internal RAM to XRAM. */
|
||||||
|
|
||||||
|
ubyte nbytes = tos - (STACK_BASE-1);
|
||||||
|
NEAR ubyte *src = (NEAR ubyte*)STACK_BASE;
|
||||||
|
FAR ubyte *dest = context->stack;
|
||||||
|
|
||||||
|
context->nbytes = nbytes;
|
||||||
|
while (nbytes--)
|
||||||
|
{
|
||||||
|
*dest++ = *src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* Name: up_saveregs
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Save the interrupt registers into the TCB.
|
||||||
|
*
|
||||||
|
* Inputs:
|
||||||
|
* context - the context structure in which to save the register info
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* - Interrupts are disabled
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
static void up_saveregs(FAR struct xcptcontext *context, ubyte tos)
|
||||||
|
{
|
||||||
|
/* Copy the irq register save area into the TCB */
|
||||||
|
|
||||||
|
FAR ubyte *src = g_irqregs;
|
||||||
|
FAR ubyte *dest = context->regs;
|
||||||
|
ubyte nbytes = REGS_SIZE;
|
||||||
|
|
||||||
|
while (nbytes--)
|
||||||
|
{
|
||||||
|
*dest++ = *src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* Name: up_saveregisters
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Save the current registers in the context save area. This function
|
||||||
|
* is called from up_savecontext (below) and also from interrupt
|
||||||
|
* handling logic.
|
||||||
|
*
|
||||||
|
* Note that this function does not save:
|
||||||
|
* a, dptr, ie - these are saved in the stack area
|
||||||
|
* sp - this can be inferred from g_irqtos or struct xcptontext.nbytes.
|
||||||
|
*
|
||||||
|
* Inputs:
|
||||||
|
* regs - the context register array in which to save the register info
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
void up_saveregisters(FAR ubyte *regs) _naked
|
||||||
|
{
|
||||||
|
_asm
|
||||||
|
mov a, b
|
||||||
|
movx @dptr, a
|
||||||
|
inc dptr
|
||||||
|
mov a, r2
|
||||||
|
movx @dptr, a
|
||||||
|
inc dptr
|
||||||
|
mov a, r3
|
||||||
|
movx @dptr, a
|
||||||
|
inc dptr
|
||||||
|
mov a, r4
|
||||||
|
movx @dptr, a
|
||||||
|
inc dptr
|
||||||
|
mov a, r5
|
||||||
|
movx @dptr, a
|
||||||
|
inc dptr
|
||||||
|
mov a, r6
|
||||||
|
movx @dptr, a
|
||||||
|
inc dptr
|
||||||
|
mov a, r7
|
||||||
|
movx @dptr, a
|
||||||
|
inc dptr
|
||||||
|
mov a, r0
|
||||||
|
movx @dptr, a
|
||||||
|
inc dptr
|
||||||
|
mov a, r1
|
||||||
|
movx @dptr, a
|
||||||
|
inc dptr
|
||||||
|
mov a, psw
|
||||||
|
movx @dptr, a
|
||||||
|
clr psw
|
||||||
|
inc dptr
|
||||||
|
mov a, _bp
|
||||||
|
movx @dptr, a
|
||||||
|
ret
|
||||||
|
_endasm;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Name: up_savecontext
|
* Name: up_savecontext
|
||||||
*
|
*
|
||||||
@@ -89,8 +213,14 @@ ubyte up_savecontext(FAR struct xcptcontext *context) _naked
|
|||||||
{
|
{
|
||||||
_asm
|
_asm
|
||||||
/* Create the stack frame that we want when it is time to restore
|
/* Create the stack frame that we want when it is time to restore
|
||||||
* this* context. The return address will be the return address
|
* this context. The return address will be the return address
|
||||||
* of this function, the return value will be zero.
|
* of this function, the return value will be zero.
|
||||||
|
*
|
||||||
|
* ...
|
||||||
|
* return address (2 bytes, already on the stack)
|
||||||
|
* register a=0 (1 byte)
|
||||||
|
* register ie (1 byte)
|
||||||
|
* register dptr (2 bytes)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
clr a
|
clr a
|
||||||
@@ -100,42 +230,95 @@ ubyte up_savecontext(FAR struct xcptcontext *context) _naked
|
|||||||
push acc /* DPL = 1 */
|
push acc /* DPL = 1 */
|
||||||
clr a
|
clr a
|
||||||
push acc /* DPH = 0 */
|
push acc /* DPH = 0 */
|
||||||
push b
|
|
||||||
push ar2
|
|
||||||
push ar3
|
|
||||||
push ar4
|
|
||||||
push ar5
|
|
||||||
push ar6
|
|
||||||
push ar7
|
|
||||||
push ar0
|
|
||||||
push ar1
|
|
||||||
push psw
|
|
||||||
clr psw
|
|
||||||
push _bp
|
|
||||||
|
|
||||||
/* Disable interrupts while we create a snapshot of the stack */
|
/* Dump the stack contents before they are occupied into XRAM */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SWITCH_FRAME_DUMP
|
||||||
|
push dpl
|
||||||
|
push dph
|
||||||
|
lcall _up_dumpstack
|
||||||
|
pop dph
|
||||||
|
pop dpl
|
||||||
|
#endif
|
||||||
|
/* Disable interrupts while we create a snapshot of the stack
|
||||||
|
* and registers. At this point, we have 5 bytes on the stack
|
||||||
|
* to account for.
|
||||||
|
*/
|
||||||
|
|
||||||
push ie
|
push ie
|
||||||
mov ea, 0
|
mov ea, 0
|
||||||
|
|
||||||
/* Now copy the current stack frame (including the saved execution
|
/* Save the registers in the context save area */
|
||||||
* context) from internal RAM to XRAM.
|
|
||||||
|
push dpl
|
||||||
|
push dph
|
||||||
|
mov a, #XCPT_REGS
|
||||||
|
add a, dpl
|
||||||
|
mov dpl, a
|
||||||
|
clr a
|
||||||
|
addc a, dph
|
||||||
|
mov dph, a
|
||||||
|
lcall _up_saveregisters
|
||||||
|
pop dph
|
||||||
|
pop dpl
|
||||||
|
|
||||||
|
#ifdef CONFIG_SWITCH_FRAME_DUMP
|
||||||
|
/* Save the address of the context structure. We will
|
||||||
|
* need this later to dump the saved frame. Now we have
|
||||||
|
* 7 bytes on the stack to account for.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
push sp
|
push dpl
|
||||||
|
push dph
|
||||||
|
|
||||||
|
/* Push the top of frame stack pointer. We need to
|
||||||
|
* decrement the current SP value by three to account
|
||||||
|
* for dpst+IE on the stack above the end of the frame.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mov a, sp
|
||||||
|
subb a, #3
|
||||||
|
#else
|
||||||
|
/* Push the top of frame stack pointer. We need to
|
||||||
|
* decrement the current stack pointer by one to account
|
||||||
|
* for IE that we saved on the stack.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mov a, sp
|
||||||
|
dec a
|
||||||
|
#endif
|
||||||
|
push acc
|
||||||
|
|
||||||
|
/* Copy the current stack frame from internal RAM to XRAM. */
|
||||||
|
|
||||||
lcall _up_savestack
|
lcall _up_savestack
|
||||||
pop acc
|
pop acc
|
||||||
|
|
||||||
|
/* Dump the contents of the saved frame after it has been
|
||||||
|
* copied from memory/registers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SWITCH_FRAME_DUMP
|
||||||
|
pop dph
|
||||||
|
pop dpl
|
||||||
|
push dpl
|
||||||
|
push dph
|
||||||
|
lcall _up_dumpframe
|
||||||
|
pop dph
|
||||||
|
pop dpl
|
||||||
|
lcall _up_dumpstack
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Restore the interrupt state */
|
/* Restore the interrupt state */
|
||||||
|
|
||||||
pop ie
|
pop ie
|
||||||
|
|
||||||
/* Now that we have a snapshot of the desired stack frame saved,
|
/* Now that we have a snapshot of the desired stack frame saved,
|
||||||
* restore the correct stackpointer.
|
* we can release the stack frame (all but the return address)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mov a, sp
|
mov a, sp
|
||||||
subb a, #15
|
subb a, #4
|
||||||
mov sp, a
|
mov sp, a
|
||||||
mov dpl,#0
|
mov dpl,#0
|
||||||
ret
|
ret
|
||||||
@@ -143,14 +326,16 @@ ubyte up_savecontext(FAR struct xcptcontext *context) _naked
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Name: up_savestack
|
* Name: up_saveirqcontext
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Save the entire interrupt stack contents in the provided context
|
* The interrupt context was saved in g_irqtos and g_irqregs when the
|
||||||
* structure.
|
* interrupt was taken. If a context switch from the interrupted task
|
||||||
|
* will be made at the interrupt level, then these saved values must be
|
||||||
|
* copied into the TCB.
|
||||||
*
|
*
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* context - the context structure in which to save the stack info
|
* context - the structure in which to save the context info
|
||||||
*
|
*
|
||||||
* Return:
|
* Return:
|
||||||
* None
|
* None
|
||||||
@@ -160,19 +345,17 @@ ubyte up_savecontext(FAR struct xcptcontext *context) _naked
|
|||||||
*
|
*
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
void up_savestack(FAR struct xcptcontext *context, ubyte tos)
|
void up_saveirqcontext(FAR struct xcptcontext *context)
|
||||||
{
|
{
|
||||||
/* Now copy the current stack frame (including the saved execution
|
/* Save the number of bytes in the stack */
|
||||||
* context) from internal RAM to XRAM.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ubyte nbytes = tos - (STACK_BASE-1);
|
context->nbytes = g_irqtos - (STACK_BASE-1);
|
||||||
NEAR ubyte *src = (NEAR ubyte*)STACK_BASE;
|
|
||||||
FAR ubyte *dest = context->stack;
|
|
||||||
|
|
||||||
context->nbytes = nbytes;
|
/* Copy the current stack frame from internal RAM to XRAM. */
|
||||||
while (nbytes--)
|
|
||||||
{
|
up_savestack(context, g_irqtos);
|
||||||
*dest++ = *src++;
|
|
||||||
}
|
/* Copy the saved registers into the TCB */
|
||||||
|
|
||||||
|
up_saveregisters(context->regs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ void up_unblock_task(FAR _TCB *tcb)
|
|||||||
* Just copy the current stack into the OLD rtcb.
|
* Just copy the current stack into the OLD rtcb.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
up_savestack(&rtcb->xcp, g_irqtos);
|
up_saveirqcontext(&rtcb->xcp);
|
||||||
|
|
||||||
/* Restore the exception context of the rtcb at the (new) head
|
/* Restore the exception context of the rtcb at the (new) head
|
||||||
* of the g_readytorun task list.
|
* of the g_readytorun task list.
|
||||||
|
|||||||
+4
-4
@@ -64,7 +64,7 @@
|
|||||||
|
|
||||||
/* This is the name for un-named tasks */
|
/* This is the name for un-named tasks */
|
||||||
|
|
||||||
static FAR char g_noname[] = "no name";
|
static const char g_noname[] = "no name";
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
@@ -247,7 +247,7 @@ STATUS task_argsetup(FAR _TCB *tcb, const char *name,
|
|||||||
|
|
||||||
if (!name)
|
if (!name)
|
||||||
{
|
{
|
||||||
name = g_noname;
|
name = (char *)g_noname;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy the name into the TCB */
|
/* copy the name into the TCB */
|
||||||
@@ -260,7 +260,7 @@ STATUS task_argsetup(FAR _TCB *tcb, const char *name,
|
|||||||
#if CONFIG_TASK_NAME_SIZE > 0
|
#if CONFIG_TASK_NAME_SIZE > 0
|
||||||
tcb->argv[0] = tcb->name;
|
tcb->argv[0] = tcb->name;
|
||||||
#else
|
#else
|
||||||
tcb->argv[0] = g_noname;
|
tcb->argv[0] = (char *)g_noname;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* For pthreads, args are strictly pass-by-value; the char*
|
/* For pthreads, args are strictly pass-by-value; the char*
|
||||||
@@ -294,7 +294,7 @@ STATUS task_argsetup(FAR _TCB *tcb, const char *name,
|
|||||||
|
|
||||||
/* And just copy the argument. For pthreads, there
|
/* And just copy the argument. For pthreads, there
|
||||||
* is really only a single argument, argv[0]. It is
|
* is really only a single argument, argv[0]. It is
|
||||||
* copy as a value -- NOT duplicated.
|
* copied as a value -- NOT duplicated.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
i = 2;
|
i = 2;
|
||||||
|
|||||||
Reference in New Issue
Block a user