/*******************************************************************************
* Freescale Semiconductor Inc.
* (c) Copyright 2010 Freescale Semiconductor, Inc.
* ALL RIGHTS RESERVED.
********************************************************************************
Services performed by FREESCALE 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. FREESCALE neither guarantees nor will be
held liable by CUSTOMER for the success of this project.
FREESCALE 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 ORE ADVISE SUPPLIED TO THE PROJECT
BY FREESCALE, AND OR NAY PRODUCT RESULTING FROM FREESCALE SERVICES. IN NO EVENT
SHALL FREESCALE BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF
THIS AGREEMENT.
CUSTOMER agrees to hold FREESCALE 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 the advise
or assistance supplied CUSTOMER in connection with product, services or goods
supplied under this Agreement.
********************************************************************************
* File:             main.c
* Owner:            b05111
* Version:          0.1
* Date:             Sep-19-2014
* Classification:   General Business Information
* Brief:            generate and handle ECC errors
********************************************************************************
* Detailed Description: 
*
* ECSM Error Generation Register EEGR is used to generate a non-correctable
* or single bit ECC error in RAM. The bad data is accessed then, so the IVOR1 
* exception is generated and handled. 
* This file shows also ECSM_combined_isr and how to correct the wrong data.
* Use macro Induce_ECC_error_by_DMA_read to select whether ECC error will be 
* injected by DMA read or CPU read.
* At the end of main file you can choose if single bit or multi bit is injected 
* and select particular ME/EE setup by comment/uncomment of particular function 
* calls.
* 
* ------------------------------------------------------------------------------
* Test HW:   XPC567XKIT516 - MPC5674ADAT516 Rev.C, MPC567XEVBFXMB Rev.B
* MCU:       PPC5674FMVYA264
* Terminal:  19200-8-no parity-1 stop bit-no flow control on eSCI_A
* Fsys:      264/200/150/60 MHz
*
********************************************************************************
Revision History:
0.1     Sep-19-2014     b05111  Initial Version
*******************************************************************************/

#include <stdio.h>
#include "MPC5674F_MVxA264.h"
#include "Exceptions.h"
#include "IntcInterrupts.h"
#include "clock.h"
#include "uart.h"

/*******************************************************************************
* Global variables
*******************************************************************************/

/*******************************************************************************
* Constants and macros
*******************************************************************************/

/* 1 = DMA read, 0 = CPU read */
#define Induce_ECC_error_by_DMA_read 0

/* ECSM macros */
#define ECSM_ECR_ER1BR_MASK    0x20 // RAM 1-Bit
#define ECSM_ECR_EF1BR_MASK    0x10 // FLASH 1-Bit
#define ECSM_ECR_ERNCR_MASK    0x02 // RAM Noncorrectable
#define ECSM_ECR_EFNCR_MASK    0x01 // FLASH Noncorrectable

#define ECSM_ESR_R1BC_MASK     0x20 // RAM 1-Bit
#define ECSM_ESR_F1BC_MASK     0x10 // FLASH 1-Bit
#define ECSM_ESR_RNCE_MASK     0x02 // RAM Noncorrectable
#define ECSM_ESR_FNCE_MASK     0x01 // FLASH Noncorrectable

#define ECSM_EEGR_FRC1BI_MASK  0x2000 // RAM Continuous 1-Bit
#define ECSM_EEGR_FR11BI_MASK  0x1000 // RAM One 1-bit
#define ECSM_EEGR_FRCNCI_MASK  0x0200 // RAM Continuous Noncorrectable
#define ECSM_EEGR_FR1NCI_MASK  0x0100 // RAM One Noncorrectable

/*******************************************************************************
* Local types
*******************************************************************************/

/*******************************************************************************
* Local function prototypes
*******************************************************************************/

