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

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

 ******************************************************************************
  File Name     : Robust_L1P_ED.c
  Version       : Initial Draft
  Author        : Jane
  Created       : 2012/10/18
  Last Modified :
  Description   : L1P EDC example

 *  Known Issue:
 *  If L1P ED error test with CPU access, other tests such as L2 EDC and memory protection test work abnormal
 *  workaround 1: only test L1P ED and not enable other tests
 *  workaround 2: use DMA access to trigger L1P ED (sometimes it works, sometimes fails).
  
  Function List :
              funcTest5
              L1P_Cache_1bit_ERR
              L1P_ED_test
  History       :
  1.Date        : 2012/10/18
    Author      : Jane
    Modification: Created file

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

#include <stdio.h>
#include "KeyStone_common.h"

/*----------------------------------------------*
 * external variables                           *
 *----------------------------------------------*/

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

/*----------------------------------------------*
 * internal routine prototypes                  *
 *----------------------------------------------*/
extern void funcTest2(void); 

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

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

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

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


#pragma DATA_SECTION (temp_LL2_test_Data, "ll2EDCData")
#pragma DATA_ALIGN (temp_LL2_test_Data, 32)
Uint8 temp_LL2_test_Data[32];

/*****************************************************************************
 Prototype    : funcTest5
 Description  : Test Function
 Input        : void  
 Output       : None
 Return Value : 
 
  History        :
  1.Date         : 2012/10/30
    Author       : Zhan
    Modification : Created function

*****************************************************************************/
#pragma CODE_SECTION (funcTest5, "ll2EDCCode")
void funcTest5(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;
}

void L1P_Cache_1bit_ERR()
{
	int cacheAddr; 
  
	printf("!!!manually generate one bit error in L1P cache for function at 0x%x, and then execute it...\n",
		((Uint32)funcTest5)+32);

	/*calculate the address of the function in L1P cache*/
	cacheAddr = 0xe00000 + ((Uint32)(funcTest5)& 0x7fff);

	/*execute the function for test, touch it into L1P cache*/
	funcTest5();
	
	CACHE_freezeL1P();
	CSL_CGEM_suspendPMCErrorDetection(); 
	
	IDMA_copy(((Uint32)funcTest2), cacheAddr, 64, DMA_WAIT);

	CSL_CGEM_enablePMCErrorDetection(); 
	CACHE_unfreezeL1P();

	funcTest5();

	printf("\n!!!manually generate one bit error in L1P cache at 0x%x, and then read it by DMA...\n",
		((Uint32)cacheAddr)+32);

	funcTest5(); //execute again, make sure the code in cache

	CACHE_freezeL1P();
	CSL_CGEM_suspendPMCErrorDetection(); 
	
	IDMA_copy(((Uint32)funcTest2), cacheAddr, 64, DMA_WAIT);

	CSL_CGEM_enablePMCErrorDetection(); 
	CACHE_unfreezeL1P();

	IDMA_copy(cacheAddr, ((Uint32)temp_LL2_test_Data), 64, 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");
	asm(" nop 5");
	asm(" nop 5"); 	/*NRP should be around the address of this instruction*/
	asm(" nop 5"); 	
	IDMA_wait();

	CACHE_invL1p((void *)((Uint32)funcTest5), 64, CACHE_WAIT);
	//CSL_CGEM_clearPMCErrorDetectionStatus(1,1);

}
/*****************************************************************************
 Prototype    : L1P_ED_test
 Description  : L1P 1bit EDC test
 Input        : None
 Output       : None
 Return Value : 
 
  History        :
  1.Date         : 2012/10/18
    Author       : Jane
    Modification : Created function

*****************************************************************************/
void L1P_ED_test()
{
	puts("====================L1P ED test=================================");

	/* configure L1P as writable for test*/
	L1P_memory_protection_cfg(MP_AIDX|MP_AID5|MP_AID4|MP_AID3|MP_AID2|MP_AID1
		|MP_AID0|MP_UX|MP_UW|MP_UR|MP_SX|MP_SW|MP_SR);

	/* 4. Run application and simulate the 1bit error */
	L1P_Cache_1bit_ERR();

	/*restore the configuration, protect L1 as cache*/
   	L1_cache_protection();
}

