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.

Beagleboard xM Watchdog

I wrote the following to learn how to use the watchdog. I have two problems:

1. there are 4 for() statments in the code, it seems that without them, the watchdog cannot be turned on or off. I also tired i<10, but it also didn't work. Technical Reference Manual dosen't show that it should wait sometime until the register value changed.

2. when I only stop the watchdog, the code works well, "Turn off watchdog 2..." will be output through uart. But when I turn off the watchdog, set the wldr register, then turn on the watchdog. The code will not work on the board, no output from uart.

Is there anything wrong with my code?

// disable watchdog 2
uart_write("Turn off watchdog 2...");
*reg_wdtimer2_wspr = 0x0000AAAA;
for (i=0; i<100; i++){}; 
while (*reg_wdtimer2_wspr & ~0x0000AAAA){};
*reg_wdtimer2_wspr = 0x00005555;
for (i=0; i<100; i++){};
while (*reg_wdtimer2_wspr & ~0x00005555){};

*reg_wdtimer2_wldr = 0x0;

// enable watchdog 2
uart_write("Turn on watchdog 2...");
*reg_wdtimer2_wspr = 0x0000BBBB;
for (i=0; i<100; i++){}; // It takes sometime to make the change on register.
while (*reg_wdtimer2_wspr & ~0x0000BBBB){};
*reg_wdtimer2_wspr = 0x00004444;
for (i=0; i<100; i++){};
while (*reg_wdtimer2_wspr & ~0x00004444){};

  • Is your only criteria for code working UART output? Are you sure your coded doesn't hang in one of these "while" loops? I think you should place the UART printouts AFTER the WD related commands.
  • after these code, I also have some code for blinking led, it also doesn't work.  I put output code here to inform me what will be done for the next step. From the debug information, it seems that, sometimes the program will dead in the loops, but before that, UART should output the message firstly. And I don't really understand why the programm can hang in the loop, it only checks register value.

  • I am not sure how the compiler will treat this "while" statement. I have seen such statements compile to a single read and then endless comparison of the value. I think you should check this.
  • Thanks for your reply. I will check that. But how about the for loop? How can I set the watchdog rightly? From the TRM, it shows:

    To disable the timer, follow this sequence:
    1. Write 0xXXXX AAAA in WDTi.WSPR.
    2. Write 0xXXXX 5555 in WDTi.WSPR.
    To enable the timer, follow this sequence:
    1. Write 0xXXXX BBBB in WDTi.WSPR.
    2. Write 0xXXXX 4444 in WDTi.WSPR.

    without the for loop, the timer can not stop or restart.

    Best Regards
    Zhiwen
  • I also see the code in watchdog.c or uart_irda_cir.c from AM335X_StarterWare, which use a while loop to check, whether the register value changed.
  • I have asked the software team to look at this. They will respond here.
  • Hi Zhiwen,

    I am not familiar with Starterware code. However, here is what is done in linux kernel to enable, disable the timer:
    static void omap_wdt_enable(struct omap_wdt_dev *wdev)
    {
    void __iomem *base = wdev->base;

    /* Sequence to enable the watchdog */
    writel_relaxed(0xBBBB, base + OMAP_WATCHDOG_SPR);
    while ((readl_relaxed(base + OMAP_WATCHDOG_WPS)) & 0x10)
    cpu_relax();

    writel_relaxed(0x4444, base + OMAP_WATCHDOG_SPR);
    while ((readl_relaxed(base + OMAP_WATCHDOG_WPS)) & 0x10)
    cpu_relax();
    }

    static void omap_wdt_disable(struct omap_wdt_dev *wdev)
    {
    void __iomem *base = wdev->base;

    /* sequence required to disable watchdog */
    writel_relaxed(0xAAAA, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */
    while (readl_relaxed(base + OMAP_WATCHDOG_WPS) & 0x10)
    cpu_relax();

    writel_relaxed(0x5555, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */
    while (readl_relaxed(base + OMAP_WATCHDOG_WPS) & 0x10)
    cpu_relax();
    }

    You can see that there is a cpu_relax() call, which basically acts as a delay between writes, same as adding the empty for loops.

    In linux kernel the writel_relaxed & cpu_relax() calls are done to ensure the sequence (for example in wdt_enable()):

    1. Write 0xBBBB in WDTi.WSPR.
    2. Write 0x4444 in WDTi.WSPR.

    And also this way we guarantee some time to ensure that there are no writes pending => while (readl_relaxed(base + OMAP_WATCHDOG_WPS) & 0x10)

    I am not quite sure what the while loop in your code does: while (*reg_wdtimer2_wspr & ~0x0000AAAA)

    Best Regards,
    Yordan

  • Hi Yordan,

    thanks for the reply, the while loop checks whether the register value is right.

    I changed the code as following, it doesn't work any more. I just want to change the value in the register wldr. It seem that, the program is dead somewhere. When I only turn off the watchdog, it works sometimes, when I try to restart the timer with writing 0xBBBB and 0x4444, the program will be dead.

    uart_write("Turn off watchdog 2...");
    *reg_wdtimer2_wspr = 0x0000AAAA;
    for (i=0; i<100; i++){};
    *reg_wdtimer2_wspr = 0x00005555;
    for (i=0; i<100; i++){};

    *reg_wdtimer2_wldr = 0x0;

    uart_write("Turn on watchdog 2...");
    *reg_wdtimer2_wspr = 0x0000BBBB;
    for (i=0; i<100; i++){};
    *reg_wdtimer2_wspr = 0x00004444;
    for (i=0; i<100; i++){};

    Best Regards,
    Zhiwen
  • And when I use xds100v2 step by step to run the program, it works well: the timer can stop and restart, but when I put the file on the SD card, and run it on the board, there will be some problems.

    I got the .out file from CCS6, and usd signGP.c generate a MLO file, then copy to SD card.

    Is there somthing wrong with these steps? which lead to the trouble in the program.

    Best regards.
    Zhiwen