static void HW_init(void);
static void DisableWatchdog(void);
static void FMPLL_init(void);
static void XBAR_init(void);
static void ECSM_init(void);
static void INTC_init(void);
static void eDMA_init(void);
static void ECSM_1bit_RAM_err_handler(void);
static void ECSM_2bit_RAM_err_handler(void);
void IVOR1_handler(void);
static asm void Increment_MCSRR0_to_next_instruction(void);
static asm void ClearMCSR(void);
static asm void ClearMSR_EE(void);
static asm void SetMSR_ME(void);
static void ECSM_combined_isr(void);
static void Fix_1bit_error_RAM_data(void);
static asm void Fix_2bit_error_RAM_data(void);
static void Generate_1bit_ECC_error(void);
static void Generate_noncorrectable_ECC_error(void);


/*******************************************************************************
* Local variables
*******************************************************************************/

static vuint8_t  ecsm_esr = 0;
static vuint32_t ecsm_rear = 0;
static vuint8_t  ecsm_remr = 0;
static vuint8_t  ecsm_reat = 0;
static vuint32_t ecsm_fear = 0;
static vuint8_t  ecsm_femr = 0;
static vuint8_t  ecsm_feat = 0;

/* align this to a 0-modulo-8 address (aligned to 8 bytes) */
static vuint32_t test[2] __attribute__ ((aligned (8))) = 
{
    0xBABADEDA,
    0xABBAABBA
};

static vuint32_t test_read = 0;


/* debugging variables */
vint32_t ECSM_2bit_RAM_err_handler_pass_count = 0;
vint32_t ECSM_1bit_RAM_err_handler_pass_count = 0;
vint32_t IVOR1_handler_pass_count = 0;

/*******************************************************************************
* Local functions
*******************************************************************************/

/*******************************************************************************
Function Name : HW_init
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      : 
Returns       : 
Notes         : 
Issues        : 
*******************************************************************************/
static void HW_init(void)
{
    DisableWatchdog();
    FMPLL_init();
    XBAR_init();
}


/*******************************************************************************
Function Name : DisableWatchdog
Engineer      : b08110
Date          : Mar-14-2011
Parameters    : 
Modifies      : 
Returns       : 
Notes         : disable SWT and e200 Core Watchdog Timer
Issues        : 
*******************************************************************************/
static void DisableWatchdog(void)
{    
    /*
    REM Disable Watchdog Timers
    REM MCM SWT New SWT in MPC56xx devices
    mm.l $fff38000 $ff00000A
    REM e200 Core Watchdog Timer (all MPC55xx and MPC56xx devices)
    spr 340t 0
    */
    SWT.MCR.R = 0xFF00000A;
    
    asm
    {
        mfhid0  r11		  	  /* Move from spr HID0 to r11 (copies HID0) */
        li      r12, 0xBFFF  /* Load immed. data of ~0x4000 to r12 */
        oris    r12, r12, 0xFFFF
        and     r11, r12, r11  /* OR r12 (~0x00004000) with r11 (HID0 value) */
        mthid0  r11          /* Move result to HID0 */

        lis     r12, 0x00
        mtspr   tcr, r12  /* clear SPR TCR register */
    }
}


