This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to eliminate FMC ECC errors?

Other Parts Discussed in Thread: HALCOGEN

We are receiving both ESM1-6 and ESM3-7 errors related to FMC ECC and cannot figure out why.

We are using essentially the sys_startup.c from HalCoGen, but modified to match the coding standards and modularity we have setup for this project as well as mapping of comments to SPNC106D Standard Init Sequence document. We are building and flashing with CCS6.1.0. When we run, sometime after branching to main, we get the nERROR output. Pausing the debugger, we see the ESM Status set as described for the two FMC ERR errors.

If the _coreEnableFlashEcc_() is commented out of sys_startup.c, everything runs without incident. 

Any insight would be appreciated.

/** @file sys_startup.c
 *
 *  This module exposes the main entry point to the system initialization code
 *  _c_init00 and then calls the initialization functions to setup the hardware.
 *  Then the module calls the main function that is the entry point to the user
 *  developed application.
 *
 *  The format of this file tailors the HalCoGen output according to the
 *  recommendations of SPNA106D, "Initialization of Hercules ARM Cortex-R4F
 *  Microcontrollers," and is annotated throughout according to the steps
 *  in that document.
 *
 *  @par
 *  Uses Interrupts NO
 *
 *  @pre None
 */

/* Include Files */
/* Library Includes */
#include <sys_common.h>
/* Utility Includes */
/* Device Support Includes */
#include <sys_pmu.h>
#include "sys_core.h"
#include "sys_selftest.h"
/* BSP Driver Includes */
#include "VIM/drv_vim.h"
#include "ESM/drv_esm.h"
#include "RAM/drv_ram.h"
/* BSP HAL Includes */
#include "system.h"
/* Data Store Includes */
/* Application Level Includes */



/* Lint review disclaimers */
/*lint -e923 OK to cast uint32_t to registers. */
/*lint -e921 OK to use signed and unsigned items in cast for bit definitions */
/*lint -e950 inline used to avoid relying on stack RAM when RAM testing */


static void sys_startup_continue (void);
static inline drv_ram_err_t drv_ram_pbist_self_check (void);
static inline drv_ram_err_t drv_ram_pbist_run (uint32_t pbist_group, uint32_t pbist_algo);
static inline drv_ram_err_t drv_ram_pbist_errata_PBIST_4 (void);


/* External Functions */
extern void __TI_auto_init(void);
extern void main(void);
extern void exit(int32_t _status);

/* Startup Routine */
void _c_int00(void);


/*lint -e975
 * suppressing the warning regarding the pragmas below that
 * are necessary for Hercules ARM controllers, ensuring that the ISR is
 * recognized as an ISR (reset vector pointing to this routine) and
 * is compiled in 32-bit mode.
 */
#pragma CODE_STATE(_c_int00, 32)
#pragma INTERRUPT(_c_int00, RESET)
#pragma WEAK(_c_int00)
/*lint +e975 */

/**
 *  This function represents the main entry point for the application
 *  that is launched by the silicon.  This function initializes the core
 *  registers to allow the processor to run, setups the clocks then
 *  calls the applications main function.
 *
 *  References throughout are to the sequence described in Texas Instruments
 *  Application Report SPNA106D, Initialization of Hercules ARM Cortex R4F
 *  Microcontrollers.
 */
