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.

RM46L852: Generated code in sys_startup.c prevents us to know system reset.

Part Number: RM46L852

Hi,

I want my application to know the cause last reset.
For example, to detect a Power-On-Reset I wanted to use the PORST bit in the systemREG1->SYSESR register.

The problem is that, for some reason, PORST is reset by the initialization code in the sys_startup.c.

    /* check for power-on reset condition */
    /*SAFETYMCUSW 139 S MR:13.7 <APPROVED> "Hardware status bit read check" */
    if ((SYS_EXCEPTION & POWERON_RESET) != 0U)
    {		
/* USER CODE BEGIN (12) */
/* USER CODE END */
        /* Add condition to check whether PLL can be started successfully */
        if (_errata_SSWF021_45_both_plls(PLL_RETRIES) != 0U)
        {
            /* Put system in a safe state */
			handlePLLLockFail();
        }
        /* clear all reset status flags */
        SYS_EXCEPTION = 0xFFFFU;

/* USER CODE BEGIN (13) */
/* USER CODE END */
/* USER CODE BEGIN (14) */
/* USER CODE END */
/* USER CODE BEGIN (15) */
/* USER CODE END */
      /* continue with normal start-up sequence */
    }

When commenting the line with SYS_EXCEPTION = 0xFFFFU, I suddenly have access to the POR bit on the SYSESR register.

My questions:
- Why is SYS_EXCEPTION  cleared in sys_startup?
- Is it safe to delete the lines that reset SYS_EXCEPTION in sys_startup ?
- Is there a better way to get the reset cause?