/*******************************************************************************
Function Name : FMPLL_init
Engineer      : b05111
Date          : Apr-19-2012
Parameters    : 
Modifies      : 
Returns       : 
Notes         : Initializes PLL for 264/200/150/60MHz system clock                         
Issues        : - Assuming 40MHz crystal reference
                - clock.h must be included
*******************************************************************************/
static void FMPLL_init(void)
{
    #if defined(CORE_CLOCK_264MHz)
        FMPLL.ESYNCR2.R = 0x00000002;								
        FMPLL.ESYNCR1.R = 0x70040032;								
        while (FMPLL.SYNSR.B.LOCK != 1) {}; /* Wait for FMPLL to LOCK  */								
        FMPLL.ESYNCR2.R = 0x00000001;                  /* Fsys =264Mhz */								
        printf("fsys = 264MHz\n\r");
    
    #elif defined(CORE_CLOCK_200MHz)
        FMPLL.ESYNCR2.R = 0x00000002;								
        FMPLL.ESYNCR1.R = 0x70040022;								
        while (FMPLL.SYNSR.B.LOCK != 1) {}; /* Wait for FMPLL to LOCK  */								
        FMPLL.ESYNCR2.R = 0x00000001;                  /* Fsys =200Mhz */								
        printf("fsys = 200MHz\n\r");
    
    #elif defined(CORE_CLOCK_150MHz)
        FMPLL.ESYNCR2.R = 0x00000005;								
        FMPLL.ESYNCR1.R = 0x7003002C;								
        while (FMPLL.SYNSR.B.LOCK != 1) {}; /* Wait for FMPLL to LOCK  */								
        FMPLL.ESYNCR2.R = 0x00000003;                  /* Fsys =150Mhz */								
        printf("fsys = 150MHz\n\r");
    #else
        printf("FMPLL wasn't set properly - default 60MHz fsys used\n\r");
    #endif
}


/*******************************************************************************
Function Name : XBAR_init
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      : 
Returns       : 
Notes         :                        
Issues        : 
*******************************************************************************/
static void XBAR_init(void)
{

    #if Induce_ECC_error_by_DMA_read     
        // set higher priority for DMA than CPU
        XBAR.MPR0.R = 0x54300012; // internal FLASH
        XBAR.MPR2.R = 0x54300012; // internal SRAM
        XBAR.MPR7.R = 0x54300012; // PBRIDGE_B         
    #else  
        // round-robin for all slaves
        XBAR.SGPCR0.B.ARB = 1;
        XBAR.SGPCR1.B.ARB = 1;
        XBAR.SGPCR2.B.ARB = 1;
        XBAR.SGPCR6.B.ARB = 1;
        XBAR.SGPCR7.B.ARB = 1;
    #endif 
}


/*******************************************************************************
Function Name : ECSM_init
Engineer      : b05111
Date          : May-19-2011
Parameters    : 
Modifies      : 
Returns       : 
Notes         : initialization of the ECSM module
Issues        : 
*******************************************************************************/
static void ECSM_init(void)
{
    /* enable RAM ECC error reporting */
    ECSM.ECR.R = (uint8_t)ECSM_ECR_ERNCR_MASK | // non-correctable RAM ECC error
                          ECSM_ECR_ER1BR_MASK ; // 1-bit RAM ECC error
}


/*******************************************************************************
Function Name : INTC_init
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      : 
Returns       : 
Notes         :                        
Issues        : 
*******************************************************************************/
static void INTC_init(void)
{
    /* install ECSM combined handler to the vector table and init PRI */
    
    INTC_InstallINTCInterruptHandler(ECSM_2bit_RAM_err_handler,9,2);
    INTC_InstallINTCInterruptHandler(ECSM_1bit_RAM_err_handler,307,1);      
    
    /* MPC555x: Lower INTC's current priority */
    INTC.CPR.B.PRI = 0;

}


