From 29430a3a106c98d2027b29d074d5db85ddb49c39 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Thu, 22 Sep 2016 09:50:59 +0200 Subject: arm/tms570: include hardware initialization and selftest based on Ti HalCoGen generated files. The configuration is specific for TMS570LS3137 based HDK. Pins configuration can be easily changed in rtems/c/src/lib/libbsp/arm/tms570/hwinit/init_pinmux.c file. The list tms570_selftest_par_list in the file rtems/c/src/lib/libbsp/arm/tms570/hwinit/bspstarthooks-hwinit.c specifies peripherals which health status is examined by parity self-test at BSP start-up. It can be easily modified for other TMS570 family members variants same as the selection of other tests in bspstarthooks-hwinit.c. --- .../arm/tms570/hwinit/bspstarthooks-hwinit.c | 422 +++++++++++++++++++++ 1 file changed, 422 insertions(+) create mode 100644 c/src/lib/libbsp/arm/tms570/hwinit/bspstarthooks-hwinit.c (limited to 'c/src/lib/libbsp/arm/tms570/hwinit/bspstarthooks-hwinit.c') diff --git a/c/src/lib/libbsp/arm/tms570/hwinit/bspstarthooks-hwinit.c b/c/src/lib/libbsp/arm/tms570/hwinit/bspstarthooks-hwinit.c new file mode 100644 index 0000000000..21f4c7d43d --- /dev/null +++ b/c/src/lib/libbsp/arm/tms570/hwinit/bspstarthooks-hwinit.c @@ -0,0 +1,422 @@ +#include +#include +#include +#include + +#include "tms570_selftest.h" +#include "tms570_selftest_parity.h" +#include "tms570_hwinit.h" + +void bsp_start_hook_0_done( void ); + +static inline +int tms570_running_from_tcram( void ) +{ + void *fncptr = (void*)bsp_start_hook_0; + return ( fncptr >= (void*)TMS570_TCRAM_START_PTR ) && + ( fncptr < (void*)TMS570_TCRAM_WINDOW_END_PTR ); +} + +static inline +int tms570_running_from_sdram( void ) +{ + void *fncptr = (void*)bsp_start_hook_0; + return ( ( (void*)fncptr >= (void*)TMS570_SDRAM_START_PTR ) && + ( (void*)fncptr < (void*)TMS570_SDRAM_WINDOW_END_PTR ) ); +} + +#define PBIST_March13N_SP 0x00000008U /**< March13 N Algo for 1 Port mem */ + +BSP_START_TEXT_SECTION void bsp_start_hook_0( void ) +{ + /* + * Work Around for Errata DEVICE#140: ( Only on Rev A silicon) + * + * Errata Description: + * The Core Compare Module(CCM-R4) may cause nERROR to be asserted after a cold power-on + * Workaround: + * Clear ESM Group2 Channel 2 error in ESMSR2 and Compare error in CCMSR register + */ + if ( TMS570_SYS1.DEVID == 0x802AAD05U ) { + _esmCcmErrorsClear_(); + } + + /* Enable CPU Event Export */ + /* This allows the CPU to signal any single-bit or double-bit errors detected + * by its ECC logic for accesses to program flash or data RAM. + */ + _coreEnableEventBusExport_(); + + /* Workaround for Errata CORTEXR4 66 */ + _errata_CORTEXR4_66_(); + + /* Workaround for Errata CORTEXR4 57 */ + _errata_CORTEXR4_57_(); + + /* check for power-on reset condition */ + /*SAFETYMCUSW 139 S MR:13.7 "Hardware status bit read check" */ + if ( ( TMS570_SYS1.SYSESR & TMS570_SYS1_SYSESR_PORST ) != 0U ) { + /* clear all reset status flags */ + TMS570_SYS1.SYSESR = 0xFFFFU; + + /* continue with normal start-up sequence */ + } + /*SAFETYMCUSW 139 S MR:13.7 "Hardware status bit read check" */ + else if ( ( TMS570_SYS1.SYSESR & TMS570_SYS1_SYSESR_OSCRST ) != 0U ) { + /* Reset caused due to oscillator failure. + Add user code here to handle oscillator failure */ + } + /*SAFETYMCUSW 139 S MR:13.7 "Hardware status bit read check" */ + else if ( ( TMS570_SYS1.SYSESR & TMS570_SYS1_SYSESR_WDRST ) != 0U ) { + /* Reset caused due + * 1) windowed watchdog violation - Add user code here to handle watchdog violation. + * 2) ICEPICK Reset - After loading code via CCS / System Reset through CCS + */ + /* Check the WatchDog Status register */ + if ( TMS570_RTI.WDSTATUS != 0U ) { + /* Add user code here to handle watchdog violation. */ + /* Clear the Watchdog reset flag in Exception Status register */ + TMS570_SYS1.SYSESR = TMS570_SYS1_SYSESR_WDRST; + } else { + /* Clear the ICEPICK reset flag in Exception Status register */ + TMS570_SYS1.SYSESR = TMS570_SYS1_SYSESR_WDRST; + } + } + /*SAFETYMCUSW 139 S MR:13.7 "Hardware status bit read check" */ + else if ( ( TMS570_SYS1.SYSESR & TMS570_SYS1_SYSESR_CPURST ) != 0U ) { + /* Reset caused due to CPU reset. + CPU reset can be caused by CPU self-test completion, or + by toggling the "CPU RESET" bit of the CPU Reset Control Register. */ + + /* clear all reset status flags */ + TMS570_SYS1.SYSESR = TMS570_SYS1_SYSESR_CPURST; + } + /*SAFETYMCUSW 139 S MR:13.7 "Hardware status bit read check" */ + else if ( ( TMS570_SYS1.SYSESR & TMS570_SYS1_SYSESR_SWRST ) != 0U ) { + /* Reset caused due to software reset. + Add user code to handle software reset. */ + } else { + /* Reset caused by nRST being driven low externally. + Add user code to handle external reset. */ + } + + /* + * Check if there were ESM group3 errors during power-up. + * These could occur during eFuse auto-load or during reads from flash OTP + * during power-up. Device operation is not reliable and not recommended + * in this case. + * An ESM group3 error only drives the nERROR pin low. An external circuit + * that monitors the nERROR pin must take the appropriate action to ensure that + * the system is placed in a safe state, as determined by the application. + */ + if ( ( TMS570_ESM.SR[ 2 ] ) != 0U ) { + /*SAFETYMCUSW 5 C MR:NA "for(;;) can be removed by adding "# if 0" and "# endif" in the user codes above and below" */ + /*SAFETYMCUSW 26 S MR:NA "for(;;) can be removed by adding "# if 0" and "# endif" in the user codes above and below" */ + /*SAFETYMCUSW 28 D MR:NA "for(;;) can be removed by adding "# if 0" and "# endif" in the user codes above and below" */ + for (;; ) { + } /* Wait */ + } + + /* Initialize System - Clock, Flash settings with Efuse self check */ + tms570_system_hw_init(); + + /* Workaround for Errata PBIST#4 */ + /* FIXME */ + //errata_PBIST_4(); + + /* + * Run a diagnostic check on the memory self-test controller. + * This function chooses a RAM test algorithm and runs it on an on-chip ROM. + * The memory self-test is expected to fail. The function ensures that the PBIST controller + * is capable of detecting and indicating a memory self-test failure. + */ + tms570_pbist_self_check(); + + /* Run PBIST on STC ROM */ + tms570_pbist_run( (uint32_t) STC_ROM_PBIST_RAM_GROUP, + ( (uint32_t) PBIST_TripleReadSlow | (uint32_t) PBIST_TripleReadFast ) ); + + /* Wait for PBIST for STC ROM to be completed */ + /*SAFETYMCUSW 28 D MR:NA "Hardware status bit read check" */ + while ( tms570_pbist_is_test_completed() != TRUE ) { + } /* Wait */ + + /* Check if PBIST on STC ROM passed the self-test */ + if ( tms570_pbist_is_test_passed() != TRUE ) { + /* PBIST and STC ROM failed the self-test. + * Need custom handler to check the memory failure + * and to take the appropriate next step. + */ + tms570_pbist_fail(); + } + + /* Disable PBIST clocks and disable memory self-test mode */ + tms570_pbist_stop(); + + /* Run PBIST on PBIST ROM */ + tms570_pbist_run( (uint32_t) PBIST_ROM_PBIST_RAM_GROUP, + ( (uint32_t) PBIST_TripleReadSlow | (uint32_t) PBIST_TripleReadFast ) ); + + /* Wait for PBIST for PBIST ROM to be completed */ + /*SAFETYMCUSW 28 D MR:NA "Hardware status bit read check" */ + while ( tms570_pbist_is_test_completed() != TRUE ) { + } /* Wait */ + + /* Check if PBIST ROM passed the self-test */ + if ( tms570_pbist_is_test_passed() != TRUE ) { + /* PBIST and STC ROM failed the self-test. + * Need custom handler to check the memory failure + * and to take the appropriate next step. + */ + tms570_pbist_fail(); + } + + /* Disable PBIST clocks and disable memory self-test mode */ + tms570_pbist_stop(); + + if ( !tms570_running_from_tcram() ) { + /* + * The next sequence tests TCRAM, main TMS570 system operation RAM area. + * The tests are destructive, lead the first to fill memory by 0xc5c5c5c5 + * and then to clear it to zero. The sequence is obliviously incompatible + * with RTEMS image running from TCRAM area (code clears itself). + * + * But TCRAM clear leads to overwrite of stack which is used to store + * value of bsp_start_hook_0 call return address from link register. + * + * If the bsp_start_hook_0 by jump to bsp_start_hook_0_done + * then generated C code does not use any variable which + * is stores on stack and code works OK even that memory + * is cleared during bsp_start_hook_0 execution. + * + * The last assumption is a little fragile in respect to + * code and compiler changes. + */ + + /* Disable RAM ECC before doing PBIST for Main RAM */ + _coreDisableRamEcc_(); + + /* Run PBIST on CPU RAM. + * The PBIST controller needs to be configured separately for single-port and dual-port SRAMs. + * The CPU RAM is a single-port memory. The actual "RAM Group" for all on-chip SRAMs is defined in the + * device datasheet. + */ + tms570_pbist_run( 0x08300020U, /* ESRAM Single Port PBIST */ + (uint32_t) PBIST_March13N_SP ); + + /* Wait for PBIST for CPU RAM to be completed */ + /*SAFETYMCUSW 28 D MR:NA "Hardware status bit read check" */ + while ( tms570_pbist_is_test_completed() != TRUE ) { + } /* Wait */ + + /* Check if CPU RAM passed the self-test */ + if ( tms570_pbist_is_test_passed() != TRUE ) { + /* CPU RAM failed the self-test. + * Need custom handler to check the memory failure + * and to take the appropriate next step. + */ + tms570_pbist_fail(); + } + + /* Disable PBIST clocks and disable memory self-test mode */ + tms570_pbist_stop(); + + /* + * Initialize CPU RAM. + * This function uses the system module's hardware for auto-initialization of memories and their + * associated protection schemes. The CPU RAM is initialized by setting bit 0 of the MSIENA register. + * Hence the value 0x1 passed to the function. + * This function will initialize the entire CPU RAM and the corresponding ECC locations. + */ + tms570_memory_init( 0x1U ); + + /* + * Enable ECC checking for TCRAM accesses. + * This function enables the CPU's ECC logic for accesses to B0TCM and B1TCM. + */ + _coreEnableRamEcc_(); + } /* end of the code skipped for tms570_running_from_tcram() */ + + /* Start PBIST on all dual-port memories */ + /* NOTE : Please Refer DEVICE DATASHEET for the list of Supported Dual port Memories. + PBIST test performed only on the user selected memories in HALCoGen's GUI SAFETY INIT tab. + */ + tms570_pbist_run( (uint32_t) 0x00000000U | /* EMAC RAM */ + (uint32_t) 0x00000000U | /* USB RAM */ + (uint32_t) 0x00000800U | /* DMA RAM */ + (uint32_t) 0x00000200U | /* VIM RAM */ + (uint32_t) 0x00000040U | /* MIBSPI1 RAM */ + (uint32_t) 0x00000080U | /* MIBSPI3 RAM */ + (uint32_t) 0x00000100U | /* MIBSPI5 RAM */ + (uint32_t) 0x00000004U | /* CAN1 RAM */ + (uint32_t) 0x00000008U | /* CAN2 RAM */ + (uint32_t) 0x00000010U | /* CAN3 RAM */ + (uint32_t) 0x00000400U | /* ADC1 RAM */ + (uint32_t) 0x00020000U | /* ADC2 RAM */ + (uint32_t) 0x00001000U | /* HET1 RAM */ + (uint32_t) 0x00040000U | /* HET2 RAM */ + (uint32_t) 0x00002000U | /* HTU1 RAM */ + (uint32_t) 0x00080000U | /* HTU2 RAM */ + (uint32_t) 0x00004000U | /* RTP RAM */ + (uint32_t) 0x00008000U, /* FRAY RAM */ + (uint32_t) PBIST_March13N_DP ); + + if ( !tms570_running_from_tcram() ) { + + /* Test the CPU ECC mechanism for RAM accesses. + * The checkBxRAMECC functions cause deliberate single-bit and double-bit errors in TCRAM accesses + * by corrupting 1 or 2 bits in the ECC. Reading from the TCRAM location with a 2-bit error + * in the ECC causes a data abort exception. The data abort handler is written to look for + * deliberately caused exception and to return the code execution to the instruction + * following the one that caused the abort. + */ + tms570_check_tcram_ecc(); + + /* Wait for PBIST for CPU RAM to be completed */ + /*SAFETYMCUSW 28 D MR:NA "Hardware status bit read check" */ + while ( tms570_pbist_is_test_completed() != TRUE ) { + } /* Wait */ + + /* Check if CPU RAM passed the self-test */ + if ( tms570_pbist_is_test_passed() != TRUE ) { + /* CPU RAM failed the self-test. + * Need custom handler to check the memory failure + * and to take the appropriate next step. + */ + tms570_pbist_fail(); + } + + } /* end of the code skipped for tms570_running_from_tcram() */ + + /* Disable PBIST clocks and disable memory self-test mode */ + tms570_pbist_stop(); + + /* Release the MibSPI1 modules from local reset. + * This will cause the MibSPI1 RAMs to get initialized along with the parity memory. + */ + TMS570_SPI1.GCR0 = TMS570_SPI_GCR0_nRESET; + + /* Release the MibSPI3 modules from local reset. + * This will cause the MibSPI3 RAMs to get initialized along with the parity memory. + */ + TMS570_SPI3.GCR0 = TMS570_SPI_GCR0_nRESET; + + /* Release the MibSPI5 modules from local reset. + * This will cause the MibSPI5 RAMs to get initialized along with the parity memory. + */ + TMS570_SPI5.GCR0 = TMS570_SPI_GCR0_nRESET; + + /* Enable parity on selected RAMs */ + tms570_enable_parity(); + + /* Initialize all on-chip SRAMs except for MibSPIx RAMs + * The MibSPIx modules have their own auto-initialization mechanism which is triggered + * as soon as the modules are brought out of local reset. + */ + /* The system module auto-init will hang on the MibSPI RAM if the module is still in local reset. + */ + /* NOTE : Please Refer DEVICE DATASHEET for the list of Supported Memories and their channel numbers. + Memory Initialization is perfomed only on the user selected memories in HALCoGen's GUI SAFETY INIT tab. + */ + tms570_memory_init( (uint32_t) ( (uint32_t) 1U << 1U ) | /* DMA RAM */ + (uint32_t) ( (uint32_t) 1U << 2U ) | /* VIM RAM */ + (uint32_t) ( (uint32_t) 1U << 5U ) | /* CAN1 RAM */ + (uint32_t) ( (uint32_t) 1U << 6U ) | /* CAN2 RAM */ + (uint32_t) ( (uint32_t) 1U << 10U ) | /* CAN3 RAM */ + (uint32_t) ( (uint32_t) 1U << 8U ) | /* ADC1 RAM */ + (uint32_t) ( (uint32_t) 1U << 14U ) | /* ADC2 RAM */ + (uint32_t) ( (uint32_t) 1U << 3U ) | /* HET1 RAM */ + (uint32_t) ( (uint32_t) 1U << 4U ) | /* HTU1 RAM */ + (uint32_t) ( (uint32_t) 1U << 15U ) | /* HET2 RAM */ + (uint32_t) ( (uint32_t) 1U << 16U ) /* HTU2 RAM */ + ); + + /* Disable parity */ + tms570_disable_parity(); + + /* + * Test the parity protection mechanism for peripheral RAMs + * Refer DEVICE DATASHEET for the list of Supported Memories + * with parity. + */ + + tms570_selftest_par_run( tms570_selftest_par_list, + tms570_selftest_par_list_size ); + +#if 0 + /* + * RTEMS VIM initialization is implemented by the function + * bsp_interrupt_facility_initialize(). RTEMS does not + * gain performance from use of vectors targets provided + * directly by VIM. RTEMS require to route all interrupts + * through _ARMV4_Exception_interrupt handler. + * + * But actual RTEMS VIM initialization lefts some registers + * default values untouched. All registers values should be + * ensured/configured in future probably. + */ + + /* Enable IRQ offset via Vic controller */ + _coreEnableIrqVicOffset_(); + + /* Initialize VIM table */ + vimInit(); +#endif + + /* Configure system response to error conditions signaled to the ESM group1 */ + tms570_esm_init(); + +#if 1 + /* + * Do not depend on link register to be restored to + * correct value from stack. If TCRAM self test is enabled + * the all stack content is zeroed there. + */ + bsp_start_hook_0_done(); +#endif +} + +BSP_START_TEXT_SECTION void bsp_start_hook_1( void ) +{ + /* At this point we can use objects outside the .start section */ +#if 0 + /* Do not run attempt to initialize MPU when code is running from SDRAM */ + if ( !tms570_running_from_sdram() ) { + /* + * MPU background areas setting has to be overlaid + * if execution of code is required from external memory/SDRAM. + * This region is non executable by default. + */ + _mpuInit_(); + } +#endif + tms570_emif_sdram_init(); + + bsp_start_copy_sections(); + bsp_start_clear_bss(); +} + +/* + * Chip specific list of peripherals which should be tested + * for functional RAM parity reporting + */ +const tms570_selftest_par_desc_t *const +tms570_selftest_par_list[] = { + &tms570_selftest_par_het1_desc, + &tms570_selftest_par_htu1_desc, + &tms570_selftest_par_het2_desc, + &tms570_selftest_par_htu2_desc, + &tms570_selftest_par_adc1_desc, + &tms570_selftest_par_adc2_desc, + &tms570_selftest_par_can1_desc, + &tms570_selftest_par_can2_desc, + &tms570_selftest_par_can3_desc, + &tms570_selftest_par_vim_desc, + &tms570_selftest_par_dma_desc, + &tms570_selftest_par_spi1_desc, + &tms570_selftest_par_spi3_desc, + &tms570_selftest_par_spi5_desc, +}; + +const int tms570_selftest_par_list_size = + RTEMS_ARRAY_SIZE( tms570_selftest_par_list ); -- cgit v1.2.3