/******************************************************************************

  Copyright (C), 2001-2012, Texas Instrument.

 ******************************************************************************
  File Name     : Robust_LL2_EDC.c
  Version       : Initial Draft
  Author        : Zhan
  Created       : 2012/3/13
  Last Modified :
  Description   : LL2 EDC test
  Function List :
              funcTest1
              funcTest2
              funcTest3
              funcTest4
              LL2_EDC_scrubbing_timer_setup
              LL2_EDC_test
              LL2_RAM_code_bit_ERR_test
              LL2_RAM_data_bit_ERR_test_byDmaAcess
              LL2_RAM_data_bit_ERR_test_byL1dAcess
  History       :
  1.Date        : 2012/3/13
    Author      : Zhan
    Modification: Created file

  2.Date         : 2012/10/18
    Author       : Jane
    Modification : Modify based on KeyStone device

  3.Date         : 2012/10/29
    Author       : Brighton Feng
    Modification : Update
******************************************************************************/

#include <stdio.h>
#include "KeyStone_common.h"
/*----------------------------------------------*
 * external variables                           *
 *----------------------------------------------*/

/*----------------------------------------------*
 * external routine prototypes                  *
 *----------------------------------------------*/

/*----------------------------------------------*
 * internal routine prototypes                  *
 *----------------------------------------------*/

/*----------------------------------------------*
 * project-wide global variables                *
 *----------------------------------------------*/

/*----------------------------------------------*
 * module-wide global variables                 *
 *----------------------------------------------*/

#pragma DATA_SECTION (LL2_EDC_test_Data, "ll2EDCData")
#pragma DATA_ALIGN (LL2_EDC_test_Data, 64)
volatile Uint8 LL2_EDC_test_Data[64]={
	0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0, 0, 0, 0, 0, 0, 0, 0,
	0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0, 0, 0, 0, 0, 0, 0, 0,
	0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0, 0, 0, 0, 0, 0, 0, 0,
	0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0, 0, 0, 0, 0, 0, 0, 0
};
#pragma DATA_SECTION (LL2_EDC_test_Data2, "ll2EDCData")
#pragma DATA_ALIGN (LL2_EDC_test_Data2, 64)
Uint8 LL2_EDC_test_Data2[64]={0,7,5,7,7,7,7,7};

/*----------------------------------------------*
 * constants                                    *
 *----------------------------------------------*/

/*----------------------------------------------*
 * macros                                       *
 *----------------------------------------------*/

/*----------------------------------------------*
 * routines' implementations                    *
 *----------------------------------------------*/



/*****************************************************************************
 Prototype    : LL2_EDC_scrubbing_timer_setup
 Description  : setup timer with period in second for LL2 EDC scrubbing
 Input        : unsigned int scrubbing_period_s  
 Output       : None
 Return Value : 
 
  History        :
  1.Date         : 2012/10/20
    Author       : Brighton Feng
    Modification : Created function

*****************************************************************************/
void LL2_EDC_scrubbing_timer_setup(unsigned int scrubbing_period_s)
{
	TDSP_Board_Type DSP_Board_Type= KeyStone_Get_dsp_board_type();
	Timer64_Config tmrCfg;

	if(C6678_EVM == DSP_Board_Type)
		tmrCfg.timer_num= 8;
	else if(C6657_EVM == DSP_Board_Type)
		tmrCfg.timer_num= 2;
	else
		tmrCfg.timer_num= 4;

	tmrCfg.timerMode= TIMER_PERIODIC_PULSE;

	/*timer period is in the unit of DSP core clock/6*/	
	tmrCfg.period= (unsigned long long)gDSP_Core_Speed_Hz*scrubbing_period_s/6; 	
	tmrCfg.pulseWidth= 3;
	Timer64_Init(&tmrCfg);
}

/*****************************************************************************
 Prototype    : funcTest1
 Description  : Test function 1
 Input        : void  
 Output       : None
 Return Value : 
 
  History        :
  1.Date         : 2012/3/13
    Author       : Zhan
    Modification : Created function

*****************************************************************************/
#pragma CODE_SECTION (funcTest1, "ll2EDCCode")
void funcTest1(void)
{
	//first fetch packet
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop   2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop   2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	//second fetch packet
	asm(" nop   1");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop   2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	return;
}