/*******************************************************************************
Function Name : eDMA_init
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      : 
Returns       : 
Notes         : 
Issues        : transfer control descriptors doesn't have any defaults
                     - every field must be initialized (15 items) !!!
*******************************************************************************/
#if Induce_ECC_error_by_DMA_read
static void eDMA_init(void)
{
    #define DMA_chnl 0
    
    // macros for SSIZE, DSIZE
    #define SIZE_1_byte  0
    #define SIZE_2_byte  1 
    #define SIZE_4_byte  2
    #define SIZE_8_byte  3
    #define SIZE_16_byte 4
    #define SIZE_32_byte 5
    
  
    /******** eDMA Control Reg: set round robin arbitration ********/
      
    //EDMA_A.CR.R = 0x0000000C; // ERGA=1,ERCA=1,EDBG=0
    //EDMA_A.CR.R = 0x0000000E; // ERGA=1,ERCA=1,EDBG=1
    EDMA_A.CR.R = 0x0001E41C; // ERGA=ERCA=HOE=ECX=1, rest default

    // eDMA Enable Error Interrupt Register Channels 63:32 
    EDMA_A.EEIRH.R = 0x00;  // disabled        
    // eDMA Enable Error Interrupt Register Channels 31:00 
    EDMA_A.EEIRL.R = 0x00;  // disabled   

    // eDMA Enable Request Register Channels 63:32 
    EDMA_A.ERQRH.R = 0x00;  // disabled  
    // eDMA Enable Request Register Channels 31:00 
    EDMA_A.ERQRL.R = 0x00;  // disabled   
  
  
    /******** source settings ********/
    
    // source address    
    EDMA_A.TCD[DMA_chnl].SADDR = (vuint32_t) &test;
    // 32-bit     
    EDMA_A.TCD[DMA_chnl].SSIZE = SIZE_4_byte;
    // no addr increment after transfer 
    EDMA_A.TCD[DMA_chnl].SOFF = 0;
    // after major loop, do not change addr    
    EDMA_A.TCD[DMA_chnl].SLAST = 0;
    // source modulo feature not used     
    EDMA_A.TCD[DMA_chnl].SMOD = 0;
    

    /******** destination settings ********/
    
    // destination address  
    EDMA_A.TCD[DMA_chnl].DADDR = (vuint32_t) &test_read;
    // 32-bit  
    EDMA_A.TCD[DMA_chnl].DSIZE = SIZE_4_byte;
    // no addr increment after transfer 
    EDMA_A.TCD[DMA_chnl].DOFF = 0;
    // after major loop, do not change addr   
    EDMA_A.TCD[DMA_chnl].DLAST_SGA = 0;    
    // destination modulo feature not used    
    EDMA_A.TCD[DMA_chnl].DMOD = 0;
    

    /******** counts ********/
    
    // 4 byte per minor loop     
    EDMA_A.TCD[DMA_chnl].NBYTES = 4;
    // major iteration count - stays at init value
    EDMA_A.TCD[DMA_chnl].BITER = 1;
    // major iteration count - updated after every minor loop
    EDMA_A.TCD[DMA_chnl].CITER = 1; 
    

    /******** linking ********/
   
    // disabled     
    EDMA_A.TCD[DMA_chnl].CITERE_LINK = 0;
    // disabled								  
    EDMA_A.TCD[DMA_chnl].BITERE_LINK = 0;
    // disabled
    EDMA_A.TCD[DMA_chnl].MAJORE_LINK = 0;
    // disabled
    EDMA_A.TCD[DMA_chnl].MAJORLINKCH = 0;
    

    /******** others ********/
    
    // do not disable channel when major loop is done    
    EDMA_A.TCD[DMA_chnl].D_REQ = 1;
    // interrupt is not used 
    EDMA_A.TCD[DMA_chnl].INT_HALF = 0;
    // interrupt is not used
    EDMA_A.TCD[DMA_chnl].INT_MAJ = 0;
    // disable scatter/gather operation    
    EDMA_A.TCD[DMA_chnl].E_SG = 0;
    // default bandwidth control- no stalls    
    EDMA_A.TCD[DMA_chnl].BWC = 0;
    // initialize status flags    
    EDMA_A.TCD[DMA_chnl].START = 0;
    EDMA_A.TCD[DMA_chnl].DONE = 0;
    EDMA_A.TCD[DMA_chnl].ACTIVE = 0;
    

    /********  enable the channel  ********/
    
    EDMA_A.SERQR.R = DMA_chnl;
    
}
#endif


/*******************************************************************************
Function Name : ECSM_1bit_RAM_err_handler
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      : 
Returns       : 
Notes         : Handles 1-bit ECC RAM error                            
Issues        : 
*******************************************************************************/
static void ECSM_1bit_RAM_err_handler(void)
{
    ECSM_combined_isr();
    Fix_1bit_error_RAM_data();
    ECSM_1bit_RAM_err_handler_pass_count++;
}


