/**HEADER********************************************************************
* 
* Copyright (c) 2012 Freescale Semiconductor;
* All Rights Reserved
*
*************************************************************************** 
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED 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 FREESCALE OR ITS 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.
*
**************************************************************************
*
* $FileName: boot.c$
* $Version : 3.6.2.0$
* $Date    : Mar-15-2012$
*
* Comments:
*
*    This file contains the boot and exception code.
*
*END************************************************************************/

#include "mqx_inc.h"
#include <fxlc95000.h>

extern unsigned long far    __BOOT_STACK_ADDRESS[];
extern unsigned long        __IPSBAR;
extern unsigned long        __INTERNAL_FLASH_BASE;
extern unsigned long        __INTERNAL_SRAM_BASE;

asm void __boot(void);
asm void __boot_exception(void);
asm void __goto_rom(void);

void _start(void);
void fxlc95000_init(void);

typedef void (*vector_entry)(void);

extern vector_entry __VECTOR_TABLE_ROM_START[]; /* defined in linker command file */
extern vector_entry __VECTOR_TABLE_RAM_START[]; /* defined in linker command file */

// User stack address is assigned in linker file.  In linker it is referred to 
// as __USP_INIT with two underscores. b39107
extern unsigned long far _USP_INIT;




#if   __REGABI__
    __declspec(register_abi)
#elif __STDABI__
      __declspec(standard_abi)
#endif
asm void __boot(void) 
{
    // Assume we could start here via the debugger or jump here at any time
    move.w #0x2700, sr                  // Disable all interrupts
   
    
    // Check for reason of reset.  If its due to illegal opcode or 
    // address, then reboot to rom.
    move.b  RCSR, d0
    and.l   #0x0c, d0
    beq     no_reboot
    
boot_to_rom:
    // Illegal opcode or address condition, reset.
    jmp     __goto_rom

 
no_reboot:
    // Init user stack pointer. b39107
    lea           _USP_INIT,a7
    move.l        a7,USP
            
    /* Setup the stack pointer */
    lea   __BOOT_STACK_ADDRESS,a7 
              
    
    
    /* Initialize int. vector table */
    move.l #__VECTOR_TABLE_ROM_START, d0
    movec d0, VBR

    /* Initialize Fxlc95000 peripherals */
    jsr    fxlc95000_init

    /* Jump to the main process */
    jmp _start
}

#if   __REGABI__
__declspec(register_abi)
#elif __STDABI__
__declspec(standard_abi)
#endif
asm void __boot_exception(void)
{
    halt
    rte
}


#if   __REGABI__
__declspec(register_abi)
#elif __STDABI__
__declspec(standard_abi)
#endif
asm void __goto_rom(void)
{
  // Reset to ROM interpreter. Clear boot from flash so that reboots to ROM
  move.w        FOPT, d0
  bclr          #13, d0
  move.w        d0, FOPT
  //  RCSR_ASR = 1; // Generate SW Reset
  mov3q         #5, d0
  bset          d0, RCSR

  nop
  nop
}