void _c_int00(void)
{
    /**
     *  2. Initialize the CPU registers and FPU registers, including stack
     *  pointers.
     */
    _coreInitRegisters_();
    _coreInitStackPointer_();

    /**
     *  1. Enable the floating-point unit (FPU) inside the Cortex-R4F CPU.
     *  Even though this is listed as the first item, the function
     *  needs to have the stack initialized first.
     */
    _coreEnableVfp_();

    /**
     *  4. Enable the CPU's Event Bus export mechanism.
     *  (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_();

    /**
     *  3. Enable the flash interface module's response to an ECC error
     *  indicated by the CPU on accesses to flash.
     */
    flashWREG->FEDACCTRL1 = 0x000A060AU;

    /**
     *  5. Enable the CPU's Single-Error-Correction Double-Error-Detection
     *  (SECDED) logic for accesses to Flash memory (CPU's ATCM interface).
     */
    _coreEnableFlashEcc_();
    /** Workaround for Errata CORTEXR4 66 */
    _errata_CORTEXR4_66_();
    /** Workaround for Errata CORTEXR4 57 */
    _errata_CORTEXR4_57_();


    /**
     *  6. Handle the cause of reset to determine whether or not to continue
     *  with the start-up sequence
     */
    if ((SYS_EXCEPTION & POWERON_RESET) != 0U)
    {
        /**
         *  Upon Power-On RESET condition, clear all reset status flags,
         *  then continue with normal start-up sequence.
         */
        SYS_EXCEPTION = 0xFFFFU;
    }
    else if ((SYS_EXCEPTION & OSC_FAILURE_RESET) != 0U)
    {
        /**
         *  Upon Oscillator failure RESET, take NO addition action at this time.
         */
        SYS_EXCEPTION = OSC_FAILURE_RESET;
    }
    else if ((SYS_EXCEPTION & WATCHDOG_RESET) !=0U)
    {
        /**
         *  Upon RESET caused by internal windowed watchdog violation or an
         *  ICEPICK Reset (After loading code via CCS/System Reset through CCS),
         *  use the Watchdog Status Register to differentiate.
         */
        if(WATCHDOG_STATUS != 0U)
        {
            /**
             *  Upon Internal Watchdog RESET, clear the Watchdog reset flag in
             *  Exception Status register and take no additional action at this
             *  time.
             */
            SYS_EXCEPTION = WATCHDOG_RESET;
        }
        else
        {
            /**
             *  Upon ICEPICK RESET, clear the ICEPICK reset flag in Exception
             *  Status register and take no additional action at this time.
             */
            SYS_EXCEPTION = ICEPICK_RESET;
        }
    }
    else if ((SYS_EXCEPTION & CPU_RESET) !=0U)
    {
        /**
         *  Upon CPU RESET (caused by CPU self-test completion, or by toggling
         *  the "CPU RESET" bit of the CPU Reset Control Register), clear all
         *  reset status flags then further determine if cause was intentional
         *  via a self-test, or a "real" reset.
         */
        SYS_EXCEPTION = CPU_RESET;

        if ((stcREG->STCSCSCR & 0xFU) == 0xAU)
        {
            /**
             *  The source of the reset should not have been an STC self-check,
             *  since it is not run, therefore halt the system as a critical
             *  core fault.
             *
             *  This path would have represented the completion of step 21, but
             *
             *  22. Run the built-in self-test for the CPU (LBIST) (A CPU
             *  reset is asserted upon completion of the CPU self-test.
             *  Therefore, the initialization steps leading up to the reset
             *  handler will be repeated).
             *
             *  ...will also not be run due to its reset dependency.
             *
             */
            system_halt();
        }
        else if ((stcREG->STCGSTAT & 0x1U) == 0x1U)
        {
            /**
             *  The source of the reset should not have been an CPU self-check,
             *  since it is not run, therefore halt the system as a critical
             *  core fault.
             */
            system_halt();
        }
        else
        {
            /**
             *  Upon any other source of CPU RESET, take NO addition action at
             *  this time.
             */
        }
    }
    else if ((SYS_EXCEPTION & SW_RESET) != 0U)
    {
        /**
         *  Upon any SW RESET, consider to be a Warm Start, taking no
         *  additional action at this time.
         */
        SYS_EXCEPTION = SW_RESET;
    }
    else
    {
        /**
         *  Upon any other reason for RESET, consider to be a Cold Start,
         *  taking no additional action at this time.
         */
    }

    /**
     *  7. Check if any ESM group3 error was indicated during power-up. If any
     *  ESM group3 error occurred during the power-up, it is not safe to
     *  continue code execution and the microcontroller initialization
     *  process can be stopped at this point. The subsequent steps in this
     *  sequence assume that there was no ESM group3 error during power-up.
     *  Halt the system as a critical core fault.
     */
    if (drv_esm_read_group3_status() != 0U)
    {
        system_halt();
    }

    /**
     *  Handle steps 8-20.
     */
    system_init();


    /**
     *  Step 24 is handled here early to duplicate the HalCoGen sequence
     *  and to check these subsystems before using in subsequent steps.
     */
    if (DRV_RAM_ERR_NONE != drv_ram_pbist_errata_PBIST_4())
    {
        system_halt();
    }
    if (DRV_RAM_ERR_NONE != drv_ram_pbist_self_check())
    {
        system_halt();
    }
    if (DRV_RAM_ERR_NONE != drv_ram_pbist_run(PBIST_GROUP_STC_ROM,
                                              PBIST_TripleReadFast |
                                              PBIST_TripleReadSlow))
    {
        system_halt();
    }
    if (DRV_RAM_ERR_NONE != drv_ram_pbist_run(PBIST_GROUP_PBIST_ROM,
                                              PBIST_TripleReadFast |
                                              PBIST_TripleReadSlow))
    {
        system_halt();
    }


    /**
     *  21. Run a diagnostic check on the CPU self-test controller (A CPU reset
     *  is asserted upon completion of the CPU self-test. Therefore, the
     *  initialization steps leading up to the reset handler will be repeated).
     *
     *  This reset-dependent check is not performed to avoid re-triggering the
     *  Bootloader, therefore the continue function is entered directly.
     */
    sys_startup_continue();
}


/**
 *  This function is the continuation of the _c_int00() function. It would
 *  become necessary if the reset-dependent tests were included.
 */