/*******************************************************************************
Function Name : ECSM_2bit_RAM_err_handler
Engineer      : b05111
Date          : May-19-2011
Parameters    : 
Modifies      : 
Returns       : 
Notes         : Handles 2-bit ECC RAM error                            
Issues        : 
*******************************************************************************/
static void ECSM_2bit_RAM_err_handler(void)
{
    ECSM_combined_isr();
    Fix_2bit_error_RAM_data();
    ECSM_2bit_RAM_err_handler_pass_count++;
}


/*******************************************************************************
Function Name : IVOR1_handler
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      : 
Returns       : 
Notes         : Function handles IVOR1 exception.        
Issues        : For z4 and z7:
                -  __declspec(interrupt machine)
                - mcsrr0 register increment
                For z0, z1, z3, z6:
                - __declspec(interrupt critical)
                - csrr0 register increment
*******************************************************************************/
#pragma push /* Save the current state */
#pragma force_active on
#pragma function_align 16 /* We use 16 bytes alignment for Exception handlers */
__declspec(interrupt machine)
void IVOR1_handler(void)
{

    ECSM_combined_isr();
    
    Fix_2bit_error_RAM_data();  
    
    Increment_MCSRR0_to_next_instruction();
    
    ClearMCSR();
    
    IVOR1_handler_pass_count++;

}
#pragma force_active off
#pragma pop


/*******************************************************************************
Function Name : Increment_MCSRR0_to_next_instruction
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      : 
Returns       : 
Notes         : - based on algorithm described in AN4648
                - applicable for IVOR1 (stores address to MCSRR0)                              
Issues        : 
*******************************************************************************/
#if VLE_IS_ON // for VLE code 
static asm void Increment_MCSRR0_to_next_instruction(void)
{
    /* prolog */
    fralloc
    
    /* MCSRR0->r5 */
    mfmcsrr0 r5
    
    /* determine opcode @ MCSRR0 */
    se_lhz r4,0(r5)
    
    /* check bit 31,28 only*/
    e_andi. r3,r4,0x9000
    e_cmpli 0x0,r3,0x1000 
    
    e_bne __machine_check_adjust_for_16bit_opcode
    
        /* 0xx1 => 32 bit*/
        se_addi r5,2
    
    __machine_check_adjust_for_16bit_opcode:
    
        /* all others just 16 bit long*/
        se_addi r5,2 
        
        /* save adjusted return address*/
        mtmcsrr0 r5 
    
    
    /* epilog */
    frfree
    blr   
}
#else //BookE
static asm void Increment_MCSRR0_to_next_instruction(void)
{
    /* prolog */
    fralloc
    
    /* MCSRR0->r5 */
    mfmcsrr0 r5
    
    /* for BookE, all instructions are 32 bit long */
    se_addi r5,4
        
    /* save adjusted return address*/
    mtmcsrr0 r5 
    
    /* epilog */
    frfree
    blr 
}
#endif


/*******************************************************************************
Function Name : ClearMCSR
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      : 
Returns       : 
Notes         : When MSR[ME] is set, error flags must be cleared to prevent 
                machine check exception to recall.                                 
Issues        : 
*******************************************************************************/
static asm void ClearMCSR(void)
{
    /* prolog */
    fralloc
    
    /* load mask */   
    lis r4, 0xFFFF
    addi r4, r4, 0xFFFF
    
    /* Clear MCSR */
    mtmcsr r4
    
    /* epilog */
    frfree
    blr   
}


/*******************************************************************************
Function Name : ClearMSR_EE
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      : 
Returns       : 
Notes         : Negates the MSR[EE].                                   
Issues        : 
*******************************************************************************/
static asm void ClearMSR_EE(void)
{
    /* prolog */
    fralloc
    
    /* read spr MSR */
    mfmsr r3  
    
    /* load mask to negate the EE bit */   
    lis r4, 0xFFFF
    addi r4, r4, 0x7FFF
    
    /* clear EE bit */
    and r3, r3, r4
    
    /* write back to MSR */
    mtmsr r3
    
    /* epilog */
    frfree
    blr   
}


