123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- /**************************************************************************
- ** *
- ** 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-2015 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 or runtime error check */
- #pragma profiling off
- #pragma runtime BCM
- #pragma nomisrac
- /* This explicit inclusion is used because the file may be compiled
- * without SFR inclusion */
- #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>");
- #if defined(_REGTC27X_H) || defined(_REGTC27XB_H) \
- || defined(_REGTC27XC_H) || defined(_REGTC27XD_H) \
- || defined(_REGTC26X_H) || defined(_REGTC26XB_H) \
- || defined(_REGTC29X_H) || defined(_REGTC29XB_H) \
- || defined(_REGTC21X_H) || defined(_REGTC22X_H) \
- || defined(_REGTC23X_H) || defined(_REGTC23X_ADAS_H) \
- || defined(_REGUSERDEF162_H)
- #if !defined(__CORE_TC0__) && !defined(__CORE_TC1__) && !defined(__CORE_TC2__)
- #define __CLONE __clone
- #else
- #define __CLONE
- #endif
- #define __DSPR_SYNC_ON_HALT_LCX __at(0xd0003f80)
- #define __DSPR_SYNC_ON_HALT_UCX __at(0xd0003fc0)
- #else
- #define __CLONE
- #define __DSPR_SYNC_ON_HALT_LCX
- #define __DSPR_SYNC_ON_HALT_UCX
- #endif
- unsigned int __near __CLONE __align(64) _sync_on_halt_lcx[16] __DSPR_SYNC_ON_HALT_LCX;
- unsigned int __near __CLONE __align(64) _sync_on_halt_ucx[16] __DSPR_SYNC_ON_HALT_UCX;
- /* 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
- * unreferenced 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(_REGTC1164_H) || defined(_REGTC1166_H) \
- /* Device has no data cache. */
- #elif defined(_REGTC1130_H)
- # define _EBU 8
- # define _DCACHE_0_ADDRESS 0xc0000000U
- # define _DCACHE_0_SIZE 64 /* In kBytes. */
- #elif defined(_REGTC1167_H) || defined(_REGTC1197_H) \
- || defined(_REGTC1724_H) || defined(_REGTC1728_H) \
- || defined(_REGTC1184_H) || defined(_REGTC1784_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)
- # if !defined(__CORE_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) || defined(_REGTC21X_H) || defined(_REGTC22X_H) || defined(_REGTC23X_H) || defined(_REGTC23X_ADAS_H)
- /* Device has no data cache, but does have a Data Line or Read Buffer (DLB or DRB). We need
- * to execute CACHEI.WI at least once. */
- # if !defined(__CORE_TC131__) && !defined(__CORE_TC16X__) && !defined(__CORE_TC162__)
- # error Internal inconsistency.
- # endif
- # define _DCACHE_LINES 1
- # define _DCACHE_WAYS 1
- # ifdef _REGTC1736_H
- # define _DCACHE_LINE_INDEX 4
- # else
- # define _DCACHE_LINE_INDEX 5
- # endif
- # define _DCACHE_OFFSET 0x80000000U
- #elif defined(_REGTC1798_H) || defined(_REGTC1748_H) || defined(_REGTC1791_H) || defined(_REGTC1793_H)
- # ifndef __CORE_TC16__
- # error Internal inconsistency.
- # endif
- # define _DCACHE_LINES 128
- # define _DCACHE_WAYS 4
- # define _DCACHE_LINE_INDEX 5
- # define _DCACHE_OFFSET 0x80000000U
- #elif defined(_REGTC27X_H) || defined(_REGTC27XB_H) || defined(_REGTC27XC_H) || defined(_REGTC27XD_H)
- # if !defined(__CORE_TC16X__) && !defined(__CORE_TC162__)
- # error Internal inconsistency.
- # endif
- /* Cache way number occupies bits 0 and 1, index number occupies bits 5...10. */
- # define _DCACHE_LINES 64
- # define _DCACHE_WAYS 4
- # define _DCACHE_LINE_INDEX 5
- # define _DCACHE_OFFSET 0x80000000U
- #elif defined(_REGTC26X_H) || defined(_REGTC26XB_H) || defined(_REGTC29X_H) \
- || defined(_REGTC29XB_H) || defined(_REGUSERDEF162_H)
- # if !defined(__CORE_TC16X__) && !defined(__CORE_TC162__)
- # error Internal inconsistency.
- # endif
- /* Cache way number occupies bit 0, index number occupies bits 5...11. */
- # define _DCACHE_LINES 128
- # define _DCACHE_WAYS 2
- # 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(_REGTC1130_H) \
- || defined(_REGTC1762_H) || defined(_REGTC1764_H) \
- || defined(_REGTC1766_H) || defined(_REGTC1766B_H) \
- || defined(_REGTC1164_H) || defined(_REGTC1166_H) \
- || defined(_REGTC1792_H) || defined(_REGTC1796_H) || defined(_REGTC1796B_H) \
- || defined(_REGUSERDEF162_H)
- /* Instruction cache flushing not supported for these devices. */
- #elif defined(_REGTC1167_H) || defined(_REGTC1197_H) \
- || defined(_REGTC1724_H) || defined(_REGTC1728_H) || defined(_REGTC1736_H) \
- || defined(_REGTC1184_H) || defined(_REGTC1784_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) \
- || defined(_REGTC21X_H) || defined(_REGTC22X_H) || defined(_REGTC23X_H) || defined(_REGTC23X_ADAS_H) \
- || defined(_REGTC27X_H) || defined(_REGTC27XB_H) || defined(_REGTC27XC_H) || defined(_REGTC27XD_H) \
- || defined(_REGTC26X_H) || defined(_REGTC26XB_H) || defined(_REGTC29X_H) || defined(_REGTC29XB_H)
- # 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
- /* In the case of a TC1.6E core, there is only a Data Read Buffer (DRB),
- * not a real cache, and as a result a single __cacheiwi(...) would
- * actually suffice. However, the loop also works. */
- 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;
- }
|