static void sys_startup_continue (void)
{
    /**
     *  23. Run a diagnostic check on the CPU compare module (CCM-R4F).
     *
     *  This check of a fundamental processor activity is not performed.
     */

    /**
     *  24. Run a diagnostic check on the memory self-test controller.
     *
     *  This is done earlier along with the errata and the checks of the PBIST
     *  ROM and the STC RAM.
     */

    /**
     *  25. Start a self-test on the CPU RAM using the programmable built-in
     *  self-test (PBIST) controller and wait for this self-test to complete
     *  and pass.
     *
     *  Disable RAM ECC before doing PBIST for Main RAM
     */
    _coreDisableRamEcc_();
    if (DRV_RAM_ERR_NONE != drv_ram_pbist_run(PBIST_GROUP_ESRAM1_SINGLE |
                                              PBIST_GROUP_ESRAM5_SINGLE |
                                              PBIST_GROUP_ESRAM6_SINGLE |
                                              PBIST_GROUP_ESRAM8_SINGLE,
                                              PBIST_March13N_SP))
    {
        system_halt();
    }


    /**
     *  26. Initialize the CPU RAM using the system module hardware
     *  initialization mechanism so that the ECC region for the CPU RAM is
     *  also initialized.
     */
    drv_ram_init((uint32_t)((uint32_t)1U << 0U));

    /**
     *  27. Enable the CPU's Single-Error-Correction Double-Error-Detection
     *  (SECDED) logic for accesses to CPU RAM memory (CPU's B0TCM and B1TCM
     *  interfaces).
     */
    _coreEnableRamEcc_();

    /**
     *  28. Start a self-test on all on-chip dual-port SRAMs using the PBIST
     *  controller.
     */
    if (DRV_RAM_ERR_NONE != drv_ram_pbist_run(PBIST_GROUP_DCAN1_DUAL |
                                              PBIST_GROUP_DCAN2_DUAL |
                                              PBIST_GROUP_DCAN3_DUAL |
                                              PBIST_GROUP_VIM_DUAL   |
                                              PBIST_GROUP_MIBADC1_DUAL |
                                              PBIST_GROUP_N2HET1_DUAL  |
                                              PBIST_GROUP_N2HET2_DUAL,
                                              PBIST_March13N_DP))
    {
        system_halt();
    }

    /**
     *  29. Run the self-test on the CPU's SECDED logic for accesses to main
     *  data RAM (B0TCM and B1TCM).
     *
     *  This memory test is not performed.
     */

    /**
     *  30. Run the self-test on the CPU's SECDED logic for accesses to the
     *  main Flash memory (ATCM).
     *
     *  This memory test is not performed.
     *
     *  Disable flash diagnostic mode
     */




    flashWREG->FEDACCTRL1 = 0x000A060AU;

    if ((esmREG->SR1[0U] & 0x40U) == 0x40U)
    {
        /* a 1-bit error was detected during flash OTP read by flash module
           run a self-check on ECC logic inside FMC */

        /* clear ESM group1 channel 6 flag */
        esmREG->SR1[0U] = 0x40U;
    }

    /* 1-bit failure was indicated and corrected */
    flashWREG->FEDACSTATUS = 0x00010006U;

    /* clear ESM group1 channel 6 flag */
    esmREG->SR1[0U] = 0x40U;

    //lint -e529
    volatile uint32_t temp = flashWREG->FUNCERRADD;
    flashWREG->FEDACSTATUS = 0x00020100U;

    /* clear ESM group3 channel 7 */
    esmREG->SR1[2U] = 0x80U;

    /* The nERROR pin will become inactive once the LTC counter expires */
    esmREG->EKR = 0x5U;

    flashWREG->FDIAGCTRL = 0x000A0007U;




    /**
     *  31. Wait for self-test to complete and pass on all on-chip dual-port
     *  SRAMs (This was already part of the PBIT run in step 28.
     */

    /**
     *  32. Start a self-test on all on-chip single-port SRAMs excluding the
     *  CPU RAM using the PBIST controller (None of these are used).
     *
     *  33. Wait for self-test to complete and pass on all on-chip single-port
     *  SRAMs.
     */

    /**
     *  34. Start auto-initialization for all other on-chip SRAMs (enable
     *  parity first).
     *
     *  35. Check if the auto-initialization process for all RAMs is completed;
     *  wait here if it has not completed (disable parity after).
     */
    sys_enable_parity();
    drv_ram_init( (uint32_t)((uint32_t)0U << 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)0U << 4U)    /* HTU1 RAM */
                | (uint32_t)((uint32_t)1U << 15U)   /* HET2 RAM */
                | (uint32_t)((uint32_t)0U << 16U)   /* HTU2 RAM */ );
    sys_disable_parity();

    /**
     *  36. Check the parity error detection mechanism for all peripheral
     *  memories.
     */
    if (FAIL == sys_vim_parity_check()) {
        system_halt();
    }
    if (FAIL == sys_het1_parity_check()) {
        system_halt();
    }
    if (FAIL == sys_het2_parity_check()) {
        system_halt();
    }

    if (FAIL == sys_adc1_parity_check()) {
        system_halt();
    }
    if (FAIL == sys_adc2_parity_check()) {
        system_halt();
    }

    if (FAIL == sys_can1_parity_check()) {
        system_halt();
    }
    if (FAIL == sys_can2_parity_check()) {
        system_halt();
    }
    if (FAIL == sys_can3_parity_check()) {
        system_halt();
    }

    /**
     *  37. Enable the CPU’s dedicated vectored interrupt controller (VIC) port.
     */
    _coreEnableIrqVicOffset_();

    /**
     *  38. Program all interrupt service routine addresses in the vectored
     *  interrupt manager (VIM) memory.
     *
     *  39. Configure IRQ / FIQ interrupt priorities for all interrupt channels.
     *
     *  40. Enable the desired interrupts (IRQ and/or FIQ) inside the CPU.
     *
     *  41. Enable the desired interrupts in the VIM control registers.
     */
    drv_vim_init();

    /**
     *  42. Set up the application responses to inputs to the error signaling
     *  module (ESM). This is handled from within the HAL because of the need
     *  to setup the callback that is scoped at that layer.
     */

    /**
     *  43. Initialize copy table, global variables, and constructors.
     */
    __TI_auto_init();


    /**
     *  44. Verify that the dual-clock-comparator (DCC) module can actually
     *  detect and flag a frequency error.
     *
     *  45. Configure the DCC module to continuously monitor the PLL output.
     *
     *  46. Verify that a memory protection unit (MPU) violation for all bus
     *  masters is flagged as an error to the ESM.
     *
     *  47. Run a background check on entire Flash using CRC and DMA.
     *
     *  48. Run the offset error calibration routine for the ADC.
     *
     *  49. Run a self-test on the analog-to-digital converter (ADC) analog
     *  input channels.
     *
     *  50. Check I/O loop-back for all peripherals.
     *
     *  51. Set up the MPU for the bus masters.
     *
     *  52. Set up the digital windowed watchdog (DWWD) module service window
     *  size and the module response on a violation (reset or NMI).
     *
     *  53. Configure the N2HET1-to-N2HET2 monitoring functionality.
     *
     *  54. Configure desired access permissions for peripherals using the
     *  Peripheral Central Resource (PCR) controller registers.
     *
     *  55. Configure external safety companion, e.g., TI TPS6538x, for online
     *  diagnostic operation.
     *
     *  56. Set up the real-time interrupt (RTI) module for generating periodic
     *  interrupts as required by the application.
     *
     *  Each of these is configured as needed from within the application and
     *  tested as part of PBIT and/or CBIT.
     */

    /**
     *  57. Call the main application.
     */
    main();
    exit(0);
}
//lint +e529


