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.

Continuous Reset issue

Expert 1175 points
Other Parts Discussed in Thread: MSP430F5418

Hello everybody,

I am using msp430f5418 with IAR. My problem is when I run the program it keep on resetting.

I don't know what is the reason. but by several observations I found that when I have small amount constant data, the program works fine.

The below is the linker output summery of my program

43 224 bytes of CODE memory

14 211 bytes of DATA memory (+ 68 absolute )

15 784 bytes of CONST memory

Is it because of the flash access error??

does the linker settings file editing can fix the issue?

 

Thank you

  • The msp430f5418 device has two FLASH program sections.

    FLASH origin=0x5c00 length=0xa380

    FLASH2 origin=0x10000 length=0x15c00

    The length of the first section(41856) is smaller than your "43 224 bytes of CODE memory"

    To use both sections  you have to compile the program using "large memory model". Be sure to use the "PLACE_INTERRUPT( )" pragma to place the interrupt vectors in the upper memory. I do use the same device here with the "Code Composer" so the pragma can differ from IAR.

     

    Niki

  • Hari,

    could it be the watchdog which reset your application? What exactly do you mean with the constant data? Is it variables with const qualifier or it is just variables initialized with constant expression?

    In the case if you have a lot of global or static variables initialized with constant expressions, it can be happenning that the initialization of these data takes too much time before the first intruction of your main code which is usually turning of the watchod timer. More information about this can be found in SLAA294 "MSP430 Software Coding Techniques" document (http://focus.ti.com/lit/an/slaa294a/slaa294a.pdf) chapter 3.6 "Using a Low-Level Initialization Function".

    Hope this helps

  • Older MSPs had a problem with the watchdog timer when the amount of initialized data was too large. Before starting a program, the automatically generated startup code will copy th einitialization data for all global or static variables from flash to ram and clear the area for the uninitialized ones (well, CCS skips the clear stage). This consumes some time, and on older MSPs, this time could grow longer than the watchdog timeout. Since you (normally, but there are some tweaks)  can deactivate the WDT only at start of your main code, this was too late to prevent a reset.
    On the 54xx series, however, the default WDT interval size is large enough to not trigger while the startup code is working.

    In your case, I suspect something different:

    your code memory and the constant memory are larger than the flash area below 64k. This is normally not a problem. The compiler/linker will take care of it and move code into the area above 64k (if activated).

    For constants, however, this introduces a serious problem: If the constant is placed above 64k, it's address won't fit into a 16 bit variable/register anymore. During normal code execution, again, the linker/compiler take care of it. But when you pass the pointer to this constant to a function, it needs to be passed as a LONG INT (32 bit) or the upper most bit of the address is lost. Also, the receiving function needs to know that it is a long (4 byte) pointer.

    Some function, such as fprinf(), expect only 16 bit (int) pointers. If passed a 32 bit value, they will take the first 16 bit and leave the rest on the stack where it is interpreted as the next parameter. This can lead to all kind of crashes that finally reset your system.

    Often, the constant data is bundled with the function in which it is used. So depending on the accumulated size, it may be that all funcitons with attached constants fit into the lower 64k.

    What you can do is to declare all strings as constants instead of just using them as strings wher you need them. This will group them together and will allow the linker to place them 'on the bottom' instead of having them tied to the functions.

    e.g.:use

    const char mytext[]="my text";
    ...
    printf(mytext);

    instead of

    printf("my text");

     

  • Hari,

    I have yet another theory.

    14 211 bytes of DATA memory

    Sounds like quite a lot for a device that has only 16KB of RAM.

    Maybe you are experiencing stack overflow?

    No matter what the cause of your trouble, the first step is probably to determine the cause of the reset using the reset interrupt vector SYSRSTIV.  Be sure to write to this register before kicking off your application.  Writing any value to SYSRSTIV clears all causes of prior resets.  This step ensures the next reset can be diagnosed.

    Jeff

  • Hai,

    Thank you for your answer.

    But I disabled the watch dog from the start-up code itself  (in cstartup.s43).

  • Hai, Thank you for your answer, I observed the SYSRSTIV value after reset. It shows 0x001E. In the user guide the explanation given for this is 'PERF peripheral/configuration area fetch (PUC)'. What does this mean? I looked at http://e2e.ti.com/support/microcontrollers/msp43016-bit_ultra-low_power_mcus/f/166/p/63350/227881.aspx about the same problem, They are saying that it is the problem with non initialized pointers. I have a function to delay one ms using semaphores. I Debug the program and found that the reset is occurred when I try to acquire a semaphore at the second time. Is it a problem with the stack or pointers??
  • Hai,

    Thank you for your answer,
    When I compile with large data model, The continuous reset is stopped, but the program is stuck. The control goes to 0x0000

    Why is it so??

  • Hai JMG,

    Thank you for your answer.

    I have an array of strings. so I pass the items with the array name.

    The other suggestion, pass strings as long pointers, I understood like this,

    long int a[][] = {

    "hello",

    "world"

    };

    main ()

    {

    fn1(a[0])

    }

    void fn1 ( long int * x )

    {


    }

     

    Is this what you meant?

  • Hari,

    One way to check for stack overflow is to put up a "fence".

    MOV.W   #0xBEEF, (SFE(DATA16_N)+1)&~1

    You may have to change "DATA16_N" to be the DATA segment listed last in your linker command file. If you need help, have IAR generate a linker map file for the forum so we can look at it.  IAR can generate this file during the build process.

    Anyway, put a breakpoint on this instruction.  Then after the undesirable reset, use the debugger to inspect the address where this instruction would write.  The memory should still contain 0xBEEF.  If it doesn't, you know you had stack overflow.

    You can use 0xF00D or 0xBEEF or 0xCAFE or any other food-related value.  ;-)

    Jeff

     

  • Hai Jeff,

    I got an invalid syntax error for MOV.W   #0xBEEF, (SFE(DATA16_N)+1)&~1.

    I don't know what to do with the DATA16_N in the linker command file.

    The links for linker command file and map file are given below.

    please find it.

    http://e2e.ti.com/cfs-file.ashx/__key/CommunityServer-Components-UserFiles/00-00-05-17-16/lnk430F5418.txt

    http://e2e.ti.com/cfs-file.ashx/__key/CommunityServer-Components-UserFiles/00-00-05-17-16/ui_5F00_sm.html

     


    Thank you

    Hari

     


  • Hari,

    I'm guessing you didn't declare this segment in your assembly language file.  Put:

    RSEG   DATA16_N

    before any of the code in that assembly language file.

    And looking at your map file, you could use DATA16_Z just as well.  Both segments end at the same location (currently 0x51C4 inclusive).  So the constant "0xBEEF" will go to 0x51C6 with your code the way it currently is.

    Jeff

  • Hari said:
    The other suggestion, pass strings as long pointers, I understood like this [...]

    It's not that easy. A long int * is a 16 bit pointer to a long int and not a 32 bit pointer of an int.
    The size of a pointer is defined by the compiler and not the code. If the compiler supports 32 bit pointers, it does so without any change in the source code. You cannot 'generate' a long pointer / far pointer /32bit pointer (however you may name it) manually in C. The C language assumes that a pointer is large enough to hold the address. period. Unfortunately it isn't automatically so bu tthe compiler needs to support this. And maybe it needs to be configured properly. (' use large data model' or similar). Back in 286 times, the 16 bit C ++compiler for teh PC had similar problems. There you had to choose the memory model so it would run on 64k codeü64k data or 64k code and 1MB data or 1MB code and 64k data or 1MB for code and data. You didn't change the code, only the compiler settings decided whether it works or not.

    And then there is code that uses (through inline assembly, or direct access to stack parameters) . So if the compiler uses 32 bit pointers, those functions needs to know this, so they pull a 32 bit value form stack and not just 16 bit, and then use the extended instructions (with 20 bit address space) rather than the normal ones with 16 bit address range.

    This is a rather complex problem and one of the reasons why it is still recommended for the MSPGCC4 compiler to restrict the data to the lower 64k (there is a compiler/linker setting for that).

    Jeff Tenney said:
    And looking at your map file, you could use DATA16_Z just as well.  Both segments end at the same location (currently 0x51C4 inclusive).  So the constant "0xBEEF" will go to 0x51C6 with your code the way it currently is.

    From the name, I'd guess that this data segment is for zeroed data, so it will not be filled with any guard value if you explicitely but your constant into it. Probably the linker will complain, but maybe not.
    It would work if you assign this guard value manually at the start of main rathern than assigning it in the variable definition.

  • Hari said:
    I observed the SYSRSTIV value after reset. It shows 0x001E. In the user guide the explanation given for this is 'PERF peripheral/configuration area fetch (PUC)'. What does this mean?

    A PERF can happen because of many things, including uninitialized pointers or stack overflow. What this basically means is that the CPU core has tried to execute code (fetch an instruction for execution) from the peripheral or configuraiton area. This causes a PUC (power-up-condition, almost a full reset, but not completely - not all hardware is reset: timers and SVS aren't).

    Executing code is only allowed from ram or main flash. If the PC (program counter) somehow gets set to an address that does not belong to ram or main flash, either a PERF is triggered (if the address was peripheral area or configuration/info flash) or a vacant memory access is triggered (when the address did not point to anything).

    So somehow your PC gets corrupted. Maybe it is returning from a function but it wasn't the return address on the top of the stack (happened a lot to me until I got my task switcher working properly). If inside of assembly code something is pushed to the stack but not popped afterwards, the left value is taken as return address. It may happen when mixing MSP430 and MSP430X code (e.g. form a precompiled library that is linked-in). MSP430X code pushes a 32 bit return address (4 bytes) on the stack. but if the called function only uses MSP430 code, it will fetch only 16 bit from the stack when returning. When the callign function was in the lower 64k, this does not do harm immediately. But now there are two '0' bytes on top of stack which are not expected to be there. Maybe what's expected is the return address for the function hat called the faulty function. And then the return will feth the wrong return address from the stack and return to a completely wrong address whose lower 16 bit are 0. So the PC is set to 0 and tries to fetch the next isntruction from the peripheral area, causing a PERF.

**Attention** This is a public forum