www.pudn.com > 2-STM.rar > sync_on_halt.c, change:2011-09-09,size:11857b


/************************************************************************** 
**                                                                        * 
**  FILE        :  sync_on_halt.c                                         * 
**                                                                        * 
**  DESCRIPTION :                                                         * 
**	Derivative-specific code that is run, every time the target       * 
**	halts, to synchronize the target and the debugger.                * 
**	                                                                  * 
**	This code is linked in by default. At the risk of debugging       * 
**	problems resulting from e.g. cache incoherence, it can be         * 
**	left out by right-clicking on the file in the C/C++ Projects      * 
**	view and selecting "Exclude from build...".                       * 
**	                                                                  * 
**	If a user-defined TriCore processor is being used, this file      * 
**	may have to be adapted.                                           * 
**                                                                        * 
**  Copyright 1996-2010 Altium BV                                         * 
**                                                                        * 
**************************************************************************/ 
 
#include <stddef.h> 
 
/* Code compaction, for example, must be avoided because this creates 
 * function calls and the CSA chain may not be initialized yet when 
 * this is run. 
 * 
 * Inlining must be avoided because it could make the label 
 * _sync_on_halt_end disappear. */ 
#pragma optimize acefgIklmNopRsuvwy 
 
/* Because this code is not part of the application program as such, 
 * it makes no sense to profile it. */ 
#pragma profiling off 
 
#pragma nomisrac 
 
/* This explicit inclusion is used because the file may be compiled 
 * with --no-tasking-sfr. */ 
#include __SFRFILE__(__CPU__) 
 
/* As above, but for the assembler. */ 
#define _SYNC_ON_HALT_STRINGIFY1(x) _SYNC_ON_HALT_STRINGIFY2(x) 
#define _SYNC_ON_HALT_STRINGIFY2(y) #y 
 
__asm(".include <sfr/reg" _SYNC_ON_HALT_STRINGIFY1(__CPU__) ".def>"); 
 
unsigned int __near __align(64) _sync_on_halt_lcx[16]; 
unsigned int __near __align(64) _sync_on_halt_ucx[16]; 
 
/* This function should never be called by the target application itself. */ 
extern void _sync_on_halt_end(void) 
{ 
	__nop(); 
	__debug(); 
} 
 
/* This function should never be called by the target application itself. 
 * __protect__ is needed to prevent this from being eliminated through 
 * duplicate section removal. */ 