/*******************************************************************************
 ** Private Functions bodies
 ******************************************************************************/


/**
 *  Run a diagnostic check on the memory self-test controller
 *
 *  @return error enumeration
 */
static inline drv_ram_err_t drv_ram_pbist_self_check (void)
{
    drv_ram_err_t err = DRV_RAM_ERR_NONE;
    volatile uint32_t idx;
    uint32_t pbist_wait_done_loop = 0U;

    /* First set up the PBIST ROM clock as this clock frequency is limited to 90MHz */
    /* Disable PBIST clocks and ROM clock */
    pbistREG->PACT = 0x0U;

    /* PBIST ROM clock frequency = HCLK frequency /2 */
    /* Disable memory self controller */
    systemREG1->MSTGCR = 0x00000105U;

    /* Disable Memory Initialization controller */
    systemREG1->MINITGCR = 0x5U;

    /* Enable memory self controller */
    systemREG1->MSTGCR = 0x0000010AU;

    /* Clear PBIST Done */
    systemREG1->MSTCGSTAT = 0x1U;

    /* Enable PBIST controller */
    systemREG1->MSINENA = 0x1U;

    /* Wait for 32 VBUS clock cycles at least, based on HCLK to VCLK ratio */
    for (idx=0U; idx<(32U + (32U * 1U)); idx++){ /* Wait */ }

    /* Enable PBIST clocks and ROM clock */
    pbistREG->PACT = 0x3U;

    /* CPU control of PBIST */
    pbistREG->DLR = 0x10U;

    /* Custom always fail algo, this will not use the ROM and just set a fail */
    pbistREG->RAMT         = 0x00002000U;
    *(volatile uint32_t *)0xFFFFE400U = 0x4C000001U;
    *(volatile uint32_t *)0xFFFFE440U = 0x00000075U;
    *(volatile uint32_t *)0xFFFFE404U = 0x4C000002U;
    *(volatile uint32_t *)0xFFFFE444U = 0x00000075U;
    *(volatile uint32_t *)0xFFFFE408U = 0x4C000003U;
    *(volatile uint32_t *)0xFFFFE448U = 0x00000075U;
    *(volatile uint32_t *)0xFFFFE40CU = 0x4C000004U;
    *(volatile uint32_t *)0xFFFFE44CU = 0x00000075U;
    *(volatile uint32_t *)0xFFFFE410U = 0x4C000005U;
    *(volatile uint32_t *)0xFFFFE450U = 0x00000075U;
    *(volatile uint32_t *)0xFFFFE414U = 0x4C000006U;
    *(volatile uint32_t *)0xFFFFE454U = 0x00000075U;
    *(volatile uint32_t *)0xFFFFE418U = 0x00000000U;
    *(volatile uint32_t *)0xFFFFE458U = 0x00000001U;

    /* PBIST_RUN */
    pbistREG->rsvd1[1U]    = 1U;

    /* wait until memory self-test done is indicated */
    while ((systemREG1->MSTCGSTAT & 0x1U) != 0x1U)
    {
        pbist_wait_done_loop++;
    }/* Wait */

    /* Check for the failure */
    if ((pbistREG->FSRF0 & 0x1U) != 0x1U)
    {
        /* No failure was indicated even if the always fail algorithm was run*/
        err = DRV_RAM_ERR_TEST_FAULT;
    }
    else
    {
        /* Check that the algorithm executed in the expected amount of time. */
        /* This time is dependent on the ROMCLKDIV selected above            */
        if (pbist_wait_done_loop >= 2U)
        {
            err = DRV_RAM_ERR_TEST_FAULT;
        }

        /* Disable PBIST clocks and ROM clock */
        pbistREG->PACT = 0x0U;

        /* Disable PBIST */
        systemREG1->MSTGCR &= 0xFFFFFFF0U;
        systemREG1->MSTGCR |= 0x5U;
    }

    return(err);
}



