/************************************************************************** * arch/z16/src/z16f/z16f_head.S * Z16F Reset Entry Point * * Copyright (C) 2008, 2012 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * 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 NuttX 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 **************************************************************************/ #include #include #include #include "common/up_internal.h" /************************************************************************** * Definitions **************************************************************************/ /************************************************************************** * External References / External Definitions **************************************************************************/ xref _z16f_clkinit:EROM xref _z16f_lowinit:EROM #ifdef CONFIG_ARCH_LEDS xref _board_led_initialize:EROM #endif #if defined(USE_LOWUARTINIT) xref _z16f_lowuartinit:EROM #elif defined(USE_EARLYSERIALINIT) xref _up_earlyserialinit:EROM #endif xref _os_start:EROM xref _up_doirq:EROM xref _z16f_sysexec:EROM xdef _z16f_reset xref _low_nearbss:RAM xref _len_nearbss xref _low_farbss:ERAM xref _len_farbss:ERAM xref _low_neardata:RAM xref _len_neardata xref _low_near_romdata:EROM xref _low_fardata:ERAM xref _len_fardata:ERAM xref _low_far_romdata:EROM xref far_heapbot:ERAM xref _far_stack:ERAM xref _near_stack:RAM /************************************************************************** * Flash Option Byte Setup **************************************************************************/ define FOPTIONSEG, SPACE=ROM, ORG=0 segment FOPTIONSEG db BOARD_FLOPTION0 db BOARD_FLOPTION1 db BOARD_FLOPTION2 db BOARD_FLOPTION3 /************************************************************************** * vectors **************************************************************************/ vector RESET=_z16f_reset vector SYSEXC=_sysexc_isr vector TIMER2=_timer2_isr vector TIMER1=_timer1_isr vector TIMER0=_timer0_isr vector UART0_RX=_uart0rx_isr vector UART0_TX=_uart0tx_isr vector I2C=_i2c_isr vector SPI=_spi_isr vector ADC=_adc_isr vector P7AD=_p7ad_isr vector P6AD=_p6ad_isr vector P5AD=_p5ad_isr vector P4AD=_p4ad_isr vector P3AD=_p3ad_isr vector P2AD=_p2ad_isr vector P1AD=_p1ad_isr vector P0AD=_p0ad_isr vector PWM_TIMER=_pwmtimer_isr vector UART1_RX=_uart1rx_isr vector UART1_TX=_uart1tx_isr vector PWM_FAULT=_pwmfault_isr vector C3=_c3_isr vector C2=_c3_isr vector C1=_c2_isr vector C0=_c0_isr /************************************************************************** * Equates **************************************************************************/ /************************************************************************** * Data Allocation **************************************************************************/ /************************************************************************** * Code **************************************************************************/ define CODESEG, SPACE=EROM segment CODESEG /************************************************************************** * Name: _z16f_reset * * Description: * Reset entry point * **************************************************************************/ _z16f_reset: /* Initialize the init/idle task stack */ ld sp, #(_near_stack+1) /* Set Stack Pointer to the top of internal RAM */ clr fp /* Initialize clocking */ call _z16f_clkinit /* Initialize onboard LEDs */ #ifdef CONFIG_ARCH_LEDS call _board_led_initialize #endif /* Perform VERY early UART initialization so that we can use it here */ #ifdef USE_LOWUARTINIT call _z16f_lowuartinit /* Initialize the UART for debugging */ #endif /* Initialize the hardware stack overflow register */ #ifdef CONFIG_Z16F_INITSPOV ld r0, #(_near_stack_bot+1) ld spov, r0 #endif /* Clear BSS */ lea r0, _low_nearbss ld r1, #_len_nearbss+1 jp _z16f_reset2 _z16f_reset1: ld.b (r0++), #0 _z16f_reset2: djnz r1, _z16f_reset1 lea r0, _low_farbss ld r1, #_len_farbss+1 jp _z16f_reset4 _z16f_reset3: ld.b (r0++), #0 _z16f_reset4: djnz r1, _z16f_reset3 /* Copy ROM data into RAM */ lea r0, _low_near_romdata lea r1, _low_neardata ld r2, #_len_neardata+1 jp _z16f_reset6 _z16f_reset5: ld.b r3, (r0++) ld.b (r1++), r3 _z16f_reset6: djnz r2, _z16f_reset5 lea r0, _low_far_romdata lea r1, _low_fardata ld r2, #_len_fardata+1 jp _z16f_reset8 _z16f_reset7: ld.b r3, (r0++) ld.b (r1++), r3 _z16f_reset8: djnz r2, _z16f_reset7 /* Perform low-level hardware initialization */ call _z16f_lowinit /* Perform low-level hardware initialization */ #ifdef USE_EARLYSERIALINIT /* Perform early serial initialization */ call _up_earlyserialinit #endif /* Start NuttX */ call _os_start /* Start the operating system */ _halt1: /* _os_start() should not return */ halt jp _halt1 /************************************************************************** * Name: _sysexec_isr * * Description: * System exception interrupt handler. On entry, the stack looks like * this: * * TOS[0] = PC[31:24] * TOS[1] = PC[23:16] * TOS[2] = PC[15:8] * TOS[3] = PC[7:0] * TOS[4] = 0 * TOS[5] = flags * **************************************************************************/ _sysexc_isr: pushmlo /* Save r0-r7 on the stack */ /* Calculate the value of the SP BEFORE the interrupt occurred and * push that as the saved value of r15=sp */ ld r1, #-6 /* return(4) + flags(1) + padding(1) */ add r1, sp /* r1 = Value of the SP before the interrupt */ push r1 /* Push r1 in the spot for the saved SP */ /* Save all of the remaining registers */ pushmhi /* SP now holds the address of the beginning of the save structure * on the stack. Now handle the system exception with arg1(r1)=address * of the register save structure. */ ld r1, sp call _z16f_sysexec /* Handle in C logic */ _halt2: /* _z16f_sysexec() should not return */ halt jp _halt2 /************************************************************************** * Name: Interrupt handlers * * Description: * All interrupts will be vectored to the following locations. * On entry, the stack contains the following: * * TOS[0] = PC[31:24] * TOS[1] = PC[23:16] * TOS[2] = PC[15:8] * TOS[3] = PC[7:0] * TOS[4] = 0 * TOS[5] = flags * **************************************************************************/ _timer2_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_TIMER2 /* r1 = Timer 2 IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _timer1_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_TIMER1 /* r1 = Timer 1 IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _timer0_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_TIMER0 /* r1 = Timer 0 IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _uart0rx_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_UART0RX /* r1 = UART0 RX IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _uart0tx_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_UART0TX /* r1 = UART0 TX IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _i2c_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_I2C /* r1 = I2C IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _spi_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_SPI /* r1 = SPI IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _adc_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_ADC /* r1 = ADC IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _p7ad_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_P7AD /* r1 = Port A/D7, rising/falling edge IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _p6ad_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_P6AD /* r1 = Port A/D6, rising/falling edge IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _p5ad_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_P5AD /* r1 = Port A/D5, rising/falling edge IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _p4ad_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_P4AD /* r1 = Port A/D4, rising/falling edge IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _p3ad_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_P3AD /* r1 = Port A/D3, rising/falling edgeEXEC IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _p2ad_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_P2AD /* r1 = Port A/D2, rising/falling edge IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _p1ad_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_P1AD /* r1 = Port A/D1, rising/falling edge IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _p0ad_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_P0AD /* r1 = Port A/D0, rising/falling edge IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _pwmtimer_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_PWMTIMER /* r1 = PWM Timer IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _uart1rx_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_UART1RX /* r1 = UART1 RX IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _uart1tx_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_UART1TX /* r1 = UART1 TX IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _pwmfault_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_PWMFAULT /* r1 = PWM Fault IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _c3_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_C3 /* r1 = Port C3, both edges DMA3 IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _c2_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_C2 /* r1 = Port C2, both edges DMA2 IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _c1_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_C1 /* r1 = Port C1, both edges DMA1 IRQ number */ jp _common_isr /* Join common interrupt handling logic */ _c0_isr: pushmlo /* Save r0-r7 on the stack */ ld r1, #Z16F_IRQ_C0 /* r1 = Port C0, both edges DMA0 IRQ number */ /* Join common interrupt handling logic */ /************************************************************************** * Name: _common_isr * * Description: * Common interrupt handling logic. * * On entry: * * r1 = IRQ number * * And the stack contains the following: * * TOS[ 0- 3] = r0 * TOS[ 4- 7] = r1 * TOS[ 8-11] = r2 * TOS[12-15] = r3 * TOS[16-19] = r4 * TOS[20-23] = r5 * TOS[24-27] = r6 * TOS[28-31] = r7 * TOS[32-35] = return PC * TOS[36-37] = flags (with padding) * **************************************************************************/ _common_isr: /* Calculate the value of the SP BEFORE the interrupt occurred and * push that as the saved value of r15=sp */ ld r2, #(9*4+2) /* See stack accounting above */ add r2, sp /* r1 = Value of the SP before the interrupt */ push r2 /* Push r1 in the spot for the saved SP */ /* Save all of the remaining registers */ pushmhi /* SP now holds the address of the beginning of the save structure * on the stack. Now handle the interrupt with arg1(r1)=IRQ number and * arg2(r2)=address of the register save structure. */ ld r2, sp call _up_doirq /* Upon return, _up_doirq will provide that address of the save structure * to use to return from the interrupt in r0. This may or may not be the * same value as sp. */ cp r0, sp /* Check if we are performing a context switch */ jp nz, _common_switch /* Jump if yes, else use faster return */ popmhi /* Restore r8-r14 */ add sp, #4 /* Skip over restore of r15=sp */ popmlo /* Restore r0-r7 */ iret /* We are not returning to the same thread that was interrupted. In this case, * r0 is not in the stack but, instead, refers to a storage structure in the TCB */ _common_switch: ld sp, 2*REG_SP(r0) /* sp=Value of SP on return from interrupt */ ld.w r1, 2*REG_FLAGS(r0) /* r1=padded flags value */ push.w r1 /* Push padded flags value onto the stack */ ld r1, 2*REG_PC(r0) /* r1=return address */ push r1 /* Push the return address onto the stack */ ld r7, 2*REG_R7(r0) /* Recover saved r7 */ push r7 /* And save on the stack so that we can use r7 */ ld r7, sp /* r7=saved sp */ ld sp, r0 /* sp=Pointer to register save structure */ popmhi /* Restore r8-r14 */ add sp, #4 /* Skip over restore of r15=sp */ popmlo /* Restore r0-r6 */ ld sp, r7 /* Switch back to the correct stack */ pop r7 /* Recover r7 from the stack */ iret /* Return from interrupt */ end