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.

LAUNCHXL-CC2650: Watchdog callback function not being called

Part Number: LAUNCHXL-CC2650
Other Parts Discussed in Thread: CC2650, CC2640

Hello all,

I am using Launchxl-CC2650.

BLE SDK 2_02_07_06

TI RTOS 2.21.1.08

CCS7.4

Compiler TI Ver.5.2.6.

I have added code for watchdog driver in  UART_ECHO example code.

I can see that uart prints on serial port successfully.

CC2650 also restarts when the watchdog timer expires.

I am writing to uart port in watchdog callback function, but this function is not being called.

Please help

Thank you,

Dnyaneshvar Salve

  • Hi,

    Thank you for reaching out of us,

    My point is that if you are writing to UART in the watchdog callback just before the restart you will not see the print out cause of the restart.

    Did you use breaking point in the function?

    regards,

  • Hi ,

    I already tried with placing breakpoint. But that breakpoint is never reached

  • Can you provide me the localisation of your UART print of in the watchdog callback?

    If you did not remove the restart function in the watchdog, optimization in debug mode could pass over this breakpoint due to the restart function after.

    regards,

  • Hi ,

    Sorry But I am not getting what exactly you wanted to say

  • /*
     *  ======== uartecho.c ========
     */
    
    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    /* TI-RTOS Header files */
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/UART.h>
    /* Example/Board Header files */
    #include "Board.h"
    #include <stdint.h>
    #include <ti/drivers/Watchdog.h>
    #include <ti/drivers/watchdog/WatchdogCC26XX.h>
    #include <stdio.h>
    #include <string.h>
    #define TASKSTACKSIZE     768
    
    Task_Struct task0Struct;
    Char task0Stack[TASKSTACKSIZE];
    
    /* Global memory storage for a PIN_Config table */
    static PIN_State ledPinState;
    
    Watchdog_Params params;
    Watchdog_Handle watchdog;
    uint32_t tickValue;
    
    /*
     * Application LED pin configuration table:
     *   - All LEDs board LEDs are off.
     */
    PIN_Config ledPinTable[] = {
    Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    Board_LED2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    PIN_TERMINATE };
    
    char str[] = "Watchdog System Reset Called\n";
    UART_Handle uart;
    /*
     *  ======== echoFxn ========
     *  Task for this function is created statically. See the project's .cfg file.
     */
    Void echoFxn(UArg arg0, UArg arg1) {
    	char input;
    	UART_Params uartParams;
    	const char echoPrompt[] = "Starting Watchdog application:\r\n";
    
    	/* Create a UART with data processing off. */
    	UART_Params_init(&uartParams);
    	uartParams.writeDataMode = UART_DATA_BINARY;
    	uartParams.readDataMode = UART_DATA_BINARY;
    	uartParams.readReturnMode = UART_RETURN_FULL;
    	uartParams.readEcho = UART_ECHO_OFF;
    	uartParams.baudRate = 115200;
    	uart = UART_open(Board_UART0, &uartParams);
    	if (uart == NULL) {
    		System_abort("Error opening the UART");
    	}
    	UART_write(uart, echoPrompt, sizeof(echoPrompt));
    	/* Loop forever echoing */
    	while (1) {
    		UART_read(uart, &input, 1);
    		UART_write(uart, &input, 1);
    	}
    }
    
    void UserCallbackFxn(UArg watchdog);
    //typedef void (*Watchdog_Callback)(uintptr_t);
    /*
     *  ======== main ========
     */
    int main(void) {
    	PIN_Handle ledPinHandle;
    	Task_Params taskParams;
    
    	/* Call board init functions */
    	Board_initGeneral()
    	;
    	Board_initUART();
    
    	//start watchdog initialization code
    	Board_initWatchdog();
    
    	/* Create and enable a Watchdog with resets enabled */
    	Watchdog_Params_init(&params);
    	params.resetMode = Watchdog_RESET_OFF;
    	params.callbackFxn = (Watchdog_Callback)UserCallbackFxn;
    	params.debugStallMode = Watchdog_DEBUG_STALL_ON;
    	watchdog = Watchdog_open(Board_WATCHDOG0, &params);
    	if (watchdog == NULL) {
    		System_printf("Failed to open Watchdog Driver\n");
    		System_flush();
    	} else {
    		System_printf("Watchdog Driver opened Successfully\n");
    	}
    	tickValue = Watchdog_convertMsToTicks(watchdog, 2000);
    	Watchdog_setReload(watchdog, tickValue);
    
    	/* Construct BIOS objects */
    	Task_Params_init(&taskParams);
    	taskParams.stackSize = TASKSTACKSIZE;
    	taskParams.stack = &task0Stack;
    	Task_construct(&task0Struct, (Task_FuncPtr) echoFxn, &taskParams, NULL);
    
    	/* Open LED pins */
    	ledPinHandle = PIN_open(&ledPinState, ledPinTable);
    	if (!ledPinHandle) {
    		System_abort("Error initializing board LED pins\n");
    	}
    
    	PIN_setOutputValue(ledPinHandle, Board_LED1, 1);
    	System_flush();
    
    	/* Start BIOS */
    	BIOS_start();
    
    	return (0);
    }
    void UserCallbackFxn(UArg watchdog) {
    	UART_write(uart, &str, sizeof(str));
    }
        Attaching my code for your reference.

  • Ok my apologies, I thought you kept the reset ON and try to print UART stuff in the same time sorry for that.

    Why are you not using the watchdogCallback(uintptr_t watchdogHandle) callback with the watchdog handle instead of the uarg parameter?

    regards,

  • Hi Guillaume,

    I think I have already tried this watchdogCallback(uintptr_t watchdogHandle).

    But still I will try this tomorrow again

  • hello Guillaume,

    Greetings of the day.

    I have tried as per your suggestion but results are same.

    It would be great if you guide me further

    regards

    Dnyaneshvar 

  • Hello,

    Here is what I think is probably happening:

    • The watchdog interrupt is triggered
    • The watchdog timer is not cleared
    • The device resets

    It states clearly in the documentation that no BIOS APIs can be called from within the watchdog timer callback, I am assuming that the UART_write operation is non-blocking, so the write operation can be started, but since the device is reset, the operation never completes.

    In other words, it is not possible to print something from the callback of the watchdog timer.

    What can be done, however, is that you can clear the watchdog timer from the callback, preventing a reset, and set a flag in the callback.

    Another task can then check the status of that flag and print whatever you want from a non-callback context.

    Hope this help to understand better the way watchdog works,

    regards,

  • Hi,

    I have commented the
    //UART_write(uart, &str, sizeof(str));

    and now i am just trying to turn ON the LED by


    PIN_setOutputValue(ledPinHandle, Board_LED1, 1);

    But the problem is UserCallbackFxn is not being called

  • Hi again,

    This behaviour is expected as well, that's not going to work either. You can only just set a flag in the callback and go that way.

    regards,

  • hi,

    As said by you,

    It states clearly in the documentation that no BIOS APIs can be called from within the watchdog timer callback,

    Can you please guide me where this is written?

  • HI,

    you said,

    Here is what I think is probably happening:

    • The watchdog interrupt is triggered
    • The watchdog timer is not cleared
    • The device resets

    How?

    As per my code (attached above) I have set 

    params.resetMode = Watchdog_RESET_OFF;

    So why do you think that "The device resets"?

  • Please have look at the attached Image

  • I will reassign this thread, thus you'll find a relevant expert.

    My apologies I forgot you kept the reset OFF, but the result should be the same.

    ...

    As it's mentioned in the watchdog.h file, pointer to callback is not supported on all targets.

    Thus, if you have a look at the watchdogCC26xx.h file located in the includes, it clearly states that's "Therefore it is not safe to call any OS APIs from the Watchdog callback function. This includes any driver calls that rely on OS APIs."

    ...

    regards,

  • As it's mentioned in the watchdog.h file, pointer to callback is not supported on all targets.

    yes, But it is not written that It is not supported with CC2650,

    So I guest It should work

  • Hello Guillaume,

    As you have attached the screenshot which states that it is not safe to call any OS API from watchdog callback

    But to my surprise same file at my end does not say anything like that. I think you were using older driver files (older SDK or TIRTOS)

    Regards,

    Dnyaneshvar

  • Hi,

    I see, you're using a SDK different than mine so I assume they add this note in the new version. (For your information I cannot access to the BLE SDK 2_02_07_06 for CC2650 so I had to work with the 5_30 from CC2640 which is basically the same code)

    Anyway, it should be something due to your callback function. Are you able to run the watchdog example and see if it works from there?

    regards,

  • Hi,

    I have not got any solution till now.

    May I know, What version of SDK are you using.

  • I am using the latest SDK, I don't think anybody will recommend using the older one 

  • As  you said yesterday that ,

    I will reassign this thread, thus you'll find a relevant expert.

    But nobody has come up with the solution

  • As I said, the SDK version I have is for cc2640 so for your information is the simplelink_cc2640r2_sdk_5_30_00_03. And as I said embedded software for those two devices are the same. 

    The thread is reassigned, just wait for the proper engineer to answer.

    regards.

  • AS I SAID FOR YOUR INFORMATION AT THE VERY BEGINING OF THIS THREAD THAT WHAT DEVICE I AM USING, WHAT SDK I AM USING, WHAT COMPILER I AM USING.

    THERE IS NO SENSE OF MENTIONING CC2640R2 SDK HERE.

    YESTERDAY YOU SAID THAT THIS THREAD WILL BE REASSIGNED BUT AFTER MANY HOURS YOU HAVE NOT DONE THAT

  • Greetings Dnyaneshvar,

    I apologize for not getting back to you sooner on this. I understand how frustrating it can be to have code that doesn't behave the way you want it to.

    Going back to the issue you are facing, is it possible for you to provide a screenshot of what the registers look like when you run your code? The way to do this would be set a breakpoint right after you have configured the Watchdog, but before, you start the timer. This will allow me to better understand the state of the registers after the config is done.

  • Greetings again Dnyaneshvar,

    I did some more looking at the SDK and device you were using, and I realized that you are using a device older than what I originally thought you were using. I apologize for this misunderstanding. Have you had any more time to check the registers on the device, and perhaps provide screenshots as to what you see? I'll be more than willing to help you debug this further.

    Best,
    Achyut Ray

  • Hello Achyut Ray,

    thank you for the reply.

    should I insert breakpoint at 

    watchdog = Watchdog_open(Board_WATCHDOG0, &params);

    and then view the registers status?

    Regards,

    Dnyaneshvar

  • Hello  Achyut Ray,

    Please have look at the attached screenshot 

    Dnyaneshvar 

  • Hi again Dnyaneshvar,

    Thank you for providing the screenshot of the registers after opening the watchdog handle. The registers look correct, and I can see that the configurations you make actually end up in their right place. When you run a debug session, you say that the breakpoint is never reached in the callback function. Can you see that the any NMI interrupt is set in the ICSR register? This can help us understand if the Watchdog interrupt actually occurred or not. If no activity happens here in the amount of time that you configured the watchdog to expire in, then the watchdog expiry interrupt doesn't occur, which would explain the callback not being called. Can you please check this and get back to me on this?

    Best,
    Achyut

  • Hi Achyut Ray,

    Thank you for the help.

    Here in Mumbai, it's raining heavily and flooded everywhere. I will check the points suggested by you as soon as I resume working.

    Regards,

    Dnyaneshvar

  • Hello Achyut Ray,

    Please have look at the attached screenshot for ICSR register

    Thank you,

    Dnyaneshvar

  • Hi Dnyaneshvar,

    Thank you for attaching the image. I see that the NMIPENDSET bit is 0, which indicates that no NMI has occurred yet. This would explain why the code does not go to the callback. Can you try changing the WDT's expiry time, so that it expires faster, to make sure that the bit is in fact set?

  • Hello Achyut Ray,

    I have set time to 500 milliseconds.

    But results are same.

    Dnyaneshvar

  • That is indeed strange. Can you try enabling test mode to see whether an interrupt is generated then?

  •  CAUSE_INTR bit in register INT_CAUS keeps on toggling

  • Nice! That means that an interrupt is a generated! That is a good thing, now the image you sent with the makes more sense. If you check the image you sent when I asked you to send an image of the NMIPENDSET, the field ISRPENDING has the value 1, meaning there is a pending interrupt somewhere. Can you try turning on the reset when WDT times out? When doing this, remember to clear the timer from the ISR, else the device will reset. When Reset is turned on, the first time the timer expires, an interrupt is generated. If the ISR does not clear the timer, then the device resets.

    Can you test with having the resets turned on? Just so I can make sure that I am not sounding confusing, enable resets, then, in the ISR add the 

    Watchdog_clear(watchdog);
     as the first line. Can you update me on how that works for you?

  • Hi,

    I added Watchdog_clear(watchdog); a shown in code I have attached.

    /*
     *  ======== uartecho.c ========
     */
    
    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    /* TI-RTOS Header files */
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/UART.h>
    /* Example/Board Header files */
    #include "Board.h"
    #include <stdint.h>
    #include <ti/drivers/Watchdog.h>
    #include <ti/drivers/watchdog/WatchdogCC26XX.h>
    #include <stdio.h>
    #include <string.h>
    #define TASKSTACKSIZE     768
    
    Task_Struct task0Struct;
    Char task0Stack[TASKSTACKSIZE];
    
    /* Global memory storage for a PIN_Config table */
    static PIN_State ledPinState;
    
    Watchdog_Params params;
    Watchdog_Handle watchdog;
    uint32_t tickValue;
    
    PIN_Handle ledPinHandle;
    /*
     * Application LED pin configuration table:
     *   - All LEDs board LEDs are off.
     */
    PIN_Config ledPinTable[] = {
    Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    Board_LED2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    PIN_TERMINATE };
    
    char str[] = "Watchdog System Reset Called\n";
    UART_Handle uart;
    /*
     *  ======== echoFxn ========
     *  Task for this function is created statically. See the project's .cfg file.
     */
    Void echoFxn(UArg arg0, UArg arg1) {
    	char input;
    	UART_Params uartParams;
    	const char echoPrompt[] = "Starting Watchdog application:\r\n";
    
    	/* Create a UART with data processing off. */
    	UART_Params_init(&uartParams);
    	uartParams.writeDataMode = UART_DATA_BINARY;
    	uartParams.readDataMode = UART_DATA_BINARY;
    	uartParams.readReturnMode = UART_RETURN_FULL;
    	uartParams.readEcho = UART_ECHO_OFF;
    	uartParams.baudRate = 115200;
    	uart = UART_open(Board_UART0, &uartParams);
    	if (uart == NULL) {
    		System_abort("Error opening the UART");
    	}
    	UART_write(uart, echoPrompt, sizeof(echoPrompt));
    	/* Loop forever echoing */
    	while (1) {
    		UART_read(uart, &input, 1);
    		UART_write(uart, &input, 1);
    	}
    }
    
    void UserCallbackFxn(Watchdog_Handle watchdog);
    //typedef void (*Watchdog_Callback)(uintptr_t);
    /*
     *  ======== main ========
     */
    int main(void) {
    	Task_Params taskParams;
    
    	/* Call board init functions */
    	Board_initGeneral()
    	;
    	Board_initUART();
    
    	//start watchdog initialization code
    	Board_initWatchdog();
    
    	/* Create and enable a Watchdog with resets enabled */
    	Watchdog_Params_init(&params);
    	params.resetMode = Watchdog_RESET_ON;
    	params.callbackFxn = (Watchdog_Callback)UserCallbackFxn;
    	params.debugStallMode = Watchdog_DEBUG_STALL_ON;
    	watchdog = Watchdog_open(Board_WATCHDOG0, &params);
    	if (watchdog == NULL) {
    		System_printf("Failed to open Watchdog Driver\n");
    		System_flush();
    	} else {
    		System_printf("Watchdog Driver opened Successfully\n");
    	}
    	tickValue = Watchdog_convertMsToTicks(watchdog, 3000);
    	Watchdog_setReload(watchdog, tickValue);
    
    	/* Construct BIOS objects */
    	Task_Params_init(&taskParams);
    	taskParams.stackSize = TASKSTACKSIZE;
    	taskParams.stack = &task0Stack;
    	Task_construct(&task0Struct, (Task_FuncPtr) echoFxn, &taskParams, NULL);
    
    	/* Open LED pins */
    	ledPinHandle = PIN_open(&ledPinState, ledPinTable);
    	if (!ledPinHandle) {
    		System_abort("Error initializing board LED pins\n");
    	}
    
    	PIN_setOutputValue(ledPinHandle, Board_LED1, 1);
    	System_flush();
    
    	/* Start BIOS */
    	BIOS_start();
    
    	return (0);
    }
    void UserCallbackFxn(Watchdog_Handle watchdog) {
    	Watchdog_clear(watchdog);
    	PIN_setOutputValue(ledPinHandle, Board_LED1, 0);
    	UART_write(uart, &str, sizeof(str));
    }
    

    But device is getting reset

  • Hi Achyut Ray,

    Is there any syntax error in my code or any other link for solution of this problem?

    dnyaneshvar

  • Hi Dnyaneshvar,

    Could you watch the handle as a variable in CCS? I am interested in knowing whether the handle gets updated with the correct address for the callback function. Another question I have, is to know whether the NMI bit now gets set at in the interrupt registers? Your code seems to be fine, and it is annoying that it doesn't work.

    Best,
    Achyut Ray

  • Hi Achyut Ray,

    Please have look at the attached screenshot

     

    Dnyaneshvar

  • As in the attached Image, Handle is not getting updated with address of usercallback function.

    Hw attributes are also not set and watchdog object is also not created. I am not sure whether I am correct or not. 

    NMI bit is still not set

  • Hi,

    is it relevant ?

    address of userfxn is 0x00003E88

    but param is having value 0x00003E89

  • The reason you don't see the updates, is because those are local variables. You could try to turn off optimization (if you haven't already done so), and then convert those variables to volatile globals instead. That way you can access them anytime, from anywhere in that file

  • The 0x00003E88 and 0x00003E89 are not addresses but rather values held at a memory location. The addresses are one column to the right. In the image you sent, that would make the address of the params 0x2000105C, for example. Nothing to worry about there Smiley

  • handle is defined  as

    volatile Watchdog_Handle watchdog;

    optimization was "turned off" by default as shown in image.

    there is no change in the behavior of code after volatile declaration 

  • No change in behavior makes sense. Volatile declaration should, however, allow you to look at the data structures to confirm if they actually get updated.

  • Hi Achyut Ray,

    With reference to the screenshots shared by me what exact parameter I should look for?

    Dnyaneshvar

  • Hi Dnyaneshvar,

    Apologies for the delayed response. With respect to the screenshots you've attached, can you check if the handle, object, and hwAttrs now get the correct values for the callback function? After checking all of this, it may be a possibility to consider that this specific device probably doesn't support callbacks to a watchdog interrupt handler.

    Best,
    Achyut Ray

  • Hi,

    Please have look at the screenshot attached for the handle, object and hwAttrs

    this specific device probably doesn't support callbacks to a watchdog interrupt handler- you can search for e2e forum on CC2650 watchdog. Many people have used it.

    regards,

    Dnyaneshvar