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.

CC1352R: Getting IMPRECISERR exception, but not always

Part Number: CC1352R
Other Parts Discussed in Thread: ALLIGATOR

Hello,

I have a C++ program with a bunch of global objects. So their constructor is called even before main is started (which is ok). But now I get in the first constructor already a IMPRECISERR exception. When I try to find the root cause and step through the startup the error is not coming.

I use a own exception handler function by giving m3Hwi.excHandlerFunc = "&myExceptionHandler"; in my project.cfg file. And there I see by checking the CFSR Register (Bits) that a Imprecise Error happened.

What I found by looking for more information that this error tells something like "something else went wrong". I have no idea why I get this exception! What could be the reason for this? It's even strange that everything works when I set a breakpoint in my first constructor and then step through the program.

Generally this looks like timing problems but I use only processor internal stuff (even each SW designer tells this :-) ). It's the first time that we use an TI ARM processor. So there might be something I do even "this should not be done". I have to say with Code Composer and TI Processor I see items that I wouldn't expect for a modern/actual development environment. I see (compiler) errors in the Problems tab even the Console, where the build output is shown, doesn't show no problem. But this errors can be deleted in the Problems tab (else there is a warning when trying to start debugging). And this is not the main problem as this "wrong compiler error" also comes only from time to time. More important is that my program works.

Regards
Erwin

  • Some additional information: when I start the debugger and let it run I got the exception (BTW: I don't use C++ exceptions, just to make it clear) very eary (while I configure the timer through HWREG(xyz) = abc where xyz and abc are all defines from compiler include files.

    If I do then a restart in the debugger window, everything works correct.

    What is even more strange: when I switch power off and on of myhardware, nothing works. I don't get the LED signs in my exception handler nor the LED signs that the program was startet. Disconnect the debugger from the hardware and doing then a power cycle also doesn't show anything. So what is the difference when I run with debugger and when without?

    Very strange things with the strange processor and strange develop environment.

    Erwin

  • Hi Eirik,

    I have found and solved the problem. As written I do the stuff in the first constructor. After doing the basic HW initialisation by, beneath others, doing PRCM settings, I have to wait some time. I inserted

       for(uint32_t i = 0; i < 0xFF; i++)
            asm(" nop");

    before continuing. And then it works.

    Without that I got even more strange things. I was not able to connect the debugger anymore ob more precises I guess the JTAG connection for debugging does not work anymore after PRCM initialization. Stepping through the code leads me also to the situation that code composer tells me main() could not be located. So with assembler debugging I saw that the code was executed but the editor looked for a file with a strange name, including main but other numbers also.

    According the stack: If I use more stack memory as I've assigned in the linker file (STACK_SIZE) I have no problem as long as I don't overwrite addresses used for other variables, right? As my functionality is the first constructor it's ok to use more stack memory then in the remaining of the program. After my constructor is done, the stack pointer is again at the normal/high address. Or is there a problem, check somewhere (implemented) which I overlook?

    Would be great to get an answer for my stack question even I mark the issue with this reply already as resolved.

    Erwin

  • Hi Erwin,

    Could you share your HWREG code that seem to trigger your issue initially (all code from the start of the object construction to failure if possible). I suspect it could have to do with power domains etc. Have you taken care of all of this? 

    Also, note that if you do your own "drivers" based on the HWREG level and then start TI-RTOS, the Power driver would kick in and you could end up in a situation where it turns a domain of that you personally expects to be on. To mitigate this, you would need to inform the power driver post init which peripherals you depend on and if these allow for standby or not (the timer for example does not).

    Also, could you share the exception dump as well?

    https://interrupt.memfault.com/blog/cortex-m-fault-debug#how-to-debug-a-hardfault-on-an-arm-cortex-m-mcu

  • As for the stack part, I guess you could think of it like that if you put it simple. As long as nothing is left on the stack in form of variables that never go out of scope, that should be the case. 

  • Thanks for the hint with TI-RTOS. We will think about it.

    As written, with the delay the code works now. But just when I step out of my constructor I see

    No source available for "__sti___8_main_cpp_ea6eb735() at X:/Alligator\cpp\BlueAccess-Beschlag\Release\BlueAccess-Beschlag.out:{3} 0x34cc{4}"

    Why doesn't the debugger find the right source code or what is this for a strange name?

    If I set an additional breakpoint in my main function, the debugger stops there. But no breakpoint can be set in the constructors above main.

    To illustrate my main.cpp looks in principle

    #include "a.h"
    #include "b.h"

    a Ainstance;  //this calls the constructor of a
    b Ainstance;  //this calls the constructor of b

    main()
    {
       a.doSomeStuff()
    }

    I can work with this situation, just would like to understand why this is not possible. Could it be because the constructor are all called from the table_init function of C++ environment and therefore not from my main.cpp?

  • It could be, to be honest I'm not to familiar with the TI ARM C++ behavior as I mainly focus on C only. I would still expect you to be able to set breakpoints as long as there is actually a PC hit in the constructor as such.

    I would suggest you take the C++ specific part in another thread and tag it for TI C/C++ compiler, hopefully someone on that team can give you a better explanation to the behavior :)

    As for the PRCM part, it sounds like you were missing the equivilient of PRCMLoadGet() in our C library? 

    dev.ti.com/.../group__prcm__api.html

  • No, I do HWREG(PRCM_BASE + PRCM_O_CLKLOADCTL) = PRCM_CLKLOADCTL_LOAD;

    But after that a delay is required (my 255 nops). Without that I got this strange behaviour. A coleque of my told it to me (and this is in another project also done) with the note that this is required, even not so clearly documented. I also doesn't find any hint in the data sheet.

  • Just one question about TI-RTOS (instead of reading a lot of pages).

    As you mentioned TI-RTOS does also the intialization of the processor. But at which point in time at startup is this done? I would need this be done already before my static class constructors are called. Or with c-programms, before main starts or even before the global variables are initialized.

    Regards
    Erwin

  • Hi Erwin,

    It would be interesting to know just what PRCM access you do, there should be no need to do anything other than "PRCMLoadSet()" and "while(!PRCMLoadGet())" for the PRCM part to settle. Could you possibly share the code section in question?

    Your "255 nops" is more or less ~2 RTC tics so either there is a AON dependent operation done and you need to wait for AON sync or there is something else going on. 

    As for TI-RTOS, there is only really "TI-RTOS" initialization done at the point where you call BIOS_start(). This include internal objects and interrupts, that is about it.

    As for anything happening before "main", that is toolchain dependent so the exact "how" varies based on you using for example TI ARM compiler or GCC. Typically, you could find a "startup.c" file in the SDK (source/ti/devices/<the device family>/startup) that shows how the ResetISR looks. In the case of TI ARM, it is typically part of __cinit11 or something like that called from this ISR. This is for the "C" case but I would assume the C++ is similar, just with another "__cinit11****" function (which could be the "strange symbol name" that you were confused about earlier). The end of these "_cinit***" functions would jump you back into main. 

    The actual implementation of this you should be able to find by digging around the XDC/Compiler directory (I need to jump the forums for now so don't have time to track the file behind it down for you, but it is part of the libraries pulled in by the toolchain).