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.

Call to SysCtlResetCauseGet ends up in FaultISR

Other Parts Discussed in Thread: TM4C123BE6PZ

I am working with TM4C123BE6PZ, CCS 5.5, Tivaware 2.1.

I compile code with a call to SysCtlResetCauseGet and when I start to debug using a Spectrum Digital XDS560v2STM, I immediately end up in the FaultISR.  I do not even hit a break point.  I remove the call, restart debugging and hit the first breakpoint possible in the code.

Why is a call to this function getting me into the FaultISR?

NVIC_FAULT_STAT has 'bus fault addr register valid' and 'precise data buss error' set.

A call to the ROM_ version ends up in the same place.  Looking at the register seems indicates the exact cause of reset.

This substitution does not work either:

UINT32 swReset = HWREG(SYSCTL_RESC);//SysCtlResetCauseGet();

  • Few here will accuse J.O. of "boring us" with quick/easy issues.  And - of course - none in my small group have made that call.  (or will admit - publicly - to so doing)

    So - long experience, "in the MCU trenches" is our ploy.

    Might you call this function too soon - or at an inopportune place/time?  I'd start there.

    Then - if those are eliminated - might you try, "SysCtlResetCauseClear()" - and then insert a delay - and only then call your (currently) failing function.  Should this surprise us (and work) it may indicate a sensitivity to an "overload" of, "SysCtlResetCauseGet()" which is released via this (or a similar) function sequence.  (this surely a SWAG - yet these have worked w/other ARM MCUs - although we cannot recall ever targeting this exact event)

    When all else fails you may wish to review the source code for, "SysCtlResetCauseGet()" and then examining each/every pertinent register - prior to and then after - deliberately induced resets.  (gold - sometimes - in thar hills...)

  • Thanks.  Your advise unfortunately did not lead anywhere, but got me off of looking at the same thing.

    I changed the function call to SysCtlFlashSizeGet/SystCtlSRAMSizeGet and had the same problem.  Then your response prompted me to look at the function, which was simply:

    uint32_t
    SysCtlResetCauseGet(void)
    {
        //
        // Return the reset reasons.
        //
        return(HWREG(SYSCTL_RESC));
    }

    Which is exactly the call I put in by hand.  SYSCTL_RESC is defined in only one spot. 

    Then I started to think...  The problem is on my bootloaders.  The same exact function call works flawlessly in my applications.  The first difference I guessed at was optimization level.  So I moved the optimization level to 'blank' on the bootloader as was the application's opt level and behold, it works.  Further investigation yields with opt level at blank or off, the call does not send the app to FaultISR.  With opt level of 1, it does.

    So with a fevered mind, I create a simple main() function and tried the same thing.  It always works.  The difference is that for my bootloader, the calling function is in the main() with opt level == 1, and the called function is in a library with opt level 1.  In my application both calling function and called function are in the application project with no part of the call sequence found in a library.

    I am concluding that I have found a linker bug.

    I will try a few more things.  The opt level change option is not preferred, as we want to have head room on the first release and this lessens it.

    Does this input add any insight?

  • Another couple of suggestions. SysCtlResetCauseGet is often called fairly quickly after reset.  Often before the debugging hardware can actually gain control of the micro. That being the case you can find yourself you can find yourself heading down blind dark alleys attempting to read the map. The noises you hear may not be rats. You need to get a little light on the situation.

    Approach 1: move the call to SysCtlCauseGet to after you gain control of the micro. Go stand under a streetlamp.

    Approach 2: Send progress information out a serial port.  SWO has the same problems as the debugger so it may not be useful here.  Get a flashlight

    Approach 3: Bit toggle.  Toggle an output (or outputs) to show how far you've progressed into the init. I've used this when for some reason the other approaches have not been feasible.  Even a penlight is potentially helpful.

    You may find that it is not the system call that is the immediate cause of the lock but rather it is disturbing some element of the initialization that then causes the problem or it simply reveals a problem that was lying in wait for an opportune moment to pounce. Or you may find you need to do more setup to support the call. And yes, I've had cases like that.

     

    Robert

  • cb1- said:
    Might you call this function too soon - or at an inopportune place/time?  I'd start there.

    Appears poster Robert - and I earlier - have identified much the same point.  (which you characterize {unkindly} as, "Leading nowhere!)  That may not be best/brightest assessment - especially as two here have now seized upon just that issue! 

    Your use of bootloader - undisclosed earlier - adds a layer of complexity & often obscures "real" issues.  Our preference is to insure that all code runs properly/completely - and only then add in a bootloader...

    You may wish to acquire (& read), "basic diplomacy" text.  Robert's streetlight, flashlight or penlight may well illuminate...

  • Robert,

    I had previously, without change code, cycled through the "delete .out -> change opt level -> build -> debug" cycle several times to confirm that the defect was following the opt level and not the code.  It was following the opt level, hence, my last post.

    I have now repeated that cycle, and on the project in question, reverting to the last release tag cannot even resurrect correct behavior.

    So the new simple main() project works, I switched to a sibling project and it works.  I will next try to blow away all .metadata to see what happens.  Yesterday I recall CSS aborting abnormally and sending an email to TI.  I will see if this works.

    So now I am not suspecting the linker.

  • As cb1 says, the bootloader adds significantly to the problem description.

     

    As for this being a linker bug.  Given the description of the problem and the simplicity of the code I'd be reluctant to ascribe it to either linker or optimizer.  Optimizer's can get fooled, particularly by HW access, but separation by a link usually improves the situation in that case.

    My first step would still be to make sure that the code you think is failing is the code that is actually failing. Then you can determine what address is causing the issue (if you haven't figured out the cause by reflection by time you get that far).

    Yes, it could be the tools, but the first rule in these situations is the the compiler is right until you can prove otherwise.

    Robert

  • John Osen said:
    I compile code with a call to SysCtlResetCauseGet and when I start to debug using a Spectrum Digital XDS560v2STM, I immediately end up in the FaultISR.

    It may be worth under CCS Project Properties -> Debug -> Flash Settings enabling "Reset target during program load to Flash memory" - this has solved some strange debugging issues as detailed in http://e2e.ti.com/support/development_tools/code_composer_studio/f/81/p/338495/1183218.aspx#1183218

  • John Osen said:
    I do not even hit a break point. 

    If the processor is suspected to be crashing in the C run-time library code before the first application breakpoint is reached, under CCS Project Properties -> Debug -> Auto Run and Launch Options -> Auto Run Options untick "On a Program load or restart" and "On a reset".

    Then, when a debug session is started the processor will be halted at the reset vector and you can try single stepping the start-up code to see at what point the failure occurs.

  • With hat in hand, I must report what is the problem.  Thankfully, it was in my code and my code did as it was supposed to do... 

    Usually, during development, we do not memory protect any flash blocks.  The targets in question were those being tested for delivery.  We have an approach that the bootloader will memory protect its own blocks if a 'fuse' is blown in another area of flash - the area in which the device manufacturer puts its build information.

    So the boards in question had this 'fuse' blown.  But when I went into emulation, the emulator does not know this and just erases flash, then writes flash.  But apparently there is no blank check in between.  So I was slowly building up a ORed combination of bits.

    In the end, with no break points defined, I was breaking somewhere in the Tiva library.

    After many gratefully received suggestions, I just sat down like Pooh Bear and said "Think, think, think..."  What ever was happening must be happening in the init code executed prior to main() (a suggestion above prompted this thought).  I suspect in the end the address stored at 0x00000004 was corrupted and execution just started somewhere, probably where memory does not exist.

    Once corrupted by emulation, our service tool could not ask the bootloader if its fuse was blown.  Once memory was corrupted, then power cycling outside of emulation would reference an invalid memory location or instruction, jump to the FaultISR address, which to begin with was not corrupted, but with each emulation attempt, became corrupted and execution ended up somewhere.

    Thanks for the suggestions.