/*******************************************************************************
* NXP Semiconductors
* ALL RIGHTS RESERVED.
********************************************************************************
Services performed by NXP in this matter are performed AS IS and without 
any warranty. CUSTOMER retains the final decision relative to the total design 
and functionality of the end product. NXP neither guarantees nor will be 
held liable by CUSTOMER for the success of this project.
NXP DISCLAIMS ALL WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY INCLUDING, 
BUT NOT LIMITED TO, IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR 
A PARTICULAR PURPOSE ON ANY HARDWARE, SOFTWARE OR ADVISE SUPPLIED TO THE PROJECT
BY NXP, AND OR NAY PRODUCT RESULTING FROM NXP SERVICES. IN NO EVENT
SHALL NXP BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF
THIS AGREEMENT.

CUSTOMER agrees to hold NXP harmless against any and all claims demands or
actions by anyone on account of any damage, or injury, whether commercial, 
contractual, or tortuous, rising directly or indirectly as a result of an advise
or assistance supplied CUSTOMER in connection with product, services or goods 
supplied under this Agreement.
********************************************************************************
* File      main.c
* Owner     NXA19261
* Version   1.0
* Date      Aug-17-2017
* Classification   General Business Information
* Brief     Simply Serial Bootloader for S12Z (SSBZ)   
********************************************************************************
* Detailed Description:
* S12Z Serial Bootloader
* Please configure bootloader in Config.h and bootloader.prm files.
* 
********************************************************************************
Revision History:
Version  Date         Author    Description of Changes
1.0      Aug-17-2017  NXA19261  Initial version
*******************************************************************************/
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#include "Config.h"
#include "flash_S12Z.h"
#include "SCI.h"
#include "main.h"
#include "Bootloader.h"


//unsigned const char my_EEPROM[] @0x100000 = {0x11, 0x22, 0x33, 0x44};

//==============================================================================
// Definitions
//============================================================================== 
//Configure the bootloader Flash Configuration Field at 0xFFF000-0xFFFFFF:
#if USE_BACKDOOR_KEY
const unsigned char backdoor_array[] @0xFFFE00 = {BACKDOOR_KEY_0, BACKDOOR_KEY_1, BACKDOOR_KEY_2, BACKDOOR_KEY_3,
                                               BACKDOOR_KEY_4, BACKDOOR_KEY_5, BACKDOOR_KEY_6, BACKDOOR_KEY_7};
#endif
#if BOOTLODER_REWRITABLE
const unsigned char flash_array[] @0xFFFE08 = {PROTECTION_OVERRIDE_KEY_H, PROTECTION_OVERRIDE_KEY_L, 0xFF, 0xFF,
#else
const unsigned char flash_array[] @0xFFFE08 = {0xFF, 0xFF, 0xFF, 0xFF,		
#endif
                                               BL_FPROT, //P-Flash Protection byte
                                               BL_DFPROT, //EEPROM Protection byte
                                               BL_FOPT, //Flash Nonvolatile byte
#if (SECURE_MCU & USE_BACKDOOR_KEY)                                              
                                               0xBD};
#elif SECURE_MCU
                                               0xFD};
#else
                                               0xFE};
#endif
/*
0xFFFE08-0xFFFE09 - Protection Override Comparison Key = 0xABCD
0xFFFE0A-0xFFFE0B - Reserved
0xFFFE0C - P-Flash Protection byte = 0xCF (Bootloader at 0xFFF000-0xFFFFFF is protected)
0xFFFE0D - EEPROM Protection byte = 0xFF (default state, protection is disabled)
0xFFFE0E - Flash Nonvolatile byte = 0xFF (default state, watchdog is disabled)
0xFFFE0F - Flash Security byte = 0xFE (default unsecured state)
*/                                            
                                               
//==============================================================================
// Function Prototypes
//============================================================================== 
                                               
                                               
                                               
//==============================================================================
// Global variables
//==============================================================================



//==============================================================================
// Functions
//============================================================================== 
/*******************************************************************************
 Function Name : SetPEImodeBUSCLK
 Engineer      : NXA19261
 Date          : Aug-17-2017
 Parameters    : NONE
 Modifies      : NONE
 Returns       : NONE
 Notes         : Configure bus clock based on 1MHz IRCCLK input clock.
 Issues        : NONE
 *******************************************************************************/ 
