From 613f809f5dd64fbc9cb223116c6571b2a4195fa4 Mon Sep 17 00:00:00 2001 From: patacongo Date: Tue, 13 Mar 2007 23:03:12 +0000 Subject: [PATCH] 8052 context switch/interrupt integration; pthread arg setup changed git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@60 42af7a65-404d-4744-a932-0658087f49c3 --- arch/pjrc-8051/defconfig | 39 ++++++++- arch/pjrc-8051/src/pjrc.h | 5 +- arch/pjrc-8051/src/up_assert.c | 2 +- arch/pjrc-8051/src/up_debug.c | 116 ++++++++++++++----------- arch/pjrc-8051/src/up_head.S | 89 +++++++++++++++++-- arch/pjrc-8051/src/up_idle.c | 4 +- arch/pjrc-8051/src/up_internal.h | 23 +++-- arch/pjrc-8051/src/up_irq.c | 4 + arch/pjrc-8051/src/up_leds.c | 16 +++- arch/pjrc-8051/src/up_restorecontext.c | 3 +- arch/pjrc-8051/src/up_savecontext.c | 1 + arch/pjrc-8051/src/up_timerisr.c | 29 ++++++- 12 files changed, 242 insertions(+), 89 deletions(-) diff --git a/arch/pjrc-8051/defconfig b/arch/pjrc-8051/defconfig index 54bab70ead..8e122c065a 100644 --- a/arch/pjrc-8051/defconfig +++ b/arch/pjrc-8051/defconfig @@ -33,16 +33,47 @@ # ############################################################ # -# architecture selection +# Architecture selection # # CONFIG_ARCH - identifies the arch subdirectory -# CONFIG_ARCH_name - for use in C code -# CONFIG_PJRC_LEDS - Use LEDs to show state. Unique to 8051. +# CONFIG_ARCH_8051 - Set if processor is 8051 family +# CONFIG_ARCH_8052 = Set if processor is 8052 family # CONFIG_ARCH=pjrc-8051 +CONFIG_ARCH_8051=n CONFIG_ARCH_8052=y + +# +# Architecture-specific settings. These may mean nothing to +# other architectures. +# +# CONFIG-ARCH_PJRC - Set if using the PJRC 87C52 board +# CONFIG_ARCH_LEDS - Use LEDs to show state. Unique to 8051. +# CONFIG_8052_TIMER2 - Use timer2 for the 100Hz system timer. +# (default is timer0 at 112.5Hz). +# +# These features are only supported when CONFIG_ARCH_BRINGUP +# is set: +# +# CONFIG_ARCH_BRINGUP - Enables some bringup features +# CONFIG_FRAME_DUMP - Enable stack/frame dumping logic +# CONFIG_FRAME_DUMP_SHORT - Terse frame dump output +# CONFIG_SUPPRESS_INTERRUPTS - Do not enable interrupts +# CONFIG_SWITCH_FRAME_DUMP - Dump frames from normal switches +# CONFIG_INTERRUPT_FRAME_DUMP - Dump frames from interrupt switches +# CONFIG_LED_DEBUG - Enable debug output from LED logic +# CONFIG_ARCH_PJRC=y -CONFIG_8051_LEDS=y +CONFIG_ARCH_LEDS=y +CONFIG_8052_TIMER2=y + +CONFIG_ARCH_BRINGUP=y +CONFIG_FRAME_DUMP=y +CONFIG_FRAME_DUMP_SHORT=n +CONFIG_SUPPRESS_INTERRUPTS=y +CONFIG_SWITCH_FRAME_DUMP=y +CONFIG_INTERRUPT_FRAME_DUMP=n +CONFIG_LED_DEBUG=n # # General OS setup diff --git a/arch/pjrc-8051/src/pjrc.h b/arch/pjrc-8051/src/pjrc.h index fd875d3883..0934c78bea 100644 --- a/arch/pjrc-8051/src/pjrc.h +++ b/arch/pjrc-8051/src/pjrc.h @@ -183,8 +183,7 @@ sfr at 0xc9 T2MOD ; * Timer 0 provides only a 8-bit auto-reload mode. */ -#define CONFIG_80C52_TIMER2 1 -#ifdef CONFIG_80C52_TIMER2 +#ifdef CONFIG_8052_TIMER2 /* To use timer 2 as the 100Hz system timer, we need to calculate a 16-bit * reload value that results in 100Hz overflow interrupts. That value @@ -207,8 +206,6 @@ sfr at 0xc9 T2MOD ; * second. */ -# warning "No support for timer 0 as the system timer" - #endif /************************************************************************** diff --git a/arch/pjrc-8051/src/up_assert.c b/arch/pjrc-8051/src/up_assert.c index 6fc77bec9e..01bec26caa 100644 --- a/arch/pjrc-8051/src/up_assert.c +++ b/arch/pjrc-8051/src/up_assert.c @@ -73,7 +73,7 @@ static void _up_assert(int errorcode) /* __attribute__ ((noreturn)) */ (void)irqsave(); for(;;) { -#ifdef CONFIG_8051_LEDS +#ifdef CONFIG_ARCH_LEDS up_ledon(LED_PANIC); up_delay(250); up_ledoff(LED_PANIC); diff --git a/arch/pjrc-8051/src/up_debug.c b/arch/pjrc-8051/src/up_debug.c index 3ca2acae7d..9b52250e2d 100644 --- a/arch/pjrc-8051/src/up_debug.c +++ b/arch/pjrc-8051/src/up_debug.c @@ -58,17 +58,8 @@ * Private Functions ************************************************************/ -#ifdef CONFIG_FRAME_DUMP -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_putspace(void) __naked +#if defined(CONFIG_FRAME_DUMP) && defined(CONFIG_ARCH_BRINGUP) +static void up_putspace(void) __naked { _asm mov a, #0x20 @@ -84,34 +75,19 @@ static void _up_putcolon(void) __naked _endasm; } -static void _up_putnl(void) __naked -{ - _asm - ljmp PM2_ENTRY_NEWLINE - _endasm; -} - -static void _up_puts(__code char *ptr) -{ - for (; *ptr; ptr++) - { - up_putc(*ptr); - } -} - static void _up_dump16(__code char *ptr, ubyte msb, ubyte lsb) { - _up_puts(ptr); - _up_puthex(msb); - _up_puthex(lsb); - _up_putnl(); + up_puts(ptr); + up_puthex(msb); + up_puthex(lsb); + up_putnl(); } static void _up_dump8(__code char *ptr, ubyte b) { - _up_puts(ptr); - _up_puthex(b); - _up_putnl(); + up_puts(ptr); + up_puthex(b); + up_putnl(); } #endif @@ -119,11 +95,49 @@ static void _up_dump8(__code char *ptr, ubyte b) * Public Functions ************************************************************/ +/************************************************************ + * Name: up_puthex, up_puthex16, up_putnl, up_puts + ************************************************************/ + +#if defined(CONFIG_ARCH_BRINGUP) +void up_puthex(ubyte hex) __naked +{ + hex; /* To avoid unreferenced argument warning */ + _asm + mov a, dpl + ljmp PM2_ENTRY_PHEX + _endasm; +} + +void up_puthex16(int hex) __naked +{ + hex; /* To avoid unreferenced argument warning */ + _asm + ljmp PM2_ENTRY_PHEX16 + _endasm; +} + +void up_putnl(void) __naked +{ + _asm + ljmp PM2_ENTRY_NEWLINE + _endasm; +} + +void up_puts(__code char *ptr) +{ + for (; *ptr; ptr++) + { + up_putc(*ptr); + } +} +#endif + /************************************************************ * Name: up_dumpstack ************************************************************/ -#ifdef CONFIG_FRAME_DUMP +#if defined(CONFIG_FRAME_DUMP) && defined(CONFIG_ARCH_BRINGUP) void up_dumpstack(void) { NEAR ubyte *start = (NEAR ubyte *)(STACK_BASE & 0xf0); @@ -132,25 +146,25 @@ void up_dumpstack(void) while (start < end) { - _up_puthex((ubyte)start); + up_puthex((ubyte)start); _up_putcolon(); for (i = 0; i < 8; i++) { - _up_putspace(); + up_putspace(); if (start < (NEAR ubyte *)(STACK_BASE) || start > end) { - _up_putspace(); - _up_putspace(); + up_putspace(); + up_putspace(); } else { - _up_puthex(*start); + up_puthex(*start); } start++; } - _up_putnl(); + up_putnl(); } } #endif @@ -159,7 +173,7 @@ void up_dumpstack(void) * Name: up_dumpframe ************************************************************/ -#ifdef CONFIG_FRAME_DUMP +#if defined(CONFIG_FRAME_DUMP) && defined(CONFIG_ARCH_BRINGUP) void up_dumpframe(FAR struct xcptcontext *context) { #ifdef CONFIG_FRAME_DUMP_SHORT @@ -180,33 +194,33 @@ void up_dumpframe(FAR struct xcptcontext *context) for (i = 0; i < context->nbytes; i += 8) { - _up_puthex(i); + up_puthex(i); _up_putcolon(); for (j = 0; j < 8; j++) { k = i + j; - _up_putspace(); + up_putspace(); if (k >= context->nbytes) { - _up_putspace(); - _up_putspace(); + up_putspace(); + up_putspace(); } else { - _up_puthex(context->stack[k]); + up_puthex(context->stack[k]); } } - _up_putnl(); + up_putnl(); } - _up_puts(" REGS:"); + up_puts(" REGS:"); for (i = 0; i < REGS_SIZE; i++) { - _up_putspace(); - _up_puthex(context->regs[i]); + up_putspace(); + up_puthex(context->regs[i]); } - _up_putnl(); + up_putnl(); #endif } #endif diff --git a/arch/pjrc-8051/src/up_head.S b/arch/pjrc-8051/src/up_head.S index 1981e5dd8c..44f8038c9e 100644 --- a/arch/pjrc-8051/src/up_head.S +++ b/arch/pjrc-8051/src/up_head.S @@ -51,6 +51,12 @@ .area REG_BANK_0 (REL,OVR,DATA) .ds 8 +#ifndef CONFIG_8052_TIMER2 + .area XSEG +_g_timer0tick: + .ds 1 +#endif + /************************************************************ * Public Data ************************************************************/ @@ -93,9 +99,12 @@ .org PM2_VECTOR_TIMER0 push acc +#ifdef CONFIG_8052_TIMER2 mov a, #TIMER0_IRQ ljmp _up_interrupt - +#else + ljmp _up_timer0 +#endif .org PM2_VECTOR_EXTINT1 push acc mov a, #EXT_INT1_IRQ @@ -127,12 +136,76 @@ start: mov sp, #(STACK_BASE-1) -#ifdef CONFIG_8051_LEDS +#ifdef CONFIG_ARCH_LEDS lcall _up_ledinit #endif ljmp _os_start +/************************************************************ + * Name: up_timer0 + * + * Description: + * Timer 0, mode 0 can be used as a system timer. In that + * mode, the 1.8432 MHz clock is divided by 32. A single + * 8-bit value is incremented at 57600 Hz, which results + * in 225 Timer 0 overflow interrupts per second. + * + * The Timer0 interrupt vectors to this point which then + * does a software divide by 2 to get a system timer of + * 112.5Hz. + * + * On Entry: + * + * (1) acc on the stack and + * (2) the IRQ number(TIMER0_IRQ) in the accumulator + * + ************************************************************/ + +#ifndef CONFIG_8052_TIMER2 +_up_timer0: + ar2 = 0x02 + ar3 = 0x03 + ar4 = 0x04 + ar5 = 0x05 + ar6 = 0x06 + ar7 = 0x07 + ar0 = 0x00 + ar1 = 0x01 + + /* ACC already on the stack; push IE. Then disable interrupts */ + + push ie + clr ea + + /* Save the remaining registers with interrupts disabled + * + * a, ie, and dptr go on the stack. + */ + + push dpl + push dph + + /* Increment the tick counter */ + + mov dptr, #_g_timer0tick + movx a, @dptr + inc a + movx @dptr, a + + /* If bit 0 is '0', then just return from the interrupt */ + + anl a, #0x01 + jnz 00101$ + ljmp _up_timer0exit + + /* If bit 0 is '1', then process the interrupt */ + +00101$: + mov a, #TIMER0_IRQ + sjmp _up_timer0join +#endif + /************************************************************ * Name: up_interrupt * @@ -167,6 +240,7 @@ _up_interrupt: push dpl push dph +_up_timer0join: /* Other registers go into the IRQ register save area */ push acc @@ -175,7 +249,7 @@ _up_interrupt: /* Show interrupt status on the LEDs */ -#ifdef CONFIG_8051_LEDS +#ifdef CONFIG_ARCH_LEDS mov dpl, #LED_INIRQ lcall _up_ledon #endif @@ -343,12 +417,12 @@ _up_interrupt: push dpl push dph lcall _up_dumpstack - pop dpl pop dph + pop dpl #endif /* Get the pointer to the register save area */ - mov a, #FRAME_SIZE + mov a, #STACK_SIZE add a, dpl mov dpl, a clr a @@ -365,18 +439,19 @@ _up_interrupt: * (context switch). */ -#ifdef CONFIG_8051_LEDS +#ifdef CONFIG_ARCH_LEDS push dpl push dph mov dpl, #LED_INIRQ lcall _up_ledoff - pop dpl pop dph + pop dpl #endif /* Restore registers from the register save area */ lcall _up_restoreregisters +_up_timer0exit: /* Restore registers from the stack and return */ pop dph diff --git a/arch/pjrc-8051/src/up_idle.c b/arch/pjrc-8051/src/up_idle.c index c413c3f413..7c9ebc040c 100644 --- a/arch/pjrc-8051/src/up_idle.c +++ b/arch/pjrc-8051/src/up_idle.c @@ -50,7 +50,7 @@ * Private Data ************************************************************/ -#if defined(CONFIG_8051_LEDS) && defined(CONFIG_8051_BRINGUP) +#if defined(CONFIG_ARCH_LEDS) && defined(CONFIG_ARCH_BRINGUP) static ubyte g_ledtoggle = 0; #endif @@ -79,7 +79,7 @@ static ubyte g_ledtoggle = 0; void up_idle(void) { -#if defined(CONFIG_8051_LEDS) && defined(CONFIG_8051_BRINGUP) +#if defined(CONFIG_ARCH_LEDS) && defined(CONFIG_ARCH_BRINGUP) g_ledtoggle++; if (g_ledtoggle == 0x80) { diff --git a/arch/pjrc-8051/src/up_internal.h b/arch/pjrc-8051/src/up_internal.h index 6348030541..80900ca568 100644 --- a/arch/pjrc-8051/src/up_internal.h +++ b/arch/pjrc-8051/src/up_internal.h @@ -50,16 +50,6 @@ * Public Definitions **************************************************************************/ -/* Bring-up debug configurations */ - -#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 **************************************************************************/ @@ -124,9 +114,16 @@ 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 */ +/* Defined in up_debug.c */ -#ifdef CONFIG_FRAME_DUMP +#if defined(CONFIG_ARCH_BRINGUP) +extern void up_puthex(ubyte hex) __naked; +extern void up_puthex16(int hex) __naked; +extern void up_putnl(void) __naked; +extern void up_puts(__code char *ptr); +#endif + +#if defined(CONFIG_FRAME_DUMP) && defined(CONFIG_ARCH_BRINGUP) extern void up_dumpstack(void); extern void up_dumpframe(FAR struct xcptcontext *context); #else @@ -136,7 +133,7 @@ extern void up_dumpframe(FAR struct xcptcontext *context); /* Defined in up_leds.c */ -#ifdef CONFIG_8051_LEDS +#ifdef CONFIG_ARCH_LEDS extern void up_ledinit(void); extern void up_ledon(ubyte led); extern void up_ledoff(ubyte led); diff --git a/arch/pjrc-8051/src/up_irq.c b/arch/pjrc-8051/src/up_irq.c index bf76b25a86..a23e4c17b4 100644 --- a/arch/pjrc-8051/src/up_irq.c +++ b/arch/pjrc-8051/src/up_irq.c @@ -71,6 +71,10 @@ extern int g_nints; void up_irqinitialize(void) { + /* Set interrupt priorities (all low) */ + + IP = 0; + #ifdef CONFIG_SUPPRESS_INTERRUPTS /* Disable all interrupts */ diff --git a/arch/pjrc-8051/src/up_leds.c b/arch/pjrc-8051/src/up_leds.c index 41d8ac8fa1..c7730ac3ef 100644 --- a/arch/pjrc-8051/src/up_leds.c +++ b/arch/pjrc-8051/src/up_leds.c @@ -57,7 +57,7 @@ static ubyte g_ledstate; * Private Functions ************************************************************/ -#if defined(CONFIG_LED_DEBUG) && defined(CONFIG_8051_LEDS) +#if defined(CONFIG_LED_DEBUG) && defined(CONFIG_ARCH_LEDS) static void _up_puthex(ubyte hex) __naked { hex; /* To avoid unreferenced argument warning */ @@ -122,7 +122,7 @@ static void _up_putnl(void) __naked * Name: up_ledinit ************************************************************/ -#ifdef CONFIG_8051_LEDS +#ifdef CONFIG_ARCH_LEDS void up_ledinit(void) { /* Set all ports as outputs */ @@ -143,6 +143,10 @@ void up_ledinit(void) void up_ledon(ubyte led) { + /* This may be called from an interrupt handler */ + + irqstate_t flags = irqsave(); + #ifdef RESET_KLUDGE_NEEDED /* I don't understand why this happens yet, but sometimes * it is necessary to reconfigure port E. @@ -164,6 +168,7 @@ void up_ledon(ubyte led) } _up_showledon(); + irqrestore(flags); } /************************************************************ @@ -172,6 +177,10 @@ void up_ledon(ubyte led) void up_ledoff(ubyte led) { + /* This may be called from an interrupt handler */ + + irqstate_t flags = irqsave(); + #ifdef RESET_KLUDGE_NEEDED /* I don't understand why this happens yet, but sometimes * it is necessary to reconfigure port E. @@ -193,5 +202,6 @@ void up_ledoff(ubyte led) } _up_showledoff(); + irqrestore(flags); } -#endif /* CONFIG_8051_LEDS */ +#endif /* CONFIG_ARCH_LEDS */ diff --git a/arch/pjrc-8051/src/up_restorecontext.c b/arch/pjrc-8051/src/up_restorecontext.c index bdb2fea241..fa7c8c2d03 100644 --- a/arch/pjrc-8051/src/up_restorecontext.c +++ b/arch/pjrc-8051/src/up_restorecontext.c @@ -37,6 +37,7 @@ * Included Files **************************************************************************/ +#include #include #include "up_internal.h" @@ -260,7 +261,7 @@ void up_restorecontext(FAR struct xcptcontext *context) __naked #endif /* Get the pointer to the register save area */ - mov a, #FRAME_SIZE + mov a, #STACK_SIZE add a, dpl mov dpl, a clr a diff --git a/arch/pjrc-8051/src/up_savecontext.c b/arch/pjrc-8051/src/up_savecontext.c index 346f9271d6..83310534ca 100644 --- a/arch/pjrc-8051/src/up_savecontext.c +++ b/arch/pjrc-8051/src/up_savecontext.c @@ -37,6 +37,7 @@ * Included Files **************************************************************************/ +#include #include #include #include "up_internal.h" diff --git a/arch/pjrc-8051/src/up_timerisr.c b/arch/pjrc-8051/src/up_timerisr.c index 5580b5bb58..8f139d89a7 100644 --- a/arch/pjrc-8051/src/up_timerisr.c +++ b/arch/pjrc-8051/src/up_timerisr.c @@ -89,10 +89,10 @@ int up_timerisr(int irq, FAR ubyte *frame) void up_timerinit(void) { -#ifdef CONFIG_80C52_TIMER2 +#ifdef CONFIG_8052_TIMER2 up_disable_irq(TIMER2_IRQ); - /* Set up timer 2 -- See up_internal.h for details */ + /* Set up timer 2 -- See pjrc.h for details */ T2MOD = 0; @@ -108,7 +108,7 @@ void up_timerinit(void) /* Configure for interrupts */ - T2CON = 0x40; + T2CON = 0x04; /* Attach and enable the timer interrupt */ @@ -116,6 +116,29 @@ void up_timerinit(void) up_enable_irq(TIMER2_IRQ); #else + /* Timer 0, mode 0 can be used as a system timer. In that mode, the + * 1.8432 MHz clock is divided by 32. A single 8-bit value is incremented + * at 57600 Hz, which results in 225 Timer 0 overflow interrupts per + * second. + */ + + up_disable_irq(TIMER0_IRQ); + + /* Initialize timer 0 */ + + TR0 = 0; /* Make sure timer 0 is stopped */ + TF0 = 0; /* Clear the overflow flag */ + TMOD &= 0xF0; /* Set to mode 0 (without changing timer1) */ + TL0 = 0; /* Clear timer 0 value */ + TH0 = 0; + + /* Attach and enable the timer interrupt */ + + irq_attach(TIMER0_IRQ, (xcpt_t)up_timerisr); + + TR0 = 1; /* Start the timer */ + up_enable_irq(TIMER0_IRQ); + # warning "No support for timer 0 as the system timer" #endif }