/*****************************************************************************
 Prototype    : funcTest2
 Description  : Test function 2
 Input        : void  
 Output       : None
 Return Value : 
 
  History        :
  1.Date         : 2012/3/13
    Author       : Zhan
    Modification : Created function

*****************************************************************************/
#pragma CODE_SECTION (funcTest2, "ll2EDCCode")
void funcTest2(void)
{
	//first fetch packet
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop   2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop   2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	//second fetch packet
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop   2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	return;
}

/*****************************************************************************
 Prototype    : funcTest3
 Description  : Test function 3
 Input        : void  
 Output       : None
 Return Value : 
 
  History        :
  1.Date         : 2012/3/13
    Author       : Zhan
    Modification : Created function

*****************************************************************************/
#pragma CODE_SECTION (funcTest3, "ll2EDCCode")
void funcTest3(void)
{
	//first fetch packet
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop   2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop   2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	//second fetch packet
	asm(" nop   4");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop   2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	return;
}

/*****************************************************************************
 Prototype    : funcTest4
 Description  : Test function 4
 Input        : void  
 Output       : None
 Return Value : 
 
  History        :
  1.Date         : 2012/3/13
    Author       : Zhan
    Modification : Created function

*****************************************************************************/
#pragma CODE_SECTION (funcTest4, "ll2EDCCode")
void funcTest4(void)
{
	//first fetch packet
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop   2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop   2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	//second fetch packet
	asm(" nop   1");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop   2");
	asm(" nop	7");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	asm(" nop	2");
	return;
}
/*****************************************************************************
 Prototype    : LL2_RAM_code_bit_ERR_test
 Description  : LL2 RAM EDC test mannually access
 Input        : None
 Output       : None
 Return Value : 
 
  History        :
  1.Date         : 2012/10/29
    Author       : Brighton Feng
    Modification : Created function

*****************************************************************************/
void LL2_RAM_code_bit_ERR_test()
{
#if 0 	/*uncorrectable code bit error test may crush the program*/
	printf("!!!manually generate 3 bit error in a function at 0x%x, and then execute the function...\n",
		((Uint32)funcTest1)+32);
	CSL_CGEM_suspendL2EDC();
	IDMA_copy(((Uint32)funcTest4), ((Uint32)funcTest1), 64, DMA_WAIT);
	CSL_CGEM_enableL2EDC();

	CACHE_invL1p((void *)((Uint32)funcTest1), 64, CACHE_WAIT);
	funcTest1();

	/*normally, exception is captured about 10~100 cycles after the 
	access violation. Dummy operations added here to wait for it.*/
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5"); 	/*NRP should be around the address of this instruction*/
	asm(" nop 5"); 	

	printf("\n!!!manually generate 2 bit error in a function at 0x%x, and then execute the function...\n",
		((Uint32)funcTest1)+32);
	CSL_CGEM_suspendL2EDC();
	IDMA_copy(((Uint32)funcTest3), ((Uint32)funcTest1), 64, DMA_WAIT);
	CSL_CGEM_enableL2EDC();

	/*normally, exception is captured about 10~100 cycles after the 
	access violation. Dummy operations added here to wait for it.*/
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5"); 	/*NRP should be around the address of this instruction*/
	asm(" nop 5"); 	

	CACHE_invL1p((void *)((Uint32)funcTest1), 64, CACHE_WAIT);
	funcTest1();
#endif
	printf("\n!!!manually generate one bit error in a function at 0x%x, and then execute the function...\n",
		((Uint32)funcTest1)+32);
	CSL_CGEM_suspendL2EDC();
	IDMA_copy(((Uint32)funcTest2), ((Uint32)funcTest1), 64, DMA_WAIT);
	CSL_CGEM_enableL2EDC();

	CACHE_invL1p((void *)((Uint32)funcTest1), 64, CACHE_WAIT);
	funcTest1();

	puts("\none bit error was corrected with previous execution. Execute the function again...(no error happens again)");
	CACHE_invL1p((void *)((Uint32)funcTest1), 64, CACHE_WAIT);
	funcTest1();
	
}