Best Regards,
Gabriel

  • Hi Gabriel,

    - Why is SYS_EXCEPTION  cleared in sys_startup?

    Previous reset source status bits in SYSESR register are not automatically cleared if new resets occur. After reading this register, the software should clear any flags that are set so that the source of future resets can be determined. 

    - Is it safe to delete the lines that reset SYS_EXCEPTION in sys_startup ?

    It is not safe to delete it.

    - Is there a better way to get the reset cause?

    Use FEE for Bank7 to store the reset cause.

    (9) TMS570LS3137: TMS570LS3137: Using SYSESR and RTIWDSTATUS after startup - Arm-based microcontrollers forum - Arm-based microcontrollers - TI E2E support forums

    (9) TMS570LS3137: SYSESR Register is not working as intended while observing reset source in debug mode - Arm-based microcontrollers forum - Arm-based microcontrollers - TI E2E support forums

    --

    Thanks & regards,
    Jagadish.

  • Hi Jagadish,

    Thanks for your answers.

    Use FEE for Bank7 to store the reset cause.

    Even after reading the linked threads, I'm not sure how to proceed.

    If I understood properly: because the memory init will clear the registers containing the reset information, we need to save those registers in the MCU non-volatile-memory using FEE.

    If I'm correct,

    - In what part of the code would you suggest I insert this code? After _coreEnableEventBusExport_() ?
    - Should I only save SYSESR? There was mention of "check watchdog violation" in the first thread.
    - Do we need to clear the register after reading them?
    - What about Flash wear? 

    Best regards,
    Gabriel

  • Hi Gabriel,

    Actually, i tried writing to the FEE memory but that method is also not working.

    After analyzing code i found below working method to preserve the reset source 

    1. First i declared one variable in main.c called "App_Rst_Src" which will give reset source value to the application,

    2. I extern this variable into the startup.c 

    3. Now i declare another variable with register type in _c_int00 function, this register type variable is required because normal global variables will get initialized in the memory initialization functions but if we declare it as a register then variable value stored in register, so value won't get lost.

    4. Actually, what i want to do is, i just want to copy the SYS_EXCEPTION value into this register variable first and again i want to copy this register value into the "App_Rst_Src" before i exit to the main function.

    But i faced one problem in doing this process, that is the register allocated for the rstSrc variable is again using in some assembly program, so again the above method failing. So, i did little modification for above method i.e. after copying into the register variable i just also want to copy it to the another register which is not used by later program, so that my value get preserve and after that i want to move it into the final application variable called App_Rst_Src.

    5. I copied the SYS_EXCEPTION  into the register variable called rstSrc which is using R12 register here, but as i told you this register is using later assembly program so i again copied that R12 value into R9 which is not using in the assembly program.

    6. And before calling the main function i am copying that R9 register value to the R12 which is rstSrc variable and from this variable i am copying to our main application variable called App_Rst_Src

    7. In Main function i am printing this variable value

    I am attaching my example project here please go through it

    Passing_System_Reset_to_Application_RM46.zip

    Startup code fixed right so there is no chance of this R9 register will affect in the future and also i tried with different optimization levels and still code is working properly. I hope this project would be helpful.

    --

    Thanks & regards,
    Jagadish.

  • Thanks for the reply Jagadish.
    I really appreciate your effort.

    The idea of storing the value in a unused register is very interesting.
    I did not think about that.
    It's a bit fragile, but as you mentioned, if the startup code doesn't change there won't be a problem.

    I will test this solution on end today.


    Actually, i tried writing to the FEE memory but that method is also not working.

    That's surprising. Do you understand why this would be the case?
    I was planning on using FEE for my project.

    Thanks again for your hard work, 
    Gabriel 

  • Hi Gabriel,

    That's surprising. Do you understand why this would be the case?
    I was planning on using FEE for my project.

    If i call the FAPI related functions after __TI_auto_init function i am not getting any issue and i can successfully able to write into the flash but if i call it just right before this function i am unable to erase or write into the sectors. 

    What i am thinking is this __TI_auto_init function will initialize the global variables stored in bss section right, so if our FAPI library might uses initialized global variables so due to that our functions are not working. This is the reason i followed unused register method.

    --

    Thanks & regards,
    Jagadish.

  • Good news: the R9 strategy seems to be working!

    That said, I noticed a weird behaviour: the watchdog bit is always set.
    When I do a software reset, the App_Rst_Src is set to 0x2008. 

    Do you also have the watchdog set at all times?
    Is there something more to do so the  System Test Abort Status Register (SYSTASR) behaves properly?

    Not sure if it's helpful, but in another thread, mentioned something that might be helpful: 

    > Previous reset source status bits in SYSESR register are not automatically cleared if new resets occur. After reading this register, the software should clear any flags that are set so that the source of future resets can be determined. 



    Also, so I better understand your solution, how did you know that the rstSrc variable would be stored in the R12 register?

    register uint32_t rstSrc;
    rstSrc = (uint16_t)SYS_EXCEPTION;
    

    Best,
    Gabriel

  • Hi Gabriel,

    That said, I noticed a weird behaviour: the watchdog bit is always set.
    When I do a software reset, the App_Rst_Src is set to 0x2008. 
    Do you also have the watchdog set at all times?

    Let me verify that.

    > Previous reset source status bits in SYSESR register are not automatically cleared if new resets occur. After reading this register, the software should clear any flags that are set so that the source of future resets can be determined. 

    Yeah, it is correct, but here we are copying the SYSESR before they are clearing the bits. If any new reset occurrs the rstSrc variable again will get updated with new SYSESR value.

    Also, so I better understand your solution, how did you know that the rstSrc variable would be stored in the R12 register?

    Actually after declaring variable i verifed in debug mode which register it gets assigned, and later i used that register. According to my initial approach i really don't want to know the register, i just want to copy the value stored in rstsrc to the App_Rst_Src variable but unfortuanately the register assigned to the rstsrc getting corrupt so i changed copied that value again to some other register.

    --

    Thanks & regards,
    Jagadish.

  • Let me verify that.

    Good looking forward to seeing your results.

    Actually after declaring variable i verifed in debug mode which register it gets assigned, and later i used that register

    Do you think it could be possible to make the variable loading explicit? 
    That way it would be future-proof (nothing worst than having a compiler update break your code)


    Something like this? (not sure how it works)


    const unsigned int test = 0x10000;
    
    __asm__ volatile ("MOV R10, %[input]"
        : // no C variable outputs
        : [input] "r" (test)
        : "R10"      // tell the compiler R10 is modified
          );

    Best regards,
    Gabriel

  • Hi Gabriel,

    Do you also have the watchdog set at all times?

    Actually, it is not due to watchdog reset, if we see TRM

    It is due to ICEPICK reset caused due to debugging.

    In code also, if watchdog reset flag set then they are again verifying WATCHDOG_STATUS register to confirm whether it is really due to watchdog or not. If it is not due to watchdog then they are confirming this reset cause as ICEPICK_RESET.

    --

    Thanks & regards,
    Jagadish.

  • It looks like it's working! 
    Using WATCHDOG_STATUS we can differentiate between watchdog and jtag reset.

    The final step is to make the R12 loading explicit (to ensure this solution is future-proof).
    Do you know a way to load a C variable in a register?

    This won't compile:

    const unsigned int test = 0x10000;
    
    __asm__ volatile ("MOV R10, %[input]"
        : // no C variable outputs
        : [input] "r" (test)
        : "R10"      // tell the compiler R10 is modified
          );


    Regards,
    Gabriel

  • Hi Gabriel,

    Using WATCHDOG_STATUS we can differentiate between watchdog and jtag reset.

    Good to hear.

    Do you know a way to load a C variable in a register?

    I tried different methods but none of them worked to load variable value to the register, that is why i stick to the method i shared.

    --

    Thanks & regards,
    Jagadish.