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.

TMS570LS2135: Prefetch Abort Exception from checkRAMCC & checkFlashECC

Part Number: TMS570LS2135
Other Parts Discussed in Thread: HALCOGEN

Tool/software:

Background:

  • We are using a bootloader (BL, sectors 0,1) and application (sectors 2,3,4). 
  • Both the BL and App run their HalCoGen generated sys_startup.c files
  • BL has `checkRAMECC()` while App has `checkRAMECC()` and `checkFlashECC()` tests enabled in their respective sys_startup.c files.
  • Our exception handling could be better. But for now, exceptions are part of BL code and nothing unique is done in App or BL to redirect them while running App.
  • We use the `vfill` mechanism in BL linker to ensure valid ECC for entire flash when loading the BL. BL is loaded by JTAG with "Auto ECC" and "Flash Verification" disabled.
  • This works so far, except for 2 boards described below.

Problem:

  • For 2 boards, BL loads fine after reset. When the BL attempts a jump to app, it runs the app's sys_startup.c file. In that file, when it runs either of `checkRAMECC` or `checkFlashECC` functions, then control jumps to address 0x0C (Prefetch abort). The MCU gets stuck, and asserts nERROR pin as those functions intentionally inject ECC errrors. The board has to be power cycled to clear the error and the whole cycle repeats.
  • We have at least 3 other boards that don't show this behavior, for the same BL and App.
  • One unique thing I can think of for these 2 problematic boards is they have stayed continuously ON for relatively much longer than other boards. Other boards see at least several power cycles in a day as they are part of CI setup. These two boards are for bench development and have stayed on without any power cycle or reset for several days and weeks at a stretch. They started showing this problem recently with no known HW/FW change.

Questions:

  • checkRAMECC() and checkFlashECC() are supposed to induce dabort exceptions, which are then gracefully handled. Why would they generate prefetch_abort exceptions ?
  • Is there any time varying behavior to be expected where these 2 boards having stayed on much longer than others might show an otherwise latent issue ?
  • Do you think this is related how the app relies on exception handlers in BL's space ? While not ideal, I don't understand why would it be a problem. 



App Linker File:

/*----------------------------------------------------------------------------*/
/* Linker Settings                                                            */

--retain="*(.intvecs)"

/* USER CODE BEGIN (1) */
/* Reserve a 4 byte memory location at end of FLASH_CODE to store CRC         */
#define __CRC_ADDRESS  0x3FFFC
/* USER CODE END */

/*----------------------------------------------------------------------------*/
/* Memory Map                                                                 */

MEMORY
{
    VECTORS         (X)  : origin=0x00010020 length=0x00000020
    /* FLASH CODE: sectors 2 to 4 are used for application */
    /* Rest of FLASH is unused */
    FLASH_CODE      (RX) : origin=0x00010040 length=0x30000 - 0x40 fill=0xFFFFFFFF
    FLASH0_UNUSED   (RX) : origin=0x00040000 length=0x00180000 - 0x40000
    FLASH1_UNUSED   (RX) : origin=0x00180000 length=0x00080000
    STACKS          (RW) : origin=0x08000000 length=0x00001500
    RAM             (RW) : origin=0x08001500 length=0x0003EB00

}

/*----------------------------------------------------------------------------*/
/* Section Configuration                                                      */

SECTIONS
{
    .intvecs : {} > VECTORS
    .text    : {} > FLASH_CODE
    .const   : {} > FLASH_CODE
    .cinit   : {} > FLASH_CODE
    .pinit   : {} > FLASH_CODE
    .crc_section : {} > __CRC_ADDRESS
    .bss     : {} > RAM
    .data    : {} > RAM
	.sysmem  : {} > RAM
	
}



BL Linker File

/***********************************************************************
* Author         : QJ Wang. qjwang@ti.com
* Date           : 5-25-2019
*/
/* Copyright (C) 2013-2019 Texas Instruments Incorporated - http://www.ti.com/
 *
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*                                                                            */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN (0) */
/* USER CODE END */


/*----------------------------------------------------------------------------*/
/* 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 vfill = 0xffffffff
    FLASH0     (RX)  : origin=0x00000020 length=0x0017FFE0 vfill = 0xffffffff
    FLASH1     (RX)  : origin=0x00180000 length=0x00080000 vfill = 0xffffffff
    SRAM       (RWX) : origin=0x08002000 length=0x0002D000
    STACK      (RW)  : origin=0x08000000 length=0x00002000

/* USER CODE BEGIN (3) */
/*
    ECC_VEC (R)  : origin=0xf0400000 length=0x4 ECC={algorithm=algoL2R5F021, input_range=VECTORS }
    ECC_FLA0 (R) : origin=0xf0400000 + 0x4 length=0x3FFFC ECC={algorithm=algoL2R5F021, input_range=FLASH0 }
    ECC_FLA1 (R) : origin=0xf0440000 length=0x40000 ECC={algorithm=algoL2R5F021, input_range=FLASH1 }
*/
#if 1
    ECC_VEC  (R) : origin=(0xf0400000 + (start(VECTORS) >> 3))
                   length=(size(VECTORS) >> 3)
                   ECC={algorithm=algoL2R5F021, input_range=VECTORS}

    ECC_FLA0 (R) : origin=(0xf0400000 + (start(FLASH0)  >> 3))
                   length=(size(FLASH0)  >> 3)
                   ECC={algorithm=algoL2R5F021, input_range=FLASH0 }

    ECC_FLA1 (R) : origin=(0xf0400000 + (start(FLASH1)  >> 3))
                   length=(size(FLASH1)  >> 3)
                   ECC={algorithm=algoL2R5F021, input_range=FLASH1 }