/**
 *  This function performs Memory Built-in Self test using PBIST module
 *  on the indicated memory group(s) using the indicated algorithm(s).
 *
 *  @param [in] pbist_group selection bits for the RAM area to test
 *  @param [in] pbist_algo selection bits for the algorithm(s) to run
 *  @return error enumeration
 */
static inline drv_ram_err_t drv_ram_pbist_run (uint32_t pbist_group,
                                        uint32_t pbist_algo)
{
    volatile uint32_t idx;
    drv_ram_err_t retval = DRV_RAM_ERR_TEST_FAILED;

    /* PBIST ROM clock frequency = HCLK frequency /2 */
    /* Disable memory self controller */
    systemREG1->MSTGCR = 0x00000105U;

    /* Disable Memory Initialization controller */
    systemREG1->MINITGCR = 0x5U;

    /* Enable PBIST controller */
    systemREG1->MSINENA = 0x1U;

    /* Enable memory self controller */
    systemREG1->MSTGCR = 0x0000010AU;

    /* Wait for 32 VBUS clock cycles at least, based on HCLK to VCLK ratio */
    for (idx=0U; idx<(32U + (32U * 1U)); idx++){ /* Wait */ }

    /* Enable PBIST clocks and ROM clock */
    pbistREG->PACT = 0x3U;

    /* Select algorithms to be tested */
    pbistREG->ALGO = pbist_algo;

    /* Select RAM groups */
    pbistREG->RINFOL = pbist_group;

    /* Select all RAM groups */
    pbistREG->RINFOU = 0x00000000U;

    /* Allow the ROM to select the appropriate RAM Group for each algorithm */
    pbistREG->OVER = 0x1U;

    /* Algorithm code is loaded from ROM */
    pbistREG->ROM = 0x3U;

    /* Start PBIST */
    pbistREG->DLR = 0x14U;

    while ((systemREG1->MSTCGSTAT & 0x1U) == 0U)
    {
        /* Wait for test to finish */
    }

    /* Is test passed? */
    if (pbistREG->FSRF0 == 0U)
    {
        retval = DRV_RAM_ERR_NONE;
    }

    /* Disable PBIST clocks and ROM clock */
    pbistREG->PACT = 0x0U;
    systemREG1->MSTGCR &= 0xFFFFFFF0U;
    systemREG1->MSTGCR |= 0x5U;

    return (retval);
}



/**
 *  This function is workaround for Errata PBIST#4.
 *  This function is designed to initialize the ROMs using the PBIST controller.
 *  The CPU will configure the PBIST controller to test the PBIST ROM and STC ROM.
 *  This function should be called at startup after system init before using the ROMs.
 *
 *  @return error enumeration
 */
