summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-03-13 14:08:18 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-03-13 14:08:18 +0000
commitbb1f767de46e1648ffc3f5a903969233b2a0d675 (patch)
tree85e820d761e1a626df7b38c50dfba69387b02d1d
parentdc5ec457e96f2c2e874f0626e0d8399ce136a4b3 (diff)
downloadnuttx-bb1f767de46e1648ffc3f5a903969233b2a0d675.tar.gz
nuttx-bb1f767de46e1648ffc3f5a903969233b2a0d675.tar.bz2
nuttx-bb1f767de46e1648ffc3f5a903969233b2a0d675.zip
8051 integration
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@59 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/arch/pjrc-8051/defconfig2
-rw-r--r--nuttx/arch/pjrc-8051/include/irq.h74
-rw-r--r--nuttx/arch/pjrc-8051/src/pjrc.h2
-rw-r--r--nuttx/arch/pjrc-8051/src/up_blocktask.c2
-rw-r--r--nuttx/arch/pjrc-8051/src/up_debug.c66
-rw-r--r--nuttx/arch/pjrc-8051/src/up_delay.c1
-rw-r--r--nuttx/arch/pjrc-8051/src/up_head.S129
-rw-r--r--nuttx/arch/pjrc-8051/src/up_idle.c15
-rw-r--r--nuttx/arch/pjrc-8051/src/up_initialize.c17
-rw-r--r--nuttx/arch/pjrc-8051/src/up_initialstate.c20
-rw-r--r--nuttx/arch/pjrc-8051/src/up_internal.h36
-rw-r--r--nuttx/arch/pjrc-8051/src/up_irq.c8
-rw-r--r--nuttx/arch/pjrc-8051/src/up_leds.c106
-rw-r--r--nuttx/arch/pjrc-8051/src/up_releasepending.c2
-rw-r--r--nuttx/arch/pjrc-8051/src/up_reprioritizertr.c2
-rw-r--r--nuttx/arch/pjrc-8051/src/up_restorecontext.c133
-rw-r--r--nuttx/arch/pjrc-8051/src/up_savecontext.c253
-rw-r--r--nuttx/arch/pjrc-8051/src/up_unblocktask.c2
-rw-r--r--nuttx/sched/task_setup.c8
19 files changed, 722 insertions, 156 deletions
diff --git a/nuttx/arch/pjrc-8051/defconfig b/nuttx/arch/pjrc-8051/defconfig
index 28044f43f..54bab70ea 100644
--- a/nuttx/arch/pjrc-8051/defconfig
+++ b/nuttx/arch/pjrc-8051/defconfig
@@ -42,7 +42,7 @@
CONFIG_ARCH=pjrc-8051
CONFIG_ARCH_8052=y
CONFIG_ARCH_PJRC=y
-CONFIG_8051_LEDS=n
+CONFIG_8051_LEDS=y
#
# General OS setup
diff --git a/nuttx/arch/pjrc-8051/include/irq.h b/nuttx/arch/pjrc-8051/include/irq.h
index 819a73df7..45891986a 100644
--- a/nuttx/arch/pjrc-8051/include/irq.h
+++ b/nuttx/arch/pjrc-8051/include/irq.h
@@ -90,28 +90,52 @@
#define FRAME_RETLS 0
#define FRAME_RETMS 1
-/* Then a full context save area which can be indexed with
- * the following definitions (relative to the beginning of
- * the initial frame.
+/* Then a partial context context save area that can be
+ * indexed with the following definitions (relative to the
+ * beginning of the initial frame.
*/
#define FRAME_ACC 2
#define FRAME_IE 3
#define FRAME_DPL 4
#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
@@ -122,8 +146,26 @@
#ifndef __ASSEMBLY__
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;
+
+ /* 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];
+
+ /* 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 */
diff --git a/nuttx/arch/pjrc-8051/src/pjrc.h b/nuttx/arch/pjrc-8051/src/pjrc.h
index 41f5a7e21..fd875d388 100644
--- a/nuttx/arch/pjrc-8051/src/pjrc.h
+++ b/nuttx/arch/pjrc-8051/src/pjrc.h
@@ -150,7 +150,7 @@ xdata at 0xF903 ubyte p82c55_def_config;
#define LED_STARTED 0
#define LED_HEAPALLOCATE 1
#define LED_IRQSENABLED 2
-#define LED_UNUSED1 3
+#define LED_IDLE 3
#define LED_UNUSED2 4
#define LED_INIRQ 5
#define LED_ASSERTION 6
diff --git a/nuttx/arch/pjrc-8051/src/up_blocktask.c b/nuttx/arch/pjrc-8051/src/up_blocktask.c
index e8ea55523..9d9094a77 100644
--- a/nuttx/arch/pjrc-8051/src/up_blocktask.c
+++ b/nuttx/arch/pjrc-8051/src/up_blocktask.c
@@ -131,7 +131,7 @@ void up_block_task(FAR _TCB *tcb, tstate_t task_state)
* 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
* of the g_readytorun task list.
diff --git a/nuttx/arch/pjrc-8051/src/up_debug.c b/nuttx/arch/pjrc-8051/src/up_debug.c
index 6f1485aaa..3ca2acae7 100644
--- a/nuttx/arch/pjrc-8051/src/up_debug.c
+++ b/nuttx/arch/pjrc-8051/src/up_debug.c
@@ -80,7 +80,7 @@ static void _up_putcolon(void) __naked
{
_asm
mov a, #0x3a
- lcall PM2_ENTRY_COUT
+ ljmp PM2_ENTRY_COUT
_endasm;
}
@@ -126,7 +126,7 @@ static void _up_dump8(__code char *ptr, ubyte b)
#ifdef CONFIG_FRAME_DUMP
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;
ubyte i;
@@ -138,7 +138,16 @@ void up_dumpstack(void)
for (i = 0; i < 8; i++)
{
_up_putspace();
- _up_puthex(*start);
+ if (start < (NEAR ubyte *)(STACK_BASE) ||
+ start > end)
+ {
+ _up_putspace();
+ _up_putspace();
+ }
+ else
+ {
+ _up_puthex(*start);
+ }
start++;
}
_up_putnl();
@@ -153,11 +162,52 @@ void up_dumpstack(void)
#ifdef CONFIG_FRAME_DUMP
void up_dumpframe(FAR struct xcptcontext *context)
{
- FAR ubyte *start = &context->stack[context->nbytes - FRAME_SIZE];
- _up_dump16(" RET ", start[FRAME_RETMS], start[FRAME_RETLS]);
- _up_dump8(" IE ", start[FRAME_IE]);
- _up_dump16(" DPTR ", start[FRAME_DPH], start[FRAME_DPL]);
- _up_dump8(" PSW ", start[FRAME_PSW]);
+#ifdef CONFIG_FRAME_DUMP_SHORT
+ FAR ubyte *stack = &context->stack[context->nbytes - FRAME_SIZE];
+ FAR ubyte *regs = context->regs;
+
+ _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
diff --git a/nuttx/arch/pjrc-8051/src/up_delay.c b/nuttx/arch/pjrc-8051/src/up_delay.c
index 7b682033f..111d2c0df 100644
--- a/nuttx/arch/pjrc-8051/src/up_delay.c
+++ b/nuttx/arch/pjrc-8051/src/up_delay.c
@@ -38,6 +38,7 @@
************************************************************/
#include <nuttx/config.h>
+#include <sys/types.h>
#include "up_internal.h"
/************************************************************
diff --git a/nuttx/arch/pjrc-8051/src/up_head.S b/nuttx/arch/pjrc-8051/src/up_head.S
index 33d9db3dd..1981e5dd8 100644
--- a/nuttx/arch/pjrc-8051/src/up_head.S
+++ b/nuttx/arch/pjrc-8051/src/up_head.S
@@ -57,12 +57,14 @@
.globl _g_irqtos
.globl _g_irqcontext
+ .globl _g_irqregs
/************************************************************
* Public Functions
************************************************************/
.globl _irq_dispatch
+ .globl _up_restoreregisters
/************************************************************
* Program entry points
@@ -157,33 +159,31 @@ _up_interrupt:
push ie
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 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 */
-#ifdef CONFIG_8051_LEDS
+ /* 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
mov dpl, #LED_INIRQ
lcall _up_ledon
- pop ar2
-#else
- mov r2, a
#endif
+
+ /* Save the IRQ number in r2 */
+
+ pop ar2
+
/* Mark that we are in an interrupt and provide the top
* of stack pointer to the context switching logic.
*/
@@ -197,7 +197,7 @@ _up_interrupt:
* structure.
*/
- mov dptr,#_g_irqcontext
+ mov dptr, #_g_irqcontext
clr a
movx @dptr,a
inc dptr
@@ -238,8 +238,17 @@ _up_interrupt:
movx a, @dptr
mov r3, a
- orl a, r2
- jz 00003$
+ orl a, r2
+ 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 */
@@ -285,6 +294,8 @@ _up_interrupt:
/* Save r2-3 = &context->stack */
inc dptr
+ push dpl
+ push dph
mov r2, dpl
mov r3, dph
@@ -293,9 +304,10 @@ _up_interrupt:
mov r0, #STACK_BASE
/* Top of the copy loop */
-00001$:
- dec r4
- jz 00002$
+00002$:
+ mov a, r4 /* a = bytes left to transfer */
+ dec r4 /* (for next time through the loop) */
+ jz 00003$ /* Jump if a = 0 (done) */
/* Fetch the next byte from context->stack */
@@ -316,38 +328,69 @@ _up_interrupt:
/* Increment the IRAM pointer */
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$:
+00003$:
+ pop dph
+ pop dpl
mov sp, r5
#ifdef CONFIG_INTERRUPT_FRAME_DUMP
+ push dpl
+ push dph
lcall _up_dumpstack
+ pop dpl
+ pop dph
#endif
- /* Then restore the context from the stack and return
- * from the interrupt
+ /* 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).
*/
-00003$:
#ifdef CONFIG_8051_LEDS
+ push dpl
+ push dph
mov dpl, #LED_INIRQ
lcall _up_ledoff
+ pop dpl
+ pop dph
#endif
- pop _bp
- pop psw
- pop ar1
- pop ar0
- pop ar7
- pop ar6
- pop ar5
- pop ar4
- pop ar3
- pop ar2
- pop b
+ /* Restore registers from the register save area */
+
+ lcall _up_restoreregisters
+
+ /* Restore registers from the stack and return */
+
pop dph
pop dpl
- pop ie
+
+ /* 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
reti
diff --git a/nuttx/arch/pjrc-8051/src/up_idle.c b/nuttx/arch/pjrc-8051/src/up_idle.c
index fcc89ed9b..c413c3f41 100644
--- a/nuttx/arch/pjrc-8051/src/up_idle.c
+++ b/nuttx/arch/pjrc-8051/src/up_idle.c
@@ -50,6 +50,10 @@
* Private Data
************************************************************/
+#if defined(CONFIG_8051_LEDS) && defined(CONFIG_8051_BRINGUP)
+static ubyte g_ledtoggle = 0;
+#endif
+
/************************************************************
* Private Functions
************************************************************/
@@ -75,5 +79,16 @@
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
}
diff --git a/nuttx/arch/pjrc-8051/src/up_initialize.c b/nuttx/arch/pjrc-8051/src/up_initialize.c
index d0680b6cf..4d988501b 100644
--- a/nuttx/arch/pjrc-8051/src/up_initialize.c
+++ b/nuttx/arch/pjrc-8051/src/up_initialize.c
@@ -60,6 +60,16 @@
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
* switch must be performed, the follwing will be set to
* to that address of the relevant context structure. The
@@ -69,6 +79,13 @@ ubyte g_irqtos;
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
************************************************************/
diff --git a/nuttx/arch/pjrc-8051/src/up_initialstate.c b/nuttx/arch/pjrc-8051/src/up_initialstate.c
index 1eae39fa9..7fc0ddc39 100644
--- a/nuttx/arch/pjrc-8051/src/up_initialstate.c
+++ b/nuttx/arch/pjrc-8051/src/up_initialstate.c
@@ -75,6 +75,7 @@
void up_initial_state(FAR _TCB *tcb)
{
FAR ubyte *frame = tcb->xcp.stack;
+ FAR ubyte *regs = tcb->xcp.regs;
/* 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_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;
+
+ /* 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;
- frame[FRAME_IE] = 0x80;
- frame[FRAME_PSW] = 0;
+ /* Initialize the remaining register save area which is
+ * outside of the stack save area.
+ */
- tcb->xcp.nbytes = FRAME_SIZE;
+ tcb->xcp.regs[REGS_PSW] = 0;
}
diff --git a/nuttx/arch/pjrc-8051/src/up_internal.h b/nuttx/arch/pjrc-8051/src/up_internal.h
index 19c628f5c..634803054 100644
--- a/nuttx/arch/pjrc-8051/src/up_internal.h
+++ b/nuttx/arch/pjrc-8051/src/up_internal.h
@@ -41,6 +41,7 @@
**************************************************************************/
#include <nuttx/config.h>
+#include <arch/irq.h>
#ifdef CONFIG_ARCH_PJRC
# include "pjrc.h"
#endif
@@ -51,10 +52,13 @@
/* Bring-up debug configurations */
-#define CONFIG_FRAME_DUMP 1 /* Enabled stack/frame dumping logic */
-#define CONFIG_SUPPRESS_INTERRUPTS 1 /* Do not enable interrupts */
-#define CONFIG_SWITCH_FRAME_DUMP 1 /* Dump frames from normal switches */
+#define CONFIG_8051_BRINGUP 1 /* Enables some bringup features */
+#define CONFIG_FRAME_DUMP 1 /* Enable stack/frame dumping logic */
+#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 */
+#define CONFIG_LED_DEBUG 1 /* Enabled debug output from LED logic */
/**************************************************************************
* Public Types
@@ -75,6 +79,16 @@
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
* switch must be performed, the follwing will be set to
* to that address of the relevant context structure. The
@@ -84,6 +98,12 @@ extern ubyte g_irqtos;
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 */
/**************************************************************************
@@ -95,11 +115,13 @@ extern FAR struct xcptcontext *g_irqcontext;
#if CONFIG_MM_REGIONS > 1
extern void up_addregion(void);
#endif
-extern void up_delay(ubyte milliseconds) __naked;
+extern void up_delay(ubyte milliseconds) __naked;
extern void up_irqinitialize(void);
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 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);
/* Defined in up_assert.c */
@@ -116,8 +138,8 @@ extern void up_dumpframe(FAR struct xcptcontext *context);
#ifdef CONFIG_8051_LEDS
extern void up_ledinit(void);
-extern void up_ledon(int led);
-extern void up_ledoff(int led);
+extern void up_ledon(ubyte led);
+extern void up_ledoff(ubyte led);
#else
# define up_ledinit()
# define up_ledon(led)
diff --git a/nuttx/arch/pjrc-8051/src/up_irq.c b/nuttx/arch/pjrc-8051/src/up_irq.c
index 8d024ca3a..bf76b25a8 100644
--- a/nuttx/arch/pjrc-8051/src/up_irq.c
+++ b/nuttx/arch/pjrc-8051/src/up_irq.c
@@ -43,6 +43,8 @@
#include <8052.h>
#include "up_internal.h"
+#include <debug.h>
+extern int g_nints;
/************************************************************
* Definitions
************************************************************/
@@ -69,7 +71,7 @@
void up_irqinitialize(void)
{
-#ifndef CONFIG_SUPPRESS_INTERRUPTS
+#ifdef CONFIG_SUPPRESS_INTERRUPTS
/* Disable all interrupts */
IE = 0;
@@ -122,7 +124,7 @@ void up_disable_irq(int irq)
{
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)
{
- IE &= ~(1 << irq);
+ IE |= g_ntobit[irq];
}
}
diff --git a/nuttx/arch/pjrc-8051/src/up_leds.c b/nuttx/arch/pjrc-8051/src/up_leds.c
index 2c1243601..41d8ac8fa 100644
--- a/nuttx/arch/pjrc-8051/src/up_leds.c
+++ b/nuttx/arch/pjrc-8051/src/up_leds.c
@@ -45,16 +45,75 @@
* Definitions
************************************************************/
+#define RESET_KLUDGE_NEEDED 1
+
/************************************************************
* Private Data
************************************************************/
-static uint32 g_ledstate;
+static ubyte g_ledstate;
/************************************************************
* 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
************************************************************/
@@ -68,38 +127,71 @@ void up_ledinit(void)
{
/* Set all ports as outputs */
- p82c55_abc_config = 128;
p82c55_def_config = 128;
/* Turn LED 1-7 off; turn LED 0 on */
- g_ledstate = 0x000000fe;
+ g_ledstate = 0xfe;
p82c55_port_e = g_ledstate;
+
+ _up_showledinit();
}
/************************************************************
* 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)
{
- g_ledstate &= ~(1 << led);
+ g_ledstate &= ~(g_ntobit[led]);
p82c55_port_e = g_ledstate;
}
+
+ _up_showledon();
}
/************************************************************
* 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)
{
- g_ledstate |= (1 << led);
+ g_ledstate |= g_ntobit[led];
p82c55_port_e = g_ledstate;
}
+
+ _up_showledoff();
}
#endif /* CONFIG_8051_LEDS */
diff --git a/nuttx/arch/pjrc-8051/src/up_releasepending.c b/nuttx/arch/pjrc-8051/src/up_releasepending.c
index dfab2ecb5..8a58da9e6 100644
--- a/nuttx/arch/pjrc-8051/src/up_releasepending.c
+++ b/nuttx/arch/pjrc-8051/src/up_releasepending.c
@@ -94,7 +94,7 @@ void up_release_pending(void)
* 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
* of the g_readytorun task list.
diff --git a/nuttx/arch/pjrc-8051/src/up_reprioritizertr.c b/nuttx/arch/pjrc-8051/src/up_reprioritizertr.c
index 6aa1da68a..1b8a3adbf 100644
--- a/nuttx/arch/pjrc-8051/src/up_reprioritizertr.c
+++ b/nuttx/arch/pjrc-8051/src/up_reprioritizertr.c
@@ -142,7 +142,7 @@ void up_reprioritize_rtr(FAR _TCB *tcb, ubyte priority)
* 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
* of the g_readytorun task list.
diff --git a/nuttx/arch/pjrc-8051/src/up_restorecontext.c b/nuttx/arch/pjrc-8051/src/up_restorecontext.c
index ce5735db9..bdb2fea24 100644
--- a/nuttx/arch/pjrc-8051/src/up_restorecontext.c
+++ b/nuttx/arch/pjrc-8051/src/up_restorecontext.c
@@ -69,6 +69,66 @@
**************************************************************************/
/**************************************************************************
+ * 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
*
* Description:
@@ -95,6 +155,10 @@ void up_restorecontext(FAR struct xcptcontext *context) __naked
ar0 = 0x00
ar1 = 0x01
+ /* Dump the contents of the saved frame before it is copied back
+ * to memory/registers.
+ */
+
#ifdef CONFIG_SWITCH_FRAME_DUMP
push dpl
push dph
@@ -109,14 +173,17 @@ void up_restorecontext(FAR struct xcptcontext *context) __naked
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
* R2-3 - Holds the working 16-bit XRAM pointer
* R4 - Holds the working byte count
* R5 - Holds the new stack pointer
- * R6-7 - Not used
+ * R6-7 - Saved context pointer
*/
/* Fetch r4 = context->nbytes */
@@ -129,26 +196,32 @@ void up_restorecontext(FAR struct xcptcontext *context) __naked
add a, #(STACK_BASE-1)
mov r5, a
- /* Save r2-3 = &context->stack */
+ /* Save r2-3 and r6-r7 = &context->stack */
inc dptr
mov r2, dpl
mov r3, dph
+ mov r6, dpl
+ mov r7, dph
/* Set r0 = stack base address */
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$:
- dec r4
- jz 00002$
+ mov a, r4 /* a = bytes left to transfer */
+ dec r4 /* (for next time through the loop) */
+ jz 00002$ /* Jump if a = 0 (done) */
/* Fetch the next byte from context->stack */
mov dpl, r2
mov dph, r3
- movx a,@dptr
+ movx a, @dptr
/* Increment the XRAM pointer */
@@ -166,26 +239,40 @@ void up_restorecontext(FAR struct xcptcontext *context) __naked
sjmp 00001$
00002$:
- /* Set the new stack pointer */
+ /* Set the new stack pointer and recover the
+ * context->stack pointer.
+ */
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
+ push dpl
+ push dph
lcall _up_dumpstack
+ pop dph
+ pop dpl
#endif
- /* Then restore the context from the stack */
-
- pop _bp
- pop psw
- pop ar1
- pop ar0
- pop ar7
- pop ar6
- pop ar5
- pop ar4
- pop ar3
- pop ar2
- pop b
+ /* 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 dph
pop dpl
@@ -197,8 +284,8 @@ void up_restorecontext(FAR struct xcptcontext *context) __naked
sjmp 00004$
00003$:
setb ie.7
- 00004$:
+ 00004$:
pop acc
ret
_endasm;
diff --git a/nuttx/arch/pjrc-8051/src/up_savecontext.c b/nuttx/arch/pjrc-8051/src/up_savecontext.c
index 9631c2a11..346f9271d 100644
--- a/nuttx/arch/pjrc-8051/src/up_savecontext.c
+++ b/nuttx/arch/pjrc-8051/src/up_savecontext.c
@@ -66,10 +66,134 @@
**************************************************************************/
/**************************************************************************
+ * 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
**************************************************************************/
/**************************************************************************
+ * 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
*
* Description:
@@ -89,8 +213,14 @@ ubyte up_savecontext(FAR struct xcptcontext *context) _naked
{
_asm
/* 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.
+ *
+ * ...
+ * return address (2 bytes, already on the stack)
+ * register a=0 (1 byte)
+ * register ie (1 byte)
+ * register dptr (2 bytes)
*/
clr a
@@ -100,42 +230,95 @@ ubyte up_savecontext(FAR struct xcptcontext *context) _naked
push acc /* DPL = 1 */
clr a
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
mov ea, 0
- /* Now copy the current stack frame (including the saved execution
- * context) from internal RAM to XRAM.
+ /* Save the registers in the context save area */
+
+ 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 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.
*/
- push sp
+ 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
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 */
pop ie
/* 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
- subb a, #15
+ subb a, #4
mov sp, a
mov dpl,#0
ret
@@ -143,14 +326,16 @@ ubyte up_savecontext(FAR struct xcptcontext *context) _naked
}
/**************************************************************************
- * Name: up_savestack
+ * Name: up_saveirqcontext
*
* Description:
- * Save the entire interrupt stack contents in the provided context
- * structure.
+ * The interrupt context was saved in g_irqtos and g_irqregs when the
+ * 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:
- * context - the context structure in which to save the stack info
+ * context - the structure in which to save the context info
*
* Return:
* 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
- * context) from internal RAM to XRAM.
- */
+ /* Save the number of bytes in the stack */
- ubyte nbytes = tos - (STACK_BASE-1);
- NEAR ubyte *src = (NEAR ubyte*)STACK_BASE;
- FAR ubyte *dest = context->stack;
+ context->nbytes = g_irqtos - (STACK_BASE-1);
- context->nbytes = nbytes;
- while (nbytes--)
- {
- *dest++ = *src++;
- }
+ /* Copy the current stack frame from internal RAM to XRAM. */
+
+ up_savestack(context, g_irqtos);
+
+ /* Copy the saved registers into the TCB */
+
+ up_saveregisters(context->regs);
}
diff --git a/nuttx/arch/pjrc-8051/src/up_unblocktask.c b/nuttx/arch/pjrc-8051/src/up_unblocktask.c
index 3f09d7ce5..005e74e54 100644
--- a/nuttx/arch/pjrc-8051/src/up_unblocktask.c
+++ b/nuttx/arch/pjrc-8051/src/up_unblocktask.c
@@ -122,7 +122,7 @@ void up_unblock_task(FAR _TCB *tcb)
* 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
* of the g_readytorun task list.
diff --git a/nuttx/sched/task_setup.c b/nuttx/sched/task_setup.c
index 3573e72d9..744f5fbf4 100644
--- a/nuttx/sched/task_setup.c
+++ b/nuttx/sched/task_setup.c
@@ -64,7 +64,7 @@
/* 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
@@ -247,7 +247,7 @@ STATUS task_argsetup(FAR _TCB *tcb, const char *name,
if (!name)
{
- name = g_noname;
+ name = (char *)g_noname;
}
/* 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
tcb->argv[0] = tcb->name;
#else
- tcb->argv[0] = g_noname;
+ tcb->argv[0] = (char *)g_noname;
#endif
/* 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
* is really only a single argument, argv[0]. It is
- * copy as a value -- NOT duplicated.
+ * copied as a value -- NOT duplicated.
*/
i = 2;