/*******************************************************************************
Function Name : SetMSR_ME
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      : 
Returns       : 
Notes         : Asserts the MSR[ME].                                   
Issues        : 
*******************************************************************************/
static asm void SetMSR_ME(void)
{
    /* prolog */
    fralloc
    
    /* read spr MSR */
    mfmsr r3
    
    /* load mask to assert the ME bit */   
    lis r4, 0x0000
    addi r4, r4, 0x1000
    
    /* set ME bit */
    or r3, r3, r4
    
    /* write back to MSR */
    mtmsr r3
    
    /* epilog */
    frfree
    blr   
}


/*******************************************************************************
Function Name : ECSM_combined_isr
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      : ecsm_esr, ecsm_rear, ecsm_reat
Returns       : 
Notes         : ECSM combined interrupt requests:
                 • Internal SRAM non-correctable error (source ECSM_ESR[RNCE])
                 • Flash non-correctable error (source ECSM_ESR[FNCE])
                Based on recommended sequence (described in ECSM chapter of RM)
                to maintain the coherent software view of the reported event.                       
Issues        : Read of reset values of rear/remr/reat/fear/femr/feat may lead
                in lockstep error on safety devices (MPC5643L/5675K)
*******************************************************************************/
static void ECSM_combined_isr(void)
{
    for (;;)
    {
        /* 1. Read the ECSM_ESR and save it */
        ecsm_esr = (uint8_t)ECSM.ESR.R;
        
        /* 2. Read and save all the address and attribute reporting registers */
        
        /* Read only RAM registers if error is caused by RAM ECC error */
        if( (ecsm_esr & ECSM_ESR_R1BC_MASK) || (ecsm_esr & ECSM_ESR_RNCE_MASK) )
        {
            ecsm_rear = (uint32_t)ECSM.REAR.R;
            ecsm_remr = (uint8_t)ECSM.REMR.R;
            ecsm_reat = (uint8_t)ECSM.REAT.R;
        }
        
        /* Read only FLASH registers if error is caused by FLASH ECC error */
        if( (ecsm_esr & ECSM_ESR_F1BC_MASK) || (ecsm_esr & ECSM_ESR_FNCE_MASK) )
        {
        
            ecsm_fear = (uint32_t)ECSM.FEAR.R;
            ecsm_femr = (uint8_t)ECSM.FEMR.R;
            ecsm_feat = (uint8_t)ECSM.FEAT.R;
        }
       	 
        /* 3. Re-read the ECSM_ESR and verify the current contents matches 
              the original contents. If the two values are different, go back 
              to step 1 and repeat */
        if (ecsm_esr == (uint8_t)ECSM.ESR.R)
        {
            break;
        }
    }
        
    /* 4. When the values are identical, write a 1 to the asserted ECSM_ESR flag 
          to negate the interrupt request - we actually negate all flags */
    ECSM.ESR.R = 0x33;    
}


/*******************************************************************************
Function Name : Fix_1bit_error_RAM_data
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      : 
Returns       : 
Notes         : 
Issues        : 
*******************************************************************************/
static void Fix_1bit_error_RAM_data(void)
{
    static vuint32_t test_temporary[2];
    static vuint8_t  ecsm_ecr = 0;
    
    #define ECSM_ECR_ER1BR_MASK    0x20 // RAM 1-Bit
    #define ECSM_ECR_EF1BR_MASK    0x10 // FLASH 1-Bit
    
    /* temporary disable 1-bit reporting */
    ecsm_ecr = ECSM.ECR.R;
    ECSM.ECR.R &= ~(ECSM_ECR_ER1BR_MASK | ECSM_ECR_EF1BR_MASK);

    /* read and write back to physically correct 1-bit error */
    test_temporary[0] = test[0];
    test_temporary[1] = test[1];
    test[0] = test_temporary[0];        
    test[1] = test_temporary[1];
    
    /* re-enable 1-bit reporting as it was before */
    ECSM.ECR.R = ecsm_ecr;      
}