#endif
/* USER CODE END */

}

/* USER CODE BEGIN (4) */
ECC
{
    algoL2R5F021 : address_mask = 0xfffffff8 /* Address Bits 31:3 */
                   hamming_mask = R4         /* Use R4/R5 build in Mask */
                   parity_mask  = 0x0c       /* Set which ECC bits are Even and Odd parity */
                   mirroring    = F021       /* RM57Lx and TMS570LCx are build in F021 */
}
/* USER CODE END */

/*----------------------------------------------------------------------------*/
/* Section Configuration                                                      */
SECTIONS
{
/* USER CODE BEGIN (5) */
/* USER CODE END */
   .intvecs : {} > VECTORS

   /* The toot directory is \Debug */
   flashAPI:
   {
     ./build/src/SafetyMCU_Bootloaders/F021_Flash_API/02.01.01/source/Fapi_UserDefinedFunctions.o (.text)
     ./build/src/SafetyMCU_Bootloaders/source/bl_flash.o (.text)
     --library= "./src/SafetyMCU_Bootloaders/F021_Flash_API/02.01.01/F021_API_CortexR4_BE.lib"  (.text)
   } palign=8 load = FLASH0, run = SRAM, LOAD_START(apiLoadStart), RUN_START(apiRunStart), SIZE(apiLoadSize)

   .text  : {} > FLASH0 /*Initialized executable code and constants*/
   .const : {} > FLASH0
   .cinit : {} > FLASH0 /*Initialized global and static variables*/
   .pinit : {} > FLASH0
   .data  : {} > SRAM
   .bss   : {} > SRAM   /*Uninitialized Global and static variables */
   .sysmem  : {} > SRAM

/* USER CODE BEGIN (6) */

/* USER CODE END */
}

/* USER CODE BEGIN (7) */
/* USER CODE END */


/*----------------------------------------------------------------------------*/
/* Misc                                                                       */

/* USER CODE BEGIN (8) */
/* USER CODE END */
/*----------------------------------------------------------------------------*/




  • I was able to diagnose this a bit more.

    I think the ECC locations are not being programmed while flashing the bootloader. I read the flash address `0xf0400000` and it reads all 0xffffffff from that location onwards. This would explain much of the behavior - where a dabort exception during start up tests would lead to prefetch abort as the MCU would find dabort handler with bad ECC. The BL doesn't enable ECC check, so it's startup tests run fine whereas the app does enable ECC checks - and hence it's start up tests lead to being stuck in prefect_abort loop.

    So the question is - in spite of using the linker-generated ECC approach in my BL's linker file above, why wouldn't the ECC be programmed correctly ? Note that while flashing the bootloader, I do un-check the "Auto ECC Generation" option on the debugger. Do I need to do anything else to ensure ECC is embedded in the .out file and it's being programmed by the loader while flashing ?

    I also ran the counter test where I enable the "Auto ECC Generation" and then flash the boot-loader. Everything works fine in that case, including successfully running the self tests in app and bootloader. I am also able to see valid data at 0xf0400000 location. This confirms my hypothesis about this being related to invalid ECC in BL code (whose exception handlers I rely on in app)

  • Hi Jim,

    Here i found one conflict in your linker file:

    As every 8 bytes of data have one byte of ECC, so for 0x180000 size of memory flash the ECC size should be 0x30000.

    I am not sure this exactly causing the issue, but try this change and test it again.

    --
    Thanks & regards,
    Jagadish.

  • Hey Jagadish,

    Thanks for your response.

    The code you flagged in red is actually commented out. The used code is right below it with the "#if 1" guard. And the code sizes the length correctly as it does a ">>3" operation on Flash size to arrive at correct length. I will clean up the dead code to avoid similar confusion for anyone else.

    I was able to resolve the issue however. The part I was missing was to add the `--ecc=on` flag to the linker command. Once I added that, things work as expected.

  • I was able to resolve the issue however. The part I was missing was to add the `--ecc=on` flag to the linker command. Once I added that, things work as expected.

    Good to hear that Jim, Good work!

    Here also they mentioned about this modification:

    10.5.9. Configuring Error Correcting Code (ECC) with the Linker — TI Arm Clang Compiler Tools User's Guide

    Anyway, Good work!

    --
    Thanks & regards,
    Jagadish.