/*****************************************************************************
 Prototype    : LL2_RAM_data_bit_ERR_test_byL1dAcess
 Description  : LL2 RAM EDC test by L1d Access
 Input        : None
 Output       : None
 Return Value : 
 
  History        :
  1.Date         : 2012/10/29
    Author       : Brighton Feng
    Modification : Created function

*****************************************************************************/
void LL2_RAM_data_bit_ERR_test_byL1dAcess()
{
	volatile Uint8 readback;
	volatile Uint32 index= 40;
#if 1	
	printf("!!!manually generate 3 bit error in data at 0x%x, and then read it...\n",
		(Uint32)&LL2_EDC_test_Data[index]);
	CACHE_invL1d((void *)&LL2_EDC_test_Data[index], 64, CACHE_WAIT);
    CACHE_freezeL1D();
	CSL_CGEM_suspendL2EDC();
	LL2_EDC_test_Data[index] = 0x7;
	CSL_CGEM_enableL2EDC();
    CACHE_unfreezeL1D();
	readback= LL2_EDC_test_Data[index];

	/*normally, exception is captured about 10~100 cycles after the 
	access violation. Dummy operations added here to wait for it.*/
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5"); 	/*NRP should be around the address of this instruction*/
	asm(" nop 5"); 	

	printf("\n!!!manually generate 2 bit error in data at 0x%x, and then read it...\n",
		(Uint32)&LL2_EDC_test_Data[index]);
	CACHE_invL1d((void *)&LL2_EDC_test_Data[index], 64, CACHE_WAIT);
    CACHE_freezeL1D();
	CSL_CGEM_suspendL2EDC();
	LL2_EDC_test_Data[index] = 0x3;
	CSL_CGEM_enableL2EDC();
    CACHE_unfreezeL1D();
	readback= LL2_EDC_test_Data[index];

	/*normally, exception is captured about 10~100 cycles after the 
	access violation. Dummy operations added here to wait for it.*/
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5"); 	/*NRP should be around the address of this instruction*/
	asm(" nop 5"); 	
#endif
	printf("\n!!!manually generate one bit error in data at 0x%x, and then read it...\n",
		(Uint32)&LL2_EDC_test_Data[index]);
	CACHE_invL1d((void *)&LL2_EDC_test_Data[index], 64, CACHE_WAIT);
    CACHE_freezeL1D();
	CSL_CGEM_suspendL2EDC();
	LL2_EDC_test_Data[index] = 0x1;
	CSL_CGEM_enableL2EDC();
    CACHE_unfreezeL1D();
	readback= LL2_EDC_test_Data[index];

	/*normally, exception is captured about 10~100 cycles after the 
	access violation. Dummy operations added here to wait for it.*/
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5"); 	/*NRP should be around the address of this instruction*/
	asm(" nop 5"); 	

	puts("\n!!!scrub the corrupted data to fix the error...");
	CACHE_invL1d((void *)((Uint32)&LL2_EDC_test_Data[index]), 64, CACHE_WAIT);
	/*scrub the corrupted code to fix the error*/
	IDMA_copy(((Uint32)&LL2_EDC_test_Data[index])&0xFFFFFFE0, 
		((Uint32)&LL2_EDC_test_Data[index])&0xFFFFFFE0, 
		32, DMA_NO_WAIT);

	/*normally, exception is captured about 10~100 cycles after the 
	access violation. Dummy operations added here to wait for it.*/
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5"); 	/*NRP should be around the address of this instruction*/
	asm(" nop 5"); 	
	IDMA_wait();

	puts("read the data again...(no error happens again)");
	readback= LL2_EDC_test_Data[index];
	
}

