Skip to content
Snippets Groups Projects
up_head.S 8.25 KiB
Newer Older
patacongo's avatar
patacongo committed
/************************************************************
 * up_head.S
 *
 *   Copyright (C) 2007 Gregory Nutt. All rights reserved.
 *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name Gregory Nutt nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ************************************************************/

/************************************************************
 * Included Files
 ************************************************************/

patacongo's avatar
patacongo committed
#include <nuttx/irq.h>
#include "up_internal.h"

	.module	up_head
	.optsdcc -mmcs51 --model-large

/************************************************************
 * Private Data
 ************************************************************/

	.area REG_BANK_0	(REL,OVR,DATA)
	.ds 8

/************************************************************
 * Public Data
 ************************************************************/

	.globl	_g_irqcontext
patacongo's avatar
patacongo committed
	.globl	_g_irqregs
patacongo's avatar
patacongo committed

/************************************************************
 * Public Functions
 ************************************************************/

	.globl	_irq_dispatch
patacongo's avatar
patacongo committed
	.globl	_up_restoreregisters
patacongo's avatar
patacongo committed

/************************************************************
 * Program entry points
 ************************************************************/

/* Program entry is through PROGRAM_BASE.  This is just a
 * branch to our start up logic.
 */

	.area	CODE1 (ABS)
	.org	PROGRAM_BASE
	ljmp	start

/* These are indirect interrupt vectors.  Logic in PAULMON2,
 * captures the interrupt vectors (near address 0x0000) and
 * re-routes them through the following entry points.
 *
 * Each of these saves acc and ie then passes the IRQ number
 * to higher level logic in a
 */

	.org	PM2_VECTOR_EXTINT0
	push	acc
	mov	a, #EXT_INT0_IRQ
	ljmp	_up_interrupt

	.org	PM2_VECTOR_TIMER0
	push	acc
	mov	a, #TIMER0_IRQ
	ljmp	_up_interrupt

	.org	PM2_VECTOR_EXTINT1
	push	acc
	mov	a, #EXT_INT1_IRQ
	ljmp	_up_interrupt

	.org	PM2_VECTOR_TIMER1
	push	acc
	mov	a, #TIMER1_IRQ
	ljmp	_up_interrupt

	.org	PM2_VECTOR_UART
	push	acc
	mov	a, #UART_IRQ
	ljmp	_up_interrupt

	.org	PM2_VECTOR_TIMER2
	push	acc
	mov	a, #TIMER2_IRQ
	ljmp	_up_interrupt

/************************************************************
 * Name: start
 *
 * Description:
 *   This is the initial entry point into NuttX
 *
 ************************************************************/

start:
	mov	sp, #(STACK_BASE-1)
patacongo's avatar
patacongo committed
	ljmp	_os_start

/************************************************************
 * Name: up_interrupt
 *
 * Description:
 *   All interrupts vector to this point with:
 *
 *   (1) acc on the stack and
patacongo's avatar
patacongo committed
 *   (2) the IRQ number in the accumulator
 *
 ************************************************************/

_up_interrupt:
	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 */
patacongo's avatar
patacongo committed

	push	ie
	clr	ea

patacongo's avatar
patacongo committed
	/* Save the remaining registers with interrupts disabled 
	 *
	 * a, ie, and dptr go on the stack.
	 */
patacongo's avatar
patacongo committed

	push	dpl
	push	dph
patacongo's avatar
patacongo committed
	/* Other registers go into the IRQ register save area */

patacongo's avatar
patacongo committed
	mov	dptr, #_g_irqregs
	lcall	_up_saveregisters

	/* Show interrupt status on the LEDs */

#ifdef CONFIG_8051_LEDS
	mov	dpl, #LED_INIRQ
	lcall	_up_ledon
#endif
patacongo's avatar
patacongo committed

	/* 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.
	 */
	/* Nullify the context pointer.  If a context switch is
	 * needed, this will be set to the address of the context
	 * structure.
	 */

patacongo's avatar
patacongo committed
	mov	dptr, #_g_irqcontext
	clr	a
	movx	@dptr,a
	inc	dptr
	movx	@dptr,a

patacongo's avatar
patacongo committed
	/* Now call void irq_dispatch(int irq, FAR void *context)
         *
	 * First, create the first argument as (int)irqno
	 */

        mov     dpl, r2
	mov	dph, #0
patacongo's avatar
patacongo committed

        /* Create the second argument (void *context) on the stack */

patacongo's avatar
patacongo committed

	/* Then dispatch the IRQ. */
patacongo's avatar
patacongo committed

	lcall	_irq_dispatch
	pop	acc
	pop	acc
patacongo's avatar
patacongo committed

	/* Indicate that we are no longer in an interrupt */
	clr	a
        movx    @dptr, a

	/* Check if a context switch is pending */

	mov	dptr,#_g_irqcontext
	mov     r2, a
	inc	dptr
	movx	a, @dptr
	mov	r3, a
patacongo's avatar
patacongo committed
	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 */
patacongo's avatar
patacongo committed

	mov	dpl, r2
	mov	dph, r3
	inc	dptr
	movx	@dptr, a

#ifdef CONFIG_INTERRUPT_FRAME_DUMP
	mov	dpl, r2
	mov	dph, r3
	push	ar2
	push	ar3
	lcall	_up_dumpframe
	pop	ar3
	pop	ar2
#endif

	/* Register usage in the following:
	 *
	 * R0   - Holds working the 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
	 */
patacongo's avatar
patacongo committed

	/* Fetch r4 = context->nbytes */
patacongo's avatar
patacongo committed

	mov	dpl, r2
	mov	dph, r3
	movx	a, @dptr
	mov	r4, a

	/* Save the new stack pointer in r5 */

	add	a, #(STACK_BASE-1)
	mov	r5, a

	/* Save r2-3 = &context->stack */

	inc	dptr
patacongo's avatar
patacongo committed
	push	dpl
	push	dph
	mov	r2, dpl
	mov	r3, dph

	/* Set r0 = stack base address */

	mov	r0, #STACK_BASE

	/* Top of the copy loop */
patacongo's avatar
patacongo committed
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 */

	mov	dpl, r2
	mov	dph, r3
	movx	a,@dptr

	/* Increment the XRAM pointer */

	inc	dptr
	mov	r2, dpl
	mov	r3, dph

	/* Save the next byte into IRAM */

	mov	@r0, a

	/* Increment the IRAM pointer */

	inc	r0
patacongo's avatar
patacongo committed
	sjmp	00002$
patacongo's avatar
patacongo committed
	/* The entire stack has been copied from XRAM into
	 * IRAM.  Set the new stack pointer
	 */
patacongo's avatar
patacongo committed
00003$:
	pop	dph
	pop	dpl
	mov	sp, r5

#ifdef CONFIG_INTERRUPT_FRAME_DUMP
patacongo's avatar
patacongo committed
	push	dpl
	push	dph
	lcall	_up_dumpstack
patacongo's avatar
patacongo committed
	pop	dpl
	pop	dph
patacongo's avatar
patacongo committed
	/* 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).
patacongo's avatar
patacongo committed
	push	dpl
	push	dph
patacongo's avatar
patacongo committed
	pop	dpl
	pop	dph
patacongo's avatar
patacongo committed
	/* Restore registers from the register save area */

	lcall	_up_restoreregisters

	/* Restore registers from the stack and return */

patacongo's avatar
patacongo committed
	pop	dph
	pop	dpl
patacongo's avatar
patacongo committed

	/* 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$:
patacongo's avatar
patacongo committed
	pop	acc
	reti