static inline drv_ram_err_t drv_ram_pbist_errata_PBIST_4 (void)
{
    drv_ram_err_t err = DRV_RAM_ERR_NONE;
    volatile uint32_t i = 0U;
    uint8_t ROM_count;
    uint32_t PBIST_wait_done_loop;
    uint32_t pmuCalibration;
    uint32_t pmuCount;

    /* PMU calibration */
    _pmuEnableCountersGlobal_();
    _pmuResetCounters_();
    _pmuStartCounters_(pmuCYCLE_COUNTER);
    _pmuStopCounters_(pmuCYCLE_COUNTER);
    pmuCalibration=_pmuGetCycleCount_();

    /* ROM_init Setup using special reserved registers as part of errata fix */
    /* (Only to be used in this function) */
    *(volatile uint32_t *)0xFFFF0400U = 0x0000000AU;
    *(volatile uint32_t *)0xFFFF040CU = 0x0000EE0AU;

    /* Loop for Executing PBIST ROM and STC ROM */
    for (ROM_count = 0U; ROM_count < 2U; ROM_count++)
    {
        PBIST_wait_done_loop = 0;

        /* Disable PBIST clocks and ROM clock */
        pbistREG->PACT = 0x0U;

        /* PBIST Clocks did not disable */
        if(pbistREG->PACT != 0x0U )
        {
            err = DRV_RAM_ERR_TEST_FAULT;
        }
        else
        {
            /* PBIST ROM clock frequency = HCLK frequency /2 */
            /* Disable memory self controller */
            systemREG1->MSTGCR = 0x00000105U;

            /* Disable Memory Initialization controller */
            systemREG1->MINITGCR = 0x5U;

            /* Enable memory self controller */
            systemREG1->MSTGCR = 0x0000010AU;

            /* Clear PBIST Done */
            systemREG1->MSTCGSTAT = 0x1U;

            /* Enable PBIST controller */
            systemREG1->MSINENA = 0x1U;

            /*SAFETYMCUSW 134 S MR:12.2 <APPROVED> "Wait for few clock cycles (Value of i not used)" */
            /*SAFETYMCUSW 134 S MR:12.2 <APPROVED> "Wait for few clock cycles (Value of i not used)" */
            /* wait for 32 VBUS clock cycles at least, based on HCLK to VCLK ratio */
            for (i=0U; i<(32U + (32U * 1U)); i++){ /* Wait */ }

            /* Enable PBIST clocks and ROM clock */
            pbistREG->PACT = 0x3U;

            /* CPU control of PBIST */
            pbistREG->DLR = 0x10U;

            /* Load PBIST ALGO to initialize the ROMs */
            *(volatile uint32_t *)0xFFFFE400U = 0x00000001U;
            *(volatile uint32_t *)0xFFFFE440U = 0x00000025U;
            *(volatile uint32_t *)0xFFFFE404U = 0x62400001U;
            *(volatile uint32_t *)0xFFFFE444U = 0x00000004U;
            *(volatile uint32_t *)0xFFFFE408U = 0x00068003U;
            *(volatile uint32_t *)0xFFFFE448U = 0x00000000U;
            *(volatile uint32_t *)0xFFFFE40CU = 0x00000004U;
            *(volatile uint32_t *)0xFFFFE44CU = 0x00006860U;
            *(volatile uint32_t *)0xFFFFE410U = 0x00000000U;
            *(volatile uint32_t *)0xFFFFE450U = 0x00000001U;
            *(volatile uint32_t *)0xFFFFE540U = 0x000003E8U;
            *(volatile uint32_t *)0xFFFFE550U = 0x00000001U;
            *(volatile uint32_t *)0xFFFFE530U = 0x00000000U;

            /* SELECT ROM */
            if (ROM_count == 1U)
            {
                /* SELECT PBIST ROM */
                *(volatile uint32_t *)0xFFFFE520U = 0x00000002U;
                *(volatile uint32_t *)0xFFFFE524U = 0x00000000U;
                pbistREG->RAMT                  = 0x01002008U;
            }
            else
            {
                /* SELECT STC ROM */
                *(volatile uint32_t *)0xFFFFE520U = 0xFFF0007CU;
                *(volatile uint32_t *)0xFFFFE524U = 0x0A63FFFFU;
                pbistREG->RAMT                  = 0x02002008U;
            }

            /*  Setup using special reserved registers as part of errata fix */
            /*      (Only to be used in this function) */
            pbistREG->rsvd1[4U]    = 1U;
            pbistREG->rsvd1[0U]    = 3U;

            /* Start PMU counter */
            _pmuResetCounters_();
            _pmuStartCounters_(pmuCYCLE_COUNTER);

            /* PBIST_RUN */
            pbistREG->rsvd1[1U]    = 1U;

            /* wait until memory self-test done is indicated */
            /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Hardware status bit read check" */
            while ((systemREG1->MSTCGSTAT & 0x1U) != 0x1U)
            {
            }/* Wait */

            /* Stop PMU counter */
            _pmuStopCounters_(pmuCYCLE_COUNTER);

            /* Get CPU cycle count */
            pmuCount =_pmuGetCycleCount_();

            /* Calculate PBIST test complete time in ROM Clock */
            /* 2 - Divide value ( Default is 2 in HALCoGen) */
            /* 1000 = 0x3E8 - Test Loop count in ROM Algorithm */
            pmuCount = pmuCount - pmuCalibration;
            PBIST_wait_done_loop = (pmuCount/2);

            /* Check PBIST status results (Address, Status, Count, etc...) */
            if ((pbistREG->FSRA0 | pbistREG->FSRA1 | pbistREG->FSRDL0 | pbistREG->rsvd3 |
                 pbistREG->FSRDL1 | pbistREG->rsvd4[0U] | pbistREG->rsvd4[1U]) != 0U)
            {
                /* PBIST Failure for the Algorithm chosen above */
                err = DRV_RAM_ERR_TEST_FAULT;
            }

            /* Check that the algorithm executed in the expected amount of time. */
            /* This time is dependent on the ROMCLKDIV selected */
            if ((PBIST_wait_done_loop <= 1020) || (PBIST_wait_done_loop >= 1200) )
            {
                err = DRV_RAM_ERR_TEST_FAULT;
            }

            /* Disable PBIST clocks and ROM clock */
            pbistREG->PACT = 0x0U;

            /* Disable PBIST */
            systemREG1->MSTGCR &= 0xFFFFFFF0U;
            systemREG1->MSTGCR |= 0x5U;
        }
    } /* ROM Loop */

    /* ROM restore default setup */
    /* (must be completed before continuing) */
    *(volatile uint32_t *)0xFFFF040CU = 0x0000AA0AU;
    *(volatile uint32_t *)0xFFFF040CU = 0x0000AA05U;
    *(volatile uint32_t *)0xFFFF0400U = 0x00000005U;

    _pmuDisableCountersGlobal_();

    return (err);
}


