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.

MSP430 will not hold the WDT during pre-main



My system initializes large array and the WDT times out, so it never gets to the main().  I have a non-trivial union constructor:

union TSample {
    uint8_t ui8[2];
    uint16_t ui16;

    TSample() {}  // usefull for array init

    TSample(uint16_t val, uint16_t exponent) {
        ui16 = (val << 4) & 0xFFE0;
        ui16 |= exponent & 0x1F;
    }
}

When the union is initialized the WDTHOLD is low.  I tried the following to keep it high:

   I tried a couple of thing:

1) Per section 4.3.5 set the --cinit_hold_wdt=on.  This had no affect on the system.  During the startup the WDTHOLD remains low.  This results in following linking command:

Building target: hw_1_5.out
Invoking: MSP430 Linker
"/home/sporty/ti/ccsv6/tools/compiler/msp430_15.12.2.LTS/bin/cl430" -vmspx --data_model=large --code_model=large --near_data=none -O1 --opt_for_speed=3 --use_hw_mpy=F5 -g --c++03 --define=__MSP430F5335__ --define=DEBUG=1 --diag_wrap=off --diag_warning=225 --display_error_number --abi=eabi --silicon_errata=CPU21 --silicon_errata=CPU22 --silicon_errata=CPU40 --printf_support=minimal -z -m"hw_1_5.map" --stack_size=1200 --heap_size=0 --cinit_hold_wdt=on -i"/home/sporty/ti/ccsv6/ccs_base/msp430/include" -i"/home/sporty/ti/ccsv6/ccs_base/msp430/lib" -i"/home/sporty/ti/ccsv6/ccs_base/msp430/lib/5xx_6xx_FRxx" -i"/home/sporty/ti/ccsv6/tools/compiler/msp430_15.12.2.LTS/include" -i"/home/sporty/ti/ccsv6/tools/compiler/msp430_15.12.2.LTS/lib" --reread_libs --diag_wrap=off --warn_sections --display_error_number --xml_link_info="hw_1_5_linkInfo.xml" --use_hw_mpy=F5 --rom_model -o "hw_1_5.out" "./coap_resources/hg.obj" "./coap_resources/root_dir.obj" "./coap_resources/system.obj" "./coap_resources/system_dir.obj" "./coap_resources/system_location.obj" "./coap_resources/system_log.obj" "./coap_resources/system_log_dir.obj" "./coap_resources/system_session.obj" "./driverlib/adc10_a.obj" "./driverlib/adc12_a.obj" "./driverlib/aes.obj" "./driverlib/battbak.obj" "./driverlib/comp_b.obj" "./driverlib/crc.obj" "./driverlib/ctsd16.obj" "./driverlib/dac12_a.obj" "./driverlib/dma.obj" "./driverlib/eusci_a_spi.obj" "./driverlib/eusci_a_uart.obj" "./driverlib/eusci_b_i2c.obj" "./driverlib/eusci_b_spi.obj" "./driverlib/flashctl.obj" "./driverlib/gpio.obj" "./driverlib/lcd_b.obj" "./driverlib/ldopwr.obj" "./driverlib/mpy32.obj" "./driverlib/oa.obj" "./driverlib/pmap.obj" "./driverlib/pmm.obj" "./driverlib/ram.obj" "./driverlib/ref.obj" "./driverlib/rtc_a.obj" "./driverlib/rtc_b.obj" "./driverlib/rtc_c.obj" "./driverlib/sd24_b.obj" "./driverlib/sfr.obj" "./driverlib/sysctl.obj" "./driverlib/tec.obj" "./driverlib/timer_a.obj" "./driverlib/timer_b.obj" "./driverlib/timer_d.obj" "./driverlib/tlv.obj" "./driverlib/ucs.obj" "./driverlib/usci_a_spi.obj" "./driverlib/usci_a_uart.obj" "./driverlib/usci_b_i2c.obj" "./driverlib/usci_b_spi.obj" "./driverlib/wdt_a.obj" "./miwt_os/cell_modem/clock_sm.obj" "./miwt_os/cell_modem/coap_server_sm.obj" "./miwt_os/cell_modem/gps_sm.obj" "./miwt_os/cell_modem/modem_sm.obj" "./miwt_os/coap/cbor_decoder.obj" "./miwt_os/coap/cbor_encoder.obj" "./miwt_os/coap/coap_pdu.obj" "./miwt_os/coap/coap_server.obj" "./miwt_os/coap/directory.obj" "./miwt_os/coap/option.obj" "./miwt_os/dispatcher/array_safe.obj" "./miwt_os/dispatcher/common.obj" "./miwt_os/dispatcher/event.obj" "./miwt_os/dispatcher/modem.obj" "./miwt_os/dispatcher/sm_names.obj" "./miwt_os/dispatcher/state_machine.obj" "./miwt_os/dispatcher/task.obj" "./miwt_os/dispatcher/tstamp.obj" "./miwt_os/sensor/sampling_sensor.obj" "./miwt_os/sensor/sensor_alarms.obj" "./miwt_os/sensor/sensor_sm.obj" "./miwt_os/sensor/transient_sensor.obj" "./miwt_os/serial/TI_aes_128.obj" "./miwt_os/serial/base64.obj" "./src/debug.obj" "./src/globals.obj" "./src/hw_abstraction.obj" "./src/hw_layer_ISRs.obj" "./src/init.obj" "./src/isr_clock.obj" "./src/isr_uart.obj" "./src/main.obj" "../lnk_msp430f5335.cmd"  -llibc.a -llibmath.a 
<Linking>
Finished building target: hw_1_5.out

