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.

TMS570LC4357: Data abort after software- or watchdog-triggered reset

Part Number: TMS570LC4357
Other Parts Discussed in Thread: HALCOGEN, RM57L843

Hello,

I'm evaluating some modules of the TMS570LC4357 on the HDK using HALCoGen and CCS with a small test application, without any OS and without interrupts. After a software- or watchdog-triggered reset, I get a data abort in one of the initialization modules generated by HALCoGen, until a hard power-on-reset. The command where the data abort occurs varies as I add or remove modules, so I think this cannot be a module-specific, but a more "general" problem.

Do you have any idea, why the processor does not do a "clean" start even after a watchdog-triggered reset?

Thanks and regards,

Jens

  • Hello Jens,

    There are several logic blocks on the MCU that are only reset by a power-on reset, mostly associated with the debug logic and some critical exception status registers. It is difficult to explain your observation without actually identifying the access that caused the data abort. Can you please paste the contents of the data fault status and address registers (in the CPU's cp15 registers) for one of the data abort instances?

    Regards,
    Sunil
  • Hello Sunil,

    thanks for your support. Here are the cp15 data fault status and address registers:

    I reduced the code of my test project to a minimum for this test:

    int main(void)
    {
    /* USER CODE BEGIN (3) */
      gioInit();
    
      /* Pushbutton GIO A7 */
      gioREG->INTDET |= (1U << 7);        /* Interrupt on both edges (cannot be set with HALCOGEN) */
    
      /* Run forever */
      while(1)
      {
        unsigned char debug_reset_test = 0;
    
        if (debug_reset_test)
        {
            systemREG1->SYSECR = 0x8000U; /* Trigger SW reset */
        }
      }
    /* USER CODE END */
    
        return 0;
    }

    In this case, the exception occurred at the access to gioREG, but, if I add additional initialization functions, it occurs in one of the other functions.

    Regards,

    Jens

  • Hi Jens,

    I have checked the behavior on my bench and do not see the issue you report. Can you paste the contents of the _c_int00() function from the sys_startup.c file? The reset handler may be skipping some initialization steps in case of software reset or watchdog reset in your setup.

    The reset handler sequence generated by HALCoGen does require an update to be able to address each reset cause separately, but it does go through the init steps that would prevent the issue that you are observing.

    Regards,
    Sunil
  • Hi Sunil,

    this is the _c_int00 routine from HL_sys_startup.c, generated by HALCoGen 04.07.00.

    Regards,

    Jens

    /* Startup Routine */
    void _c_int00(void);
    /* USER CODE BEGIN (4) */
    /* USER CODE END */
    
    #pragma CODE_STATE(_c_int00, 32)
    #pragma INTERRUPT(_c_int00, RESET)
    #pragma WEAK(_c_int00)
    
    /* SourceId : STARTUP_SourceId_001 */
    /* DesignId : STARTUP_DesignId_001 */
    /* Requirements : HL_CONQ_STARTUP_SR1 */
    void _c_int00(void)
    {
    
    /* USER CODE BEGIN (5) */
    /* USER CODE END */
    
        /* Initialize Core Registers to avoid CCM Error */
        _coreInitRegisters_();
    	
        /* Initialize Stack Pointers */
        _coreInitStackPointer_();
    
        /* Reset handler: the following instructions read from the system exception status register
         * to identify the cause of the CPU reset.
         */
        switch(getResetSource())
        {
            case POWERON_RESET:
            case DEBUG_RESET:
            case EXT_RESET:
    
    /* USER CODE BEGIN (6) */
    /* USER CODE END */
    
            /* Initialize L2RAM to avoid ECC errors right after power on */
            _memInit_();
    
    /* USER CODE BEGIN (7) */
    /* USER CODE END */
    
    /* USER CODE BEGIN (8) */
    /* USER CODE END */
    
    
    /* USER CODE BEGIN (9) */
    /* USER CODE END */
    
            /* 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_();
    
    /* USER CODE BEGIN (10) */
    /* USER CODE END */
    
            /* 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. */
            if ((esmREG->SR1[2]) != 0U)
            {
               esmGroup3Notification(esmREG,esmREG->SR1[2]);               
            }
    	
            /* Initialize System - Clock, Flash settings with Efuse self check */
            systemInit();
    
    /* USER CODE BEGIN (11) */
    /* USER CODE END */
    
            /* Enable IRQ offset via Vic controller */
            _coreEnableIrqVicOffset_();
                
            /* Initialize VIM table */
    	    vimInit();
    
    /* USER CODE BEGIN (12) */
    /* USER CODE END */
            /* Configure system response to error conditions signaled to the ESM group1 */
            /* This function can be configured from the ESM tab of HALCoGen */
            esmInit();
    
    /* USER CODE BEGIN (13) */
    /* USER CODE END */
    
            break;
    
            case OSC_FAILURE_RESET:
    /* USER CODE BEGIN (14) */
    /* USER CODE END */
            break;
    		
            case WATCHDOG_RESET:
            case WATCHDOG2_RESET:
    /* USER CODE BEGIN (15) */
    /* USER CODE END */
            break;
        
            case CPU0_RESET:
    /* USER CODE BEGIN (16) */
    /* USER CODE END */
    
    /* USER CODE BEGIN (17) */
    /* USER CODE END */
    		
    /* USER CODE BEGIN (18) */
    /* USER CODE END */
    
            /* 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_();
    		
    /* USER CODE BEGIN (19) */
    /* USER CODE END */
            break;
        
            case SW_RESET:
    /* USER CODE BEGIN (20) */
    /* USER CODE END */
            break;
        
            default:
    /* USER CODE BEGIN (21) */
    /* USER CODE END */
            break;
        }
    
    /* USER CODE BEGIN (22) */
    /* USER CODE END */
    
        _mpuInit_();
    	
    /* USER CODE BEGIN (23) */
    /* USER CODE END */
    
        _cacheEnable_();
    
    /* USER CODE BEGIN (24) */
    /* USER CODE END */
    
    
    /* USER CODE BEGIN (25) */
    /* USER CODE END */
    
            /* initialize global variable and constructors */
        __TI_auto_init();
    /* USER CODE BEGIN (26) */
    /* USER CODE END */
        
            /* call the application */
    /*SAFETYMCUSW 296 S MR:8.6 <APPROVED> "Startup code(library functions at block scope)" */
    /*SAFETYMCUSW 326 S MR:8.2 <APPROVED> "Startup code(Declaration for main in library)" */
    /*SAFETYMCUSW 60 D MR:8.8 <APPROVED> "Startup code(Declaration for main in library;Only doing an extern for the same)" */
        main();
    /* USER CODE BEGIN (27) */
    /* USER CODE END */
    /*SAFETYMCUSW 122 S MR:20.11 <APPROVED> "Startup code(exit and abort need to be present)" */
        exit(0);
    
    
    /* USER CODE BEGIN (28) */
    /* USER CODE END */
    
    }

  • Hi Jens,

    This matches the code that I ran. Can you set a breakpoint on the line 28, the "switch(getResetSource())" statement? Then you can step through the code execution from the breakpoint to make sure that all the system initialization steps are executed. The error in the c_int00 routine is that the getResetSource() function returns everything other than a power-on-reset to be an "external reset". It essentially does not distinguish between the many other causes of reset and follows the identical initialization procedure. This has already been filed as a bug in the code generated by HALCoGen and is being addressed in the next update.

    Regards,
    Sunil
  • Hi Sunil,

    getResetSource() detects and returns SW_RESET correctly, but in _c_int00, there is only a reduced initialization for the case SW_RESET. When add the SW_RESET case to the first block before _memInit_(), to run the full initialization like after a POWERON_RESET I do not get the abort any more.
    Would this be the correct way to handle a SW reset (and a watchdog reset), or are there some initializations I have to exclude after a SW reset in comparison to a POWERON_RESET?

    By the way, is there a "known bug list" or "Errara" available for HALCoGen?

    Regards,
    Jens
  • Hi Jens,

    That is different from my observation. In my case the EXT RST bit is always set for any cause of system reset (expected behavior). The get ResetSource is implemented such that it will always report EXT RST if it is not a power-on-reset. Do you see the EXT RST bit (bit 3 in SYSESR) get set at all?

    To answer your other question: no, it is not the correct way of handling a system reset caused by a watchdog or software reset. Most of the MCU gets reset (save for the debug logic) and needs to be initialized again in either of these cases.

    This has been reported before as well, and I will check with the HALCoGen team to find out what their update plans are.

    Regards,
    Sunil
  • Hi Sunil

    We have the exact same problem! But on the RM57L843 CPU.

    I find it critical that this has not yet been fixed in HalCoGen?

    Do you have sample code for a proper fix for all reset causes that we can use for the RM57L843 CPU.

    As a side note the HalCoGen software version mentioned Help->About is not updated to the installed version.

  • Hello,

    This bug has been marked as critical and will be corrected in the next update. I do not yet have a planned release date for the update though.

    As for the correct way of handling resets:

    • A power-on reset check must be first, as this can be used to clear every reset flag
    • Once it is determined that a reset has not been caused by power-on-reset, the other reset causes can be checked in order, with the check for EXTRST (bit 3) being the last
    • Special handling is required for the CPURST (bit 5) as this only really indicates a CPU reset, so that only the CPU initialization needs to be done as part of the reset handler
    • Special handling is also required for the ICSTRST (bit 7) as this indicates a reset due to an interconnect self-test check, which also resets the CPU. So you do need to reinitialize the CPU configuration after this reset.

    Hope this helps.

    Regards,

    Sunil

  • Hi Sunil,

    sorry for my late response; I was busy with some other modules...

    This is my getResetSource function, generated by HALCoGen:

    /* SourceId : SYSTEM_SourceId_008 */
    /* DesignId : SYSTEM_DesignId_008 */
    /* Requirements : HL_CONQ_SYSTEM_SR9 */
    resetSource_t getResetSource(void)
    {
        register resetSource_t rst_source;
    
        if ((SYS_EXCEPTION & (uint32)POWERON_RESET) != 0U)
        {
            /* power-on reset condition */
            rst_source = POWERON_RESET;
    
            /* Clear all exception status Flag and proceed since it's power up */
            SYS_EXCEPTION = 0x0000FFFFU;
        }
        else if ((SYS_EXCEPTION & (uint32)EXT_RESET) != 0U)
        {
            /* Reset caused due to External reset. */
            rst_source = EXT_RESET;
            SYS_EXCEPTION = (uint32)EXT_RESET;
        }
        else if ((SYS_EXCEPTION & (uint32)DEBUG_RESET) !=0U)
        {
            /* Reset caused due Debug reset request */
            rst_source = DEBUG_RESET;
            SYS_EXCEPTION = (uint32)DEBUG_RESET;
        }
        else if ((SYS_EXCEPTION & (uint32)OSC_FAILURE_RESET) != 0U)
        {
         /* Reset caused due to oscillator failure.
            Add user code here to handle oscillator failure */
            rst_source = OSC_FAILURE_RESET;
            SYS_EXCEPTION = (uint32)OSC_FAILURE_RESET;
        }
        else if ((SYS_EXCEPTION & (uint32)WATCHDOG_RESET) !=0U)
        {
            /* Reset caused due watchdog violation */
            rst_source = WATCHDOG_RESET;
            SYS_EXCEPTION = (uint32)WATCHDOG_RESET;
        }
        else if ((SYS_EXCEPTION & (uint32)WATCHDOG2_RESET) !=0U)
        {
            /* Reset caused due watchdog violation */
            rst_source = WATCHDOG2_RESET;
            SYS_EXCEPTION = (uint32)WATCHDOG2_RESET;
        }
        else if ((SYS_EXCEPTION & (uint32)CPU0_RESET) !=0U)
        {
            /* Reset caused due to CPU0 reset.
            CPU reset can be caused by CPU self-test completion, or
            by toggling the "CPU RESET" bit of the CPU Reset Control Register. */
            rst_source = CPU0_RESET;
            SYS_EXCEPTION = (uint32)CPU0_RESET;
        }
        else if ((SYS_EXCEPTION & (uint32)SW_RESET) != 0U)
        {
            /* Reset caused due to software reset. */
            rst_source = SW_RESET;
            SYS_EXCEPTION = (uint32)SW_RESET;
        }
        else
        {
            /* No_reset occured. */
            rst_source = NO_RESET;
        }
    
        return rst_source;
    }

    The reset causes SW_RESET (0x0010), WATCHDOG_RESET (0x2000) and EXT_RESET (0x0008) are detected and returned correctly by getResetSource. But, the switch in _c_int00 seems to do the wrong initializations in case of SW_RESET and WATCHDOG_RESET.

    If I put SW_RESET and WATCHDOG_RESET at the top of the switch  in _c_int00, it seems to work:

            case POWERON_RESET:
            case DEBUG_RESET:
            case EXT_RESET:
    
    /* USER CODE BEGIN (6) */
            case SW_RESET: //test only
            case WATCHDOG_RESET: //test only
    /* USER CODE END */

    So there is only the question for me, what would be the correct code for _c_int00.

    Regards,

    Jens

  • Hi Jens,

    The getResetSource() function needs to be corrected. The check for the EXTRST:

    else if ((SYS_EXCEPTION & (uint32)EXT_RESET) != 0U)
    {
    /* Reset caused due to External reset. */
    rst_source = EXT_RESET;
    SYS_EXCEPTION = (uint32)EXT_RESET;
    }

    must be the last reset condition to be checked, just above the "No reset occurred" condition.

    The issue is that the EXTRST bit gets set for every single cause of a system reset. This prevents the original getResetSource() from being able to correctly identify the actual reset cause as it will always return EXTRST if the actual reset is not a power-on reset.

    Regards,
    Sunil
  • Hi Sunil,

    I think we are talking about two different problems. I changed the getResetSource function as you described, but the EXT_RESET bit is never set when the function is entered. The function always returns the right reset source. It does not always return EXT_RESET as you assumed.

    So when I do a software reset, getResetSource returns SW_RESET correctly. Then in _c_int00, all the initializations in the switch are skipped for the case SW_RESET, and my application crashes. When I just put the case SW_RESET at the top of the switch, it seems to work, but I'm not sure, if this is the right way do do this.

    Regards,

    Jens

  • Hi Jens,

    I agree that we are talking about two separate issues, but related ones. What is connected to the nRST pin in your system? Do you see the nRST pin driven low whenever you cause a software reset or a watchdog reset? The functionality of nRST terminal is that it gets driven low for indicating all causes of system reset on-chip, regardless of whether they are internally generated or if the nRST is driven low externally. This makes (should) the EXTRST bit get set for every cause of system reset.

    Now, to address your specific issue - for all causes of system reset the same system initialization sequence is required. So you should put the other system reset causes (OSC_FAILURE_RESET, WATCHDOG_RESET, WATCHDOG2_RESET, SW_RESET) also on top of EXT_RESET.

    I will work on a "suggested reset handler" and post it when it is ready (could be next week).

    Regards,
    Sunil
  • Hi Sunil,
    I'm using the HDK at the moment, without any modification of the reset circuit. I checked the nRST pin with a scope; is not driven low when I cause a SW- or watchdog reset. nRST is only driven low when press the S3 button (signal WARM_RSTn). The reset triggered by the S3 button is detected as EXT_RESET (0x0008).
    So I will patch the initialzation sequence for the short term and double-check it again when your suggested reset handler is ready.
    Thanks and regards,
    Jens
  • Hi Jens,

    The suggested reset handler will be part of the HALCoGen update that is planned for July 2018.

    I will mark this post as resolved and close it. Please feel free to post any questions you may have.

    Regards,
    Sunil