extern void __protect__ _sync_on_halt(void) 
{ 
#if	   defined(_REGTC1762_H) || defined(_REGTC1764_H) || defined(_REGTC1766_H) || defined(_REGTC1766B_H)	\ 
	|| defined(_REGTC1792_H) || defined(_REGTC1796_H) || defined(_REGTC1796B_H)				\ 
	|| defined(_REGTC1161_H) || defined(_REGTC1162_H) || defined(_REGTC1163_H)				\ 
	|| defined(_REGTC1164_H) || defined(_REGTC1165_H) || defined(_REGTC1166_H)				\ 
 
/* Device has no data cache. */ 
 
#elif	   defined(_REGTC1100_H) || defined(_REGTC1115_H) || defined(_REGTC1130_H) 
#  define _EBU 8 
 
#  define _DCACHE_0_ADDRESS	0xc0000000U 
#  define _DCACHE_0_SIZE	64		/* In kBytes. */ 
 
#elif defined(_REGTC11IB_H) 
 
#  define _EBU 8 
 
#  define _DCACHE_0_ADDRESS	0x9fe00000U 
#  define _DCACHE_0_SIZE	1024 
 
#  define _DCACHE_1_ADDRESS	0xc0000000U 
#  define _DCACHE_1_SIZE	512 
 
#elif	   defined(_REGTC1167_H) || defined(_REGTC1197_H)				\ 
	|| defined(_REGTC1767_H) || defined(_REGTC1768_H) || defined(_REGTC1797_H)	\ 
	|| defined(_REGTC1782_H) || defined(_REGTC1783_H) || defined(_REGTC1746_H)	\ 
	|| defined(_REGTC1337_H) || defined(_REGTC1367_H) || defined(_REGTC1387_H) 
#  ifndef __TC131__ 
#    error Internal inconsistency. 
#  endif 
 
#  define _DCACHE_LINES		256 
#  define _DCACHE_WAYS		2 
#  define _DCACHE_LINE_INDEX	4 
 
#  define _DCACHE_OFFSET	0x80000000U 
 
 
#elif defined(_REGTC1736_H) 
 
/* Device has no data cache, but does have a Data Line Buffer (DLB). We need 
 * to execute CACHEI.WI at least once. */ 
 
#  ifndef __TC131__ 
#    error Internal inconsistency. 
#  endif 
 
#  define _DCACHE_LINES		1 
#  define _DCACHE_WAYS		1 
#  define _DCACHE_LINE_INDEX	4 
 
#  define _DCACHE_OFFSET	0x80000000U 
 
#elif defined(_REGTC1798_H) || defined(_REGTC1748_H) || defined(_REGTC1791_H) || defined(_REGTC1793_H) 
 
#  ifndef __TC16__ 
#    error Internal inconsistency. 
#  endif 
 
#  define _DCACHE_LINES		128 
#  define _DCACHE_WAYS		4 
#  define _DCACHE_LINE_INDEX	5 
 
#  define _DCACHE_OFFSET	0x80000000U 
 
#else 
#  error Unknown device. For user-defined devices, this code may have to be adapted. 
#endif 
 
 
 
 
 
#ifdef _DCACHE_LINES 
        unsigned char *         line_addr;	 
        unsigned int            line_index; 
        unsigned int            way_index; 
#endif 
 
#ifdef _EBU 
	EBU_ADDRSEL0_type *	ebu_addrselx; 
	ptrdiff_t		ebu_addrsel_delta; 
	int			region_index; 
	unsigned int		region_addr_u; 
#endif 
 
#if defined(_EBU) || defined(_DCACHE_0_ADDRESS) 
	unsigned char *		line_addr; 
	unsigned int		line_count; 
	unsigned int		line_index; 
#endif 
 
 
	/* Determine number of EBU regions. (Note that at the time of this writing at 
	 * least it was not actually possible for there to be 5 or 6, only 4 or 7.) */ 
#ifndef _EBU 
   /* (Nothing.) */ 
#elif defined(EBU_ADDRSEL7) || !defined(EBU_ADDRSEL3) 
#  error Unexpected number of EBU_ADDRSELx registers. 
#elif defined(EBU_ADDRSEL6) 
#  define _EBU_REGION_COUNT 7 
#elif defined(EBU_ADDRSEL5) 
#  define _EBU_REGION_COUNT 6 
#elif defined(EBU_ADDRSEL4) 
#  define _EBU_REGION_COUNT 5 
#else 
#  define _EBU_REGION_COUNT 4 
#endif 
 
	/* *************************************************************************************** 
	 * Save PSW and (most of) the address and data registers. (Not all of these will actually 
	 * be used,but that is up to the compiler and cannot be predicted reliably.) 
	 * 
	 * Note that PSW must be saved because of the switch to supervisor mode below, but also 
	 * because the remainder of the code may change the flags. 
	 * 
	 * The st*cx instructions do not affect the CSA list and do not require it to be properly 
	 * initialized (which it might not be at this point). */ 
	__asm("stlcx _sync_on_halt_lcx"); 
	__asm("stucx _sync_on_halt_ucx"); 
 
	/* Set PSW.IO to 2 (supervisor mode). This is needed for certain operations 
	 * performed below. */ 
	__mtcr(PSW, (int) (((unsigned int) __mfcr(PSW) & 0xfffff3ffU) | 0x800U)); 
 
	/* *************************************************************** 
	 * Initiate flushing of instruction cache. (Waiting for it to 
	 * complete is done later, i.e. in parallel with the data 
	 * cache flushing.) 
	 */ 
#if	   defined(_REGTC1100_H) || defined(_REGTC1115_H) || defined(_REGTC1130_H) || defined(_REGTC11IB_H)	\ 
	|| defined(_REGTC1762_H) || defined(_REGTC1764_H) || defined(_REGTC1766_H) || defined(_REGTC1766B_H)	\ 
	|| defined(_REGTC1161_H) || defined(_REGTC1162_H) || defined(_REGTC1163_H)				\ 
	|| defined(_REGTC1164_H) || defined(_REGTC1165_H) || defined(_REGTC1166_H)				\ 
	|| defined(_REGTC1792_H) || defined(_REGTC1796_H) || defined(_REGTC1796B_H) 
 
/* Instruction cache flushing not supported for these devices. */ 
 
#elif	   defined(_REGTC1167_H) || defined(_REGTC1197_H) || defined(_REGTC1736_H)	\ 
	|| defined(_REGTC1767_H) || defined(_REGTC1768_H) || defined(_REGTC1797_H)	\ 
	|| defined(_REGTC1782_H) || defined(_REGTC1783_H) || defined(_REGTC1746_H)	\ 
	|| defined(_REGTC1337_H) || defined(_REGTC1367_H) || defined(_REGTC1387_H) 
 
#  define _ICACHE_BIT0	PMI_CON1.B.PCINV 
#  define _ICACHE_BIT1	PMI_CON1.B.PBINV 
 
#elif defined(_REGTC1798_H) || defined(_REGTC1748_H) || defined(_REGTC1791_H) || defined(_REGTC1793_H) 
 
//#  define _ICACHE_BIT0	PCON1.B.PCINV 
//#  define _ICACHE_BIT1	PCON1.B.PBINV 
 
#  define _ICACHE_BIT0_W(bit_val) \ 
        __mtcr(PCON1, (int) (((unsigned int) __mfcr(PCON1) & 0xfffffffeU) | (bit_val ? 1 : 0))) 
#  define _ICACHE_BIT1_W(bit_val) \ 
        __mtcr(PCON1, (int) (((unsigned int) __mfcr(PCON1) & 0xfffffffdU) | (bit_val ? 2 : 0))) 
 
#  define _ICACHE_BIT0_R \ 
        (((unsigned int) __mfcr(PCON1) & 0x1U)!=0U) 
#  define _ICACHE_BIT1_R \ 
        (((unsigned int) __mfcr(PCON1) & 0x2U)!=0U) 
 
#else 
#  error Unknown device. 
#endif 
 
 
#ifdef _ICACHE_BIT0 
	_ICACHE_BIT0 = 1; 
	_ICACHE_BIT1 = 1; 
#endif 
 
#ifdef _ICACHE_BIT0_W 
        _ICACHE_BIT0_W(1); 
        _ICACHE_BIT1_W(1); 
#endif 
 
	/* ********************************************************** 
	 * Flush data cache. This will also flush the data line 
	 * buffer, if there is one. */ 
 
#ifdef _EBU 
	ebu_addrselx = &EBU_ADDRSEL0; 
 
	ebu_addrsel_delta = ((EBU_ADDRSEL0_type *) &EBU_ADDRSEL1) - &EBU_ADDRSEL0; 
 
	for (	region_index = 0; region_index < _EBU_REGION_COUNT; 
		region_index++, ebu_addrselx += ebu_addrsel_delta	) 
	{ 
		if (!ebu_addrselx->B.REGENAB) 
		{ 
			continue; 
		} 
 
		if (	   (((ebu_addrselx->B.BASE >> 16) & 0xfU) == _EBU) 
			|| (ebu_addrselx->B.ALTENAB && (ebu_addrselx->B.ALTSEG == _EBU)) 
		   ) 
		{ 
			/* EBU region is accessible via segment specified by _EBU. */ 
 
			/* Calculate start address of region. First, bits 28-31. */ 
			region_addr_u = ((unsigned int) _EBU << 28); 
 
			/* Add bits 12-27. */ 
			region_addr_u +=	((unsigned int) (ebu_addrselx->B.BASE & 0xffff) << 12) 
						& (0xffffffffU << (27 - ebu_addrselx->B.MASK)); 
 
			/* Size measured in 16-byte (128-bit) cache lines. 
			 * For example, when MASK equals 15, the size is 
			 * 4 KBytes, i.e. 256 lines. */ 
			line_count = 1 << (23 - ebu_addrselx->B.MASK); 
 
			line_addr = (unsigned char *) region_addr_u; 
 
			for (line_index = 0; line_index < line_count; line_index++) 
			{ 
                                __cacheawi(line_addr); 
 
                                line_addr += 16;				 
			} 
		} 
	} 
#endif /* #ifdef _EBU */ 
 
#ifdef _DCACHE_0_ADDRESS 
	line_count = (_DCACHE_0_SIZE * 1024) / 16; 
	line_addr = (unsigned char *) _DCACHE_0_ADDRESS; 
 
	for (line_index = 0; line_index < line_count; line_index++) 
	{ 
		__cacheawi(line_addr); 
 
		line_addr += 16; 
	} 
#endif 
 
#ifdef _DCACHE_1_ADDRESS 
	line_count = (_DCACHE_1_SIZE * 1024) / 16; 
	line_addr = (unsigned char *) _DCACHE_1_ADDRESS; 
 
	for (line_index = 0; line_index < line_count; line_index++) 
	{ 
		__cacheawi(line_addr); 
 
		line_addr += 16; 
	} 
#endif 
 
 
#ifdef _DCACHE_LINES 
        line_addr = (unsigned char *) _DCACHE_OFFSET;                ; 
	 
	for (line_index = 0; line_index < _DCACHE_LINES; line_index++) 
	{ 
		for (way_index = 0; way_index < _DCACHE_WAYS; way_index++) 
		{ 
			__cacheiwi( line_addr+way_index ); 
                } 
		 
		line_addr += (1 << _DCACHE_LINE_INDEX);			 
	} 
#endif 
 
	/* ********************************************************** 
	 * Wait for code cache flushing to complete. 
	 */ 
#ifdef _ICACHE_BIT0 
	while (_ICACHE_BIT0 || _ICACHE_BIT1); 
#endif 
 
#ifdef _ICACHE_BIT0_R 
        while (_ICACHE_BIT0_R || _ICACHE_BIT1_R); 
#endif 
 
	/* *************************************************************************************** 
	 * Restore registers. */ 
 
	/* If we switched to supervisor mode above, this restores the prior mode 
	 * as well. */ 
	__mtcr(PSW, _sync_on_halt_ucx[1]); 
	__asm("lducx _sync_on_halt_ucx"); 
	__asm("ldlcx _sync_on_halt_lcx"); 
 
	/* *************************************************************************************** 
	 * Flush pipeline. */ 
 
	__dsync();		/* Synchronize data. */ 
	__isync();		/* Synchronize instructions. */ 
	__nop();		/*  */ 
	__nop();		/* TC113_CPU9. */ 
 
	/* No function call should be used here, because the CSA may not have 
	 * been initialized yet. */ 
	__asm("j _sync_on_halt_end"); 
	return; 
}