2) added custom function

int _system_pre_init(void) {
    WDTCTL = WDTPW + WDTHOLD;
    return 1;
}


but the system still keeps WDTHOLD low during C++ object construction and the system fails, why?

  • To make it work, the WDT needs to be held after cinit.  So:

    extern "C" {
    // Redefine post init
    void _system_post_cinit(void) { WDTCTL = WDTPW + WDTHOLD; }
    }


    This works, as noted by Chester's post below.   The C++ objects are initialized by user

    constructors, therefore TI decided to enable the WDT before running through user code.

  • Cannot argue with what works, but it sounds rather odd.
    You said WDT expires during the lengthy "cinit". If so, how is "post_cinit" going to help?
  • I agree, it does sound strange.  I stepped through the pre-main process and roughly it looks like it runs through the following process,

    1)  _system_pre_init(void)

    2) init c vars

    3) WDT is enabled in by code in file autoinitwdt.c

    4)  _system_post_cinit(void)

    5) Construct C++ global objects         <= this is what is taking long and tripping WDT

    ... some other steps

    n) main()

    Also, it is good to argue with "what works but seems add", every time something seemed add, and I assumed it is OK, I ended up shooting myself in the foot.  So thank you for your comment...

  • >5) Construct C++ global objects <= this is what is taking long and tripping WDT
    No wonder it looked odd because only now you tell that you are using C++ ! Note that everyone by "default" assumes that plain C is used.
  • I thought it was obvious by first code snipped, anyone who knows anything about C, can recognize that the union is not C due to non-trivial constructor, there is no such thing in C.
  • 1)  _system_pre_init(void)

    2) init c vars

    3) WDT is enabled in by code in file autoinitwdt.c

    4)  _system_post_cinit(void)

    5) Construct C++ global objects         <= this is what is taking long and tripping WDT

    ... some other steps

    n) main()

    From my understanding, a WDT is a kind of last recourse if cyclic code fails. (Forcing a reset is not an optimal solution, but still better than failing).

    So, I have always started a watchdog after other initialisations are finished. I see no good reason to start it that early.

  • Agree, in my case it is just getting on the way, and the listed proposed solutions do not work for C++, so it makes it confusing.
  • WDT is automatically enabled before your step (1).

    Your step (3) did not help and can only make that situation worse. It should be eliminated.

    Is your step (5) part if your main? If so, you can precede that step by holding the WDT instead using step (4).
  • Steps 1 through 5 are default boot sequence, designed by TI, so I can customize some of the behavior by adding custom pre and post cinit functions, but as far as the step 3, it is there by default, part of bootup sequence written by TI. I can probably replace the whole thing, but, it makes compiler upgrade more challenging.
  • ... but as far as the step 3, it is there by default, part of bootup sequence written by TI.

    But usually, this startup code is copied into your project directory by the project generation "wizard" - at least all my IDE/toolchains do (for Cortex M). This suggests it is intended for project-specific adaption. My company does this frequently. And actually, incompatible changes to the startup method (file names, symbol names, assembler syntax, etc.) don't happen so frequently.

  • That would makes sense, unfortunately, for the MSP430 it is part of the library, revised with every compiler revision and probably intended to be customized via the pre and post cinit functions but not replaced by custom boot sequence, unless I manually start changing things, which I do not want to do.
  • Silver Diamond said:
    but the system still keeps WDTHOLD low during boject init and the system fails, why?

    I had previously asked a similar question in Should MSP430 linker --cinit_hold_wdt hold the watchdog around pinit as well as cinit, and the answer was that since user C++ constructors can "do anything" it is up to the user to code manage holding and/or or patting the watchdog during pinit.

  • Could you check your linker "heap_size" option? From your first post, it looks like it's equal to zero, which could be causing an issue here since insufficient heaps can cause a variety of software problems like runtime crashes and instability. This may explain why disabling the WDT before main() isn't working.

    The heap is a large pool of memory that can be allocated at runtime by application programs. Memory is allocated from a global pool, or heap, that is defined in the .sysmem section. The heap is dependent on the amount and type of data used for dynamic allocation (malloc, calloc, printf, etc.), therefore there is no mechanism to precisely determine the heap usage (unless using an RTOS like BIOS). It is recommended to start with a reasonable heap size like 0x400 when there is limited dynamic allocation (like printf() calls in the code), and increase it as needed depending on the application.

    Heap size can be set in CCS6 under Project->Properties->Build->MSP430 Linker->Basic Options->Heap size for C/C++ dynamic memory allocation (--heap_size, -heap)

    Regards,

    James

    MSP Customer Applications

  • Jim,

    Good catch, but actually it was a simplified linking command that I used during debugging.  Once I got past WDT resetting I added memory to heap.  Since I do use the new operator, I actually need much bigger heap, in order of 0x1000, than most.  Once I withheld WDT after cinit, system worked fine.

  • Chester,

    OK, this makes sense, I can see why...
  • I'm happy to hear that you were able to resolve your issue! I'll go ahead and close the thread, but please feel free to reply here or open a new thread and provide a link to this one if you have any further questions.

    Regards,

    James
    MSP Customer Applications

**Attention** This is a public forum