void SetPEImodeBUSCLK(byte _synr, byte _refdiv, byte _postdiv)
{
  // Generally, whenever changing PLL reference clock (REFCLK) frequency to a higher value,
  // it's recommended to write CPMUSYNR = 0x00 in order to stay within specified  maximum frequency of the MCU
  CPMUSYNR = 0x00;
  CPMUREFDIV = _refdiv;
  CPMUSYNR = _synr;
  CPMUPOSTDIV = _postdiv;
  CPMUIFLG = 0xFF;  // clear all flags, especially LOCKIF and OSCIF
  // Wait for oscillator to start up (UPOSC=1) and PLL to lock (LOCK=1).
  while (!CPMUIFLG_LOCK)
  {
  // you can check for timeout here with error message report
  };
  CPMURFLG = 0x60;  // Clear PORF and LVRF
  //-------- select clocks ----------------
  while(CPMUCLKS != 0b10000000)            // After writing CPMUCLKS register, it is strongly recommended to read  
  {                                        // back CPMUCLKS register to make sure that write of PLLSEL,
                                           // RTIOSCSEL, COPOSCSEL0 and COPOSCSEL1 was successful.
        CPMUCLKS = 0b10000000;                   
                  /* ||||||||-------- COPOSCSEL0 - COP Clock Select 0
                     |||||||--------- RTIOSCSEL - RTI Clock Select
                     ||||||---------- PCE - COP Enable During Pseudo Stop Bit
                     |||||----------- PRE - RTI Enable During Pseudo Stop Bit
                     ||||------------ COPOSCSEL1 - COP Clock Select 1
                     |||------------- CSAD - COP in Stop Mode ACLK Disable
                     ||-------------- PSTP   - Pseudo Stop Bit
                     |--------------- PLLSEL - PLL Select Bit
                    */
  }
//    CPMUINT_LOCKIE = 1;  // Enable PLL Lock Interrupt (interrupt will be requested whenever LOCKIF is set)
}




/*******************************************************************************
 Function Name : Machine_Exception_ISR
 Engineer      : NXA19261
 Date          : Jan-08-2016
 Parameters    : NONE
 Modifies      : NONE
 Returns       : NONE
 Notes         : Machine Exception is not an interrupt. There is no stack-frame 
                 created for a Machine Exception so simply calling "RTI" (which 
                 expects a stack-frame) at the end of the Machine Exception routine 
                 will result in a crash.
                 The difference is explained in S12Z CPU RM:
                 http://www.nxp.com/files/microcontrollers/doc/ref_manual/S12ZCPU_RM_V1.pdf
                 See Chapter 7 - Exceptions.
                 Therefore, the correct recovery action should be (indicate error and) MCU reset.
 Issues        : Function is programmed here so it must be removed from
                 the part "A Set of unimplemented interrupts"
 *******************************************************************************/
interrupt VectorNumber_Vme void Machine_Exception_ISR(void)
{  
  CPMUCOP = 0x01;   //Initialize COP watchdog
  CPMUARMCOP = 0x00; //write any value except 0x55 or 0xAA cause MCU reset
}

/*******************************************************************************
 Function Name : InterruptModuleSetup
 Engineer      : NXA19261
 Date          : Aug-17-2017
 Parameters    : NONE
 Modifies      : NONE
 Returns       : NONE
 Notes         : Allocate interrupt vector table into RAM.
 Issues        : NONE
/******************************************************************************/
void InterruptModuleSetup(void)
{
  //set the S12Z interrupt vector base address in RAM
  IVBR = (IVBR_RAM_BASE >> 8);
  *(unsigned long *)(IVBR_RAM_BASE + SCI_VEC_ADR) = (unsigned long)SCIISR;
  *(unsigned long *)(IVBR_RAM_BASE + 0x1E8) = (unsigned long)Machine_Exception_ISR;
}


/*******************************************************************************
 Function Name : main
 Engineer      : NXA19261
 Date          : Aug-17-2017
 Parameters    : NONE
 Modifies      : NONE
 Returns       : NONE
 Notes         : Main loop.
 Issues        : NONE
 *******************************************************************************/ 

void main(void) {
  
  
  MODRR0 = BL_MODRR0;                       //Routing configuration - Write once in normal, anytime in special mode
  
  SetPEImodeBUSCLK(BL_SYNR, BL_REFDV, BL_POSDIV);       //Configure bus clock
  
  FCNFG = 0x0C;                             //WSTAT=0b11 - disable flash wait states
  while (!FPSTAT_WSTATACK){}                //wait until Wait-State switch is complete
  
  PFLASH_Init(BL_FCLKDIV);                  //internal oscillator 1MHz. For bus clk 25MHz -> divide by 0x18 
                                            //to achieve FCLK approximately 1MHz
  
  InitSCI();                                //Initialise SCI

#if BOOTLODER_REWRITABLE 
  InterruptModuleSetup();                   //Allocate interrupt vector table into RAM
#endif /* BOOTLODER_REWRITABLE */
  EnableInterrupts;
  DisplayMenu();		    
}

