Products > Programming

assembler program to reset Nuvoton W83527HG watchdog

(1/5) > >>

m4rtin:
I have a motherboard which has a Nuvoton W83527HG chip(manual attached) which includes the watchdog functionality. When I enable the watchdog feature in UEFI, then the workstation resets with 300s interval as expected because nothing resets the watchdog from operating system. As I have no previous experience with assembler, then this seemed to be a good opportunity to learn. Based on the example in the manual on page 18 I ended up with following simple program:


--- Code: ---$ cat -n wd_reset.a
     1  ;-----------------------------------------------------
     2  ; Enter the Extended Function Mode
     3  ;-----------------------------------------------------
     4  MOV     DX,     0x2E
     5  MOV     AL,     0x87
     6  OUT     DX,     AL
     7  OUT     DX,     AL
     8  ;-----------------------------------------------------------------------------
     9  ; Configure Logical Device 8, Configuration Register CRF6
    10  ;-----------------------------------------------------------------------------
    11  MOV     DX,     0x2E
    12  MOV     AL,     0x07
    13  OUT     DX,     AL   ; point to Logical Device Number Reg.
    14  MOV     DX,     0x2F
    15  MOV     AL,     0x08
    16  OUT     DX,     AL   ; select Logical Device 8
    17  ;
    18  MOV     DX,     0x2E
    19  MOV     AL,     0xF6
    20  OUT     DX,     AL   ; select CRF6
    21  MOV     DX,     0x2F
    22  MOV     AL,     0x01
    23  OUT     DX,     AL   ; update CRF6 with value 01H
    24  ;----------------------------------------------------------------------------
    25  ; Exit the Extended Function Mode
    26  ;----------------------------------------------------------------------------
    27  MOV     DX,     0x2E
    28  MOV     AL,     0xAA
    29  OUT     DX,     AL
$

--- End code ---

First two OUT instructions on lines 6 and 7 are needed to enter the Extended Function mode. On lines 14-16 I select the Logical Device 8. I do this because page 16 in the manual tells that the watch dog(WDTO) is Logical Device 8. On lines 18 - 20 I select the Configuration Register F6 and on lines 21-23 I update it with 1 because the manual says that:


--- Quote ---The  time-out  value  is  set  at  Logical  Device  8,  CR  [F6h].  Writing  zero  disables the Watchdog Timer function. Writing any non-zero value to this register causes the counter to load this value into the Watchdog Timer counter and start counting down.
--- End quote ---

This is from page 105. However, I'm not sure that this is the correct Configuration Register to write to in order to reset the watchdog timer..

Then I assembled this program with yasm and made the executable with ld:

--- Code: ---$ yasm -f elf64 -o wd_reset.o wd_reset.a                                 
$ ld -g -o wd_reset wd_reset.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400080
$

--- End code ---

Now when I run this using debugger, then the program receives the SIGSEGV which should mean that it tries to access a restricted area in the memory:

--- Code: ---$ gdb ./wd_reset                                                         
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./wd_reset...(no debugging symbols found)...done.
(gdb) run
Starting program: /home/martin/wd_reset

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400086 in ?? ()
(gdb)

--- End code ---

I'm pretty sure that I made multiple mistakes along the way.. For example, is the Configuration Register 0xF6 the correct one to reset the watchdog? Can I assembler the program the way I did in my operating system if I want it to work with W83527HG chip?

andersm:
I believe that watchdog type is already supported by the Linux kernel's watchdog framework, in the w83627hf_wdt driver. I haven't looked at your code, but you can't access I/O ports (or any hardware resources) directly with just normal user permissions.

m4rtin:

--- Quote from: andersm on January 03, 2020, 10:50:51 pm ---I believe that watchdog type is already supported by the Linux kernel's watchdog framework, in the w83627hf_wdt driver.

--- End quote ---
I tried that, but this does not seem to work:

--- Code: ---# modprobe -v w83627hf_wdt                                     
insmod /lib/modules/4.4.0-170-generic/kernel/drivers/watchdog/w83627hf_wdt.ko
modprobe: ERROR: could not insert 'w83627hf_wdt': No such device
#

--- End code ---
In addition, I tried with w83877f_wdt, wm8350_wdt and wm831x_wdt drivers, but none of those worked.


--- Quote from: andersm ---I haven't looked at your code, but you can't access I/O ports (or any hardware resources) directly with just normal user permissions.

--- End quote ---
Thanks for pointing this out. I tried under the root user, but the result is the same(probably because my program is faulty):

--- Code: ---# gdb ./wd_reset
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./wd_reset...(no debugging symbols found)...done.
(gdb) run
Starting program: /home/martin/wd_reset

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400086 in ?? ()
(gdb)

--- End code ---

Nominal Animal:

--- Quote from: m4rtin on January 03, 2020, 09:46:31 pm ---Based on the example in the manual on page 18 I ended up with following simple program:
--- End quote ---
No.  Linux, and other operating systems like Windows and MacOS, do not allow arbitrary programs direct access to chips and devices.

In Linux, you need to use a watchdog kernel driver.  In your case, w83627hf_wdt should support yours, but for some reason, does not detect your W83527HG chip correctly.  (According to hwmon developers, W83527HG is a variant of W83627DHG-P with just fewer features but "hopefully compatible".)

Even if you were to create an userspace application (it is possible), it would not work as well as the kernel driver.  In particular, it would either consume a lot of unnecessary CPU time, OR cause the machine to reboot at very heavy loads.  No, you do not want to go that route.


Looking at the datasheet, it says the Chip ID is C1 on page 72 (chapter 9.40).  If we look at the w83627hf_wdt driver, we find it does not detect it.  It would have w83527hg in the enum chips on line 51 or so, and "W83527HG" in the corresponding position in the chip_name array in wdt_init on line 471-493;
    #define W83527HG_ID 0xc1
between lines 94 and 95; a
    case w83527hg:
somewhere in w83627hf_init() around line 167-216; and
    case W83527HG_ID:
        ret = w83527hg;
        break;
in wdt_find() around line 349-427.

I didn't bother checking if the W83527HG needs specific handling; there might be a few additional lines, if the manual says it needs different handling compared to one of the existing chips the driver already supports.

You could contact the driver author (Pádraig Brady, address listed at the bottom of the source file, linked to above), include the manual PDF or a link to this discussion, and ask if they would help with the patch.  You'd need to learn how to recompile your Linux kernel in Ubuntu, applying the patch needed to the w83627hf_wdt.c driver.  You'd need to test the driver, and report any issues or success to the author, but if successful, it would be included in the vanilla Linux; you could then ask Greg KH to include the patch in the stable kernel series (Brady might do that automatically), and even the Ubuntu folks to include it in standard Ubuntu kernels if they don't pick it up automatically, getting the support into all future Ubuntu kernels.  It will be months before the changes percolate down to the kernels you use, so in the mean time, you'd need to recompile your own kernels.  Overall, it is still the path of least work, and although it does require some effort from you, this is the path I would take myself -- and I'm very lazy myself.

You should definitely mention which motherboard this is, as well.  It does not matter if there are just a few in use; these kind of additional support details are almost always happily added by the developers like Brady.  Just make sure you are willing to do the testing and checking they ask, first.

andersm:

--- Quote from: Nominal Animal on January 04, 2020, 01:25:20 am ---Looking at the datasheet, it says the Chip ID is C1 on page 72 (chapter 9.40).
--- End quote ---
If I read the driver correctly, it reads the chip ID from global register 0x20, which should return 0xB0, the same ID used for the W83627DHG-P.

Edit: m4rtin, have you checked if the driver printed anything in the kernel logs?

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version