/*******************************************************************************
Function Name : Fix_2bit_error_RAM_data
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      : 
Returns       : 
Notes         : fixes the wrong data with a 64-bit write
                data pattern could possibly to be loaded from some backup
Issues        : stmw rS,D(rA) stores all GPR register above rS =>
                     => r30 and r31 must to be used        
*******************************************************************************/
static asm void Fix_2bit_error_RAM_data(void)
{
    /* prolog */
    fralloc
    
    /* load the address of the wrong data */
    lis     r3, test@h
    ori     r3, r3, test@l
    
    /* load data pattern to GPR4 and GPR5 */
    lis     r30, 0xfeed
    ori     r30, r30, 0xface
    lis     r31, 0xcafe
    ori     r31, r31, 0xbeef	
	
    stmw    r30,0(r3) 		/* write GPR30 and 31 to SRAM as one 64bit access */     
    
    /* epilog */
    frfree
    blr

}


/*******************************************************************************
Function Name : Generate_1bit_ECC_error
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      :  
Returns       : 
Notes         : generates 1-bit ECC error in RAM using the ECSM_EEGR register
Issues        : 
*******************************************************************************/
static void Generate_1bit_ECC_error(void)
{
    /* Force internal SRAM one 1-bit correctable data error */
    ECSM.EEGR.R = (uint16_t)(ECSM_EEGR_FR11BI_MASK | 1); /* RAM[1] is inverted */
    
    /* write to internal SRAM - this generates the wrong data */
    test[0] = 0xCAFEBEEF;    
    
    #if Induce_ECC_error_by_DMA_read
        EDMA_A.TCD[DMA_chnl].START = 1;
    #else
        test_read = test[0];
        
    #endif
}


/*******************************************************************************
Function Name : Generate_noncorrectable_ECC_error
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      :  
Returns       : 
Notes         : generates 2-bit ECC error in RAM using the ECSM_EEGR register
Issues        : 
*******************************************************************************/
static void Generate_noncorrectable_ECC_error(void)
{
    
    /* Force internal SRAM one non-correctable data error */
    ECSM.EEGR.R = (uint16_t)(ECSM_EEGR_FR1NCI_MASK | 1);
    
    /* write to internal SRAM - this generates the wrong data */
    test[0] = 0xCAFEBEEF;
    
    /* now here the ECC is checked and non-correctable error found */

    #if Induce_ECC_error_by_DMA_read
        EDMA_A.TCD[DMA_chnl].START = 1;
    #else
        /* error caused by read (it should set MCSR[MAV, LD, BUS_DRERR]) */
        test_read = test[0];  
        //test_read = test[1];
    #endif
    
    // Note: this can be achieved also by 32-bit, 16-bit and 8-bit write
    // as it behaves as read-modify-write operation above 64-bit field like this

    // test[0] = 0x5a5a5a5a; 
    // error caused by write (it should set MCSR[MAV, LD, BUS_DRERR, BUS_WRERR])

}


/*******************************************************************************
* Global functions
*******************************************************************************/

/*******************************************************************************
Function Name : main
Engineer      : b05111
Date          : Sep-19-2014
Parameters    : 
Modifies      :  
Returns       : 
Notes         : 
Issues        : 
*******************************************************************************/
int32_t main(void) 
{          
    HW_init();
    
    #if Induce_ECC_error_by_DMA_read     
        eDMA_init();
    #endif    
    
	INTC_init();   
    
    ECSM_init();   
    
    //SetMSR_ME();
    
    //ClearMSR_EE();
        
    //Generate_noncorrectable_ECC_error();
    
    Generate_1bit_ECC_error();
              

    /* Loop forever */
    for (;;) 
    {
    }
}