/*lint +e950 */
/*lint +e923 */
/*lint +e921 */


/* End of File */

  • Hi Jeff,
    Can you please check the DFAR (Data Fault Address Register) in the CPU? Once you find out the address then go to that location in the memory browser. Do you see any valid data? I want to know if you are reading from an unimplemented location for which there is no corresponding ECC. The CPU can generate speculative access to the flash area. If the address has only the erased data without proper ECC then it will detect as a ECC error, whether 1-bit or 2-bit. A speculative access that is later NOT taken into the CPU's pipeline with not cause the CPU to take the abort exception but the ECC error is still exported on its event bus.
  • Charles, thanks for the reply.

    CP15_DATA_FAULT_ADDRESS contains 0x00018014. That address in the Memory Browser comes up as ???????? which I''ll assume is not valid data.

    Also, the FCorErrAddr and FUncErrAddr in the Flash wrapper are 0x00018020 and 0x00018010, respectively, which also show in the browser as ????????.

    Does this mean I need to take additional steps to somehow force the ECC to be generated for these areas (already have Auto ECC Generation checked under Properties...Debug...Flash), or is there some other issue which I need to address?

  • /*----------------------------------------------------------------------------*/
    /* Linker Settings                                                            */
    
    --retain="*(.intvecs)"
    
    /* USER CODE BEGIN (1) */
    /* USER CODE END */
    
    /*----------------------------------------------------------------------------*/
    /* Memory Map                                                                 */
    
    MEMORY
    {
    /* USER CODE BEGIN (2) */
    /* USER CODE END */
        VECTORS (X)  : origin=0x00000000 length=0x00000020 fill=0xffffffff
        FLASH0  (RX) : origin=0x00000020 length=0x0017FFE0 vfill=0xffffffff
        FLASH1  (RX) : origin=0x00180000 length=0x00180000 vfill=0xffffffff
        STACKS  (RW) : origin=0x08000000 length=0x00001500
        RAM     (RW) : origin=0x08001500 length=0x0003EB0
    
    
    /* USER CODE BEGIN (3) */
    	ECC_VEC  (R)   : origin=0xf0400000            length=0x4             ECC={ input_range=VECTORS }
    	ECC_FLA0 (R)   : origin=0xf0400000 + 0x4      length=0x2FFFC         ECC={ input_range=FLASH0  }
    	ECC_FLA1 (R)   : origin=0xf0400000 + 0x30000  length=0x30000         ECC={ input_range=FLASH1  }
    /* USER CODE END */
    }
    
    /* USER CODE BEGIN (4) */
    /* USER CODE END */
    
    
    /*----------------------------------------------------------------------------*/
    /* Section Configuration                                                      */
    
    SECTIONS
    {
    /* USER CODE BEGIN (5) */
    /* USER CODE END */
        .intvecs : {} > VECTORS
        .text   align(8) : {} > FLASH0 | FLASH1
        .const  align(8) : {} > FLASH0 | FLASH1
        .cinit  align(8) : {} > FLASH0 | FLASH1
        .pinit  align(8) : {} > FLASH0 | FLASH1
        .bss     : {} > RAM
        .data    : {} > RAM
        .sysmem  : {} > RAM
    	
    
    /* USER CODE BEGIN (6) */
    /* USER CODE END */
    }
    
    /* USER CODE BEGIN (7) */
    /* USER CODE END */
    
    
    /*----------------------------------------------------------------------------*/
    /* Misc                                                                       */
    
    /* USER CODE BEGIN (8) */
    ECC {
    	algo_name : address_mask = 0x003ffff8
    	hamming_mask             = R4
    	parity_mask              = 0x0c
    	mirroring                = F021
    }
    /* USER CODE END */
    /*----------------------------------------------------------------------------*/
    

    Hi Jeff,

     the Auto-ECC will not generate ECC for the unimplemented flash locations. You can use the Linker generated ECC with the vfill command. The linker will generate ECC for all the unimplemented flash areas with proper ECC values. See below and give a try. The linker command is for the LS3137 device. If you have a different device with different flash size you will need to modify accordingly. Also make sure you disable auto-ECC since the .out file has already the ECC in it.

  • Charles,

    I feel confident that this is the solution, but am having a problem getting it to load. I didn't do our original linker script, but I added the ECC-related stuff hopefully analogous to your example above:

    --retain="*(.intvecs)"
    
    /*
        Define memory matching device.
    */
    MEMORY
    {
        BANK0_SECTOR0 (X) : origin=0x00000000 length=0x00008000 vfill=0xFFFFFFFF  // Loader flash memory. Not available outside CBL.
        BANK0_SECTOR1 (X) : origin=0x00008000 length=0x00008000 vfill=0xFFFFFFFF
        BANK0_SECTOR2 (X) : origin=0x00010000 length=0x00008000 vfill=0xFFFFFFFF
        BANK0_SECTOR3 (X) : origin=0x00018000 length=0x00008000 vfill=0xFFFFFFFF  // PDIF goes here.
        BANK0_SECTOR4 (X) : origin=0x00020000 length=0x00010000 fill=0xFFFFFFFF   // Application goes here.
        /*
        	length shortened from 0x00020000 to 0x00010000 until we get CAN_host and HexCalc to work with non contiguous output sections.
        */
    
        /*
            This stack location and stack size needs to be reflected in sys_core.asm
            function _coreInitStackPointer_
        */
        STACKS  (RW) : origin=0x08000000 length=0x00003500
        RAM     (RW) : origin=0x08003500 length=0x0003CB00
    
        ECC_B0_S0 (R) : origin=0xf0400000 length=0x1000 ECC={ input_range=BANK0_SECTOR0 }
        ECC_B0_S1 (R) : origin=0xf0401000 length=0x1000 ECC={ input_range=BANK0_SECTOR1 }
        ECC_B0_S2 (R) : origin=0xf0402000 length=0x1000 ECC={ input_range=BANK0_SECTOR2 }
        ECC_B0_S3 (R) : origin=0xf0403000 length=0x1000 ECC={ input_range=BANK0_SECTOR3 }
        ECC_B0_S4 (R) : origin=0xf0404000 length=0x2000 ECC={ input_range=BANK0_SECTOR4 }
    
    }
    
    /*
        SECTIONS assigns linker sections to specific memory blocks.
    */
    SECTIONS
    {
        /*
            Allocate uninitalized data sections:
        */
        .bss     : {} > RAM
        .data    : {} > RAM
        .sysmem  : {} > RAM
        .stack   : {} > RAM
    
         .application_info_ovr : {app_info.obj(.application_info_ovr)} type=DSECT > BANK0_SECTOR4
        /*
            Allocate initialized sections to flash.
            Use GROUP to keep the sections together and in order.
        */
        GROUP (Initialized_App_Flash) palign(32)
        {
            .application_info palign(32)
            .intvecs palign(32)
            .text palign(32)
            .const palign(32)
            .cinit palign(32)
        } > BANK0_SECTOR4
    
        /*
            Map the crc structure for the PDIF.
            Notice this is only a place holder. The PDIF will initialize this memory, not the application.
        */
        .PDIF_config_info_ovr : {app_info.obj(.PDIF_config_info_ovr)} type=DSECT > BANK0_SECTOR3
    }
    
    
    ECC {
        algo_name : address_mask = 0x003ffff8
        hamming_mask             = R4
        parity_mask              = 0x0c
        mirroring                = F021
    }
    
    /*
        Linker diagnostic messages which are suppressed.
    */
    --diag_suppress=10229   // Suppress "output section ".data" refers to load symbol "_nop" and hence cannot be compressed; compression "rle" is ignored."
    /*
    	Linker options so unused sections aren't eliminated.
    */
    --unused_section_elimination=off
    

  • HI Markus,
    Not sure why it is not working. Can you check the map file and look for the ECC sections. Do you see them? Perhaps you can create a simple project and see if my linker works by using the memory browser to view all the unimplemented locations. Are they now showing 0xFFFFFFFF?
  • Thanks, Charles. I think I've worked it all out.

    I don't ultimately think the speculative read was the problem, but an actual read.

    Referring to our linker memory map:

    MEMORY
    {
        BANK0_SECTOR0 (X) : origin=0x00000000 length=0x00008000 vfill=0xFFFFFFFF  // Loader flash memory. Not available outside CBL.
        BANK0_SECTOR1 (X) : origin=0x00008000 length=0x00008000 vfill=0xFFFFFFFF
        BANK0_SECTOR2 (X) : origin=0x00010000 length=0x00008000 vfill=0xFFFFFFFF
        BANK0_SECTOR3 (X) : origin=0x00018000 length=0x00008000 vfill=0xFFFFFFFF  // PDIF goes here.
        BANK0_SECTOR4 (X) : origin=0x00020000 length=0x00010000 fill=0xFFFFFFFF   // Application goes here.
    

    Our code is all in sector 4 which is literally being filled in the .out, .hex, etc. and therefore the auto-ECC is probably covering this area fine. However, our code is doing access into our parameter area in sector 3 which has not been initialized at all. The intent is that this will be loaded by our bootloader and the ECC populated then, but at this stage of development, that is not done. However, our application is running a CRC check of this area, therefore, when running code from the debugger, we are accessing a flash area that has not had the ECC setup. The short solution is that I change the vfill on sector 3 above to a fill and the auto-ECC took care of it.

    I am certain that the linker-generated ECC would have also taken care of this, but our build scripts were choking on the extra memory sections in the .hex file and I figured out this fill solution before anyone could get around to fixing that.

    Thank you again for all your help and the very prompt responses,

    Jeff

  • Hi Jeff,
    Everything now makes sense with your explanation about the empty sector that was supposed to be loaded by the bootloader later on. Glad that your problem is resolved. And yes, both fill and vfill will solve the problem. It is just that the fill command would have actually filled the sector3 with data of all F's and hence grow your binary size and ultimately take longer time to program. Vfill command will not have this problem as only the ECC is added to the .out. Anyway, one sector probably is not too bad. If you were to use fill command for a device with 4MB of flash, i.e. LC4357 then then it will be beneficial to use vfill than fill as the programming time will be much quicker if your actual application code is small.