/*****************************************************************************
 Prototype    : LL2_RAM_data_bit_ERR_test_byDmaAcess
 Description  : LL2 RAM EDC test by DMA access
 Input        : None
 Output       : None
 Return Value : 
 
  History        :
  1.Date         : 2012/10/28
    Author       : Brighton Feng
    Modification : Created function

*****************************************************************************/
void LL2_RAM_data_bit_ERR_test_byDmaAcess()
{
	volatile Uint8 readback;

#if 1
	printf("!!!manually generate 3 bit error in data at 0x%x, and then read it...\n",
		(Uint32)LL2_EDC_test_Data);
	CACHE_invL1d((void *)LL2_EDC_test_Data, 64, CACHE_WAIT);
	CSL_CGEM_suspendL2EDC();
	LL2_EDC_test_Data[12]= 0xcc;
	CSL_CGEM_enableL2EDC();
	//readback= LL2_EDC_test_Data[0];
	IDMA_copy(((Uint32)LL2_EDC_test_Data), ((Uint32)LL2_EDC_test_Data2), 
		32, DMA_WAIT);

 	/*normally, exception is captured about 10~100 cycles after the
	access violation. Dummy operations added here to wait for it.*/
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5"); 	/*NRP should be around the address of this instruction*/
	asm(" nop 5");

	printf("!!!manually generate 2 bit error in data at 0x%x, and then read it...\n",
		(Uint32)LL2_EDC_test_Data);
	CACHE_invL1d((void *)LL2_EDC_test_Data, 64, CACHE_WAIT);
	CSL_CGEM_suspendL2EDC();
	LL2_EDC_test_Data[12]= 0x8c;
	CSL_CGEM_enableL2EDC();
	//readback= LL2_EDC_test_Data[0];
	IDMA_copy(((Uint32)LL2_EDC_test_Data), ((Uint32)LL2_EDC_test_Data2), 
		32, DMA_WAIT);

	/*normally, exception is captured about 10~100 cycles after the
	access violation. Dummy operations added here to wait for it.*/
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5"); 	/*NRP should be around the address of this instruction*/
	asm(" nop 5");
#endif
	printf("!!!manually generate one bit error in data at 0x%x, and then read it...\n",
		(Uint32)LL2_EDC_test_Data);
	CACHE_invL1d((void *)LL2_EDC_test_Data, 64, CACHE_WAIT);
	CSL_CGEM_suspendL2EDC();
	LL2_EDC_test_Data[12]= 0x6c;
	CSL_CGEM_enableL2EDC();
	//readback= LL2_EDC_test_Data[0];
	IDMA_copy(((Uint32)LL2_EDC_test_Data), ((Uint32)LL2_EDC_test_Data2), 
		32, DMA_WAIT);

	/*normally, exception is captured about 10~100 cycles after the
	access violation. Dummy operations added here to wait for it.*/
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5");
	asm(" nop 5"); 	/*NRP should be around the address of this instruction*/
	asm(" nop 5");

	puts("!!!scrub the corrupted data to fix the error...");
	CACHE_invL1d((void *)((Uint32)LL2_EDC_test_Data), 64, CACHE_WAIT);
	/*scrub the corrupted code to fix the error*/
	IDMA_copy(((Uint32)LL2_EDC_test_Data), ((Uint32)LL2_EDC_test_Data), 
		32, DMA_WAIT);

	puts("read the data again...(no error happens again)");
	readback= LL2_EDC_test_Data[12];

}
/*****************************************************************************
 Prototype    : LL2_EDC_test
 Description  : LL2 EDC test 
 Input        : None
 Output       : None
 Return Value : 
 
  History        :
  1.Date         : 2012/10/29
    Author       : Brighton Feng
    Modification : Created function

*****************************************************************************/
void LL2_EDC_test()
{
	puts("===================-LL2 EDC test-================================");
	puts("--------------------LL2 data EDC test----------------------------");
	LL2_RAM_data_bit_ERR_test_byL1dAcess();
	//LL2_RAM_data_bit_ERR_test_byDmaAcess();
	puts("--------------------LL2 code EDC test----------------------------");
	LL2_RAM_code_bit_ERR_test();
}



