• uboot - 驱动开发 - dw watchdog


    说明

    • 公司SOC使用的watchdog模块是新思(Synopsys)的IP。

    需求

    • 用户有时会在uboot/kernel中做些开发,新增一些功能(OTA升级等),可能会出现uboot/kernel启动崩溃甚至设备死机等问题,需要在uboot启动阶段开启watchdog监控设备运行实现异常后复位。

    实现

    • 前提:dts watchdog节点配置ok。
    • 由于历史原因,根据是否支持DM(Driver model),uboot原生支持两种wdt驱动和使用的配置/实现方式。
    1. 不支持DM,常见于较早版本(uboot,wdt驱动)实现
    核心配置项:CONFIG_HW_WATCHDOG
    
    • 1
    1. 支持DM
    核心配置项:CONFIG_WDT
    
    // file: drivers/watchdog/Kconfig
    config WDT
        bool "Enable driver model for watchdog timer drivers"
        depends on DM
        ....    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    不支持DM

    配置项

    1. 核心配置
    CONFIG_HW_WATCHDOG 
    
    • 1
    1. wdt timeout时间
    CONFIG_WATCHDOG_TIMEOUT_MSECS
    
    • 1
    1. 具体型号的wdt,例如:dw wdt。
    CONFIG_DESIGNWARE_WATCHDOG
    
    • 1
    • 如果未配置支持DM(CONFIG_WDT),但是配置了硬件wdt,CONFIG_HW_WATCHDOG会自动选上,例如:
    config DESIGNWARE_WATCHDOG
        bool "Designware watchdog timer support"
        select HW_WATCHDOG if !WDT
        ...
    
    • 1
    • 2
    • 3
    • 4

    驱动代码

    1. 定义并实现驱动相关功能接口
    //file: drivers/watchdog/designware_wdt.c
    static int designware_wdt_settimeout(unsigned int timeout)
    {
        ....
    }
    
    static void designware_wdt_enable(void)
    {
        ....
    }
    
    static void designware_wdt_disable(void)
    {
        ....
    }
    
    static unsigned int designware_wdt_is_enabled(void)
    {
        ....
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    1. 定义实现对外接口
    //file: drivers/watchdog/designware_wdt.c
    #if defined(CONFIG_HW_WATCHDOG)
    void hw_watchdog_reset(void)
    {
        ...
    }
    
    void hw_watchdog_init(void)
    {
        // 初始化wdt,并enable
        ...
    }
    
    void hw_watchdog_disable(void)
    {
        ...
    }
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    uboot中使用

    1. 头文件(watchdog.h)中会定义统一的宏(WATCHDOG_RESET、WATCHDOG_DISABLE)指向驱动文件中实现的hw对外接口,具体使用后面统一说明。
    // file: include/watchdog.h
    #if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)
    #define INIT_FUNC_WATCHDOG_INIT init_func_watchdog_init,
    #define INIT_FUNC_WATCHDOG_RESET        init_func_watchdog_reset,
    #else
    #define INIT_FUNC_WATCHDOG_INIT
    #define INIT_FUNC_WATCHDOG_RESET
    #endif
    
    #ifdef CONFIG_HW_WATCHDOG
        #if defined(__ASSEMBLY__)
            #define WATCHDOG_RESET bl hw_watchdog_reset
        #else
            extern void hw_watchdog_reset(void);
            extern void hw_watchdog_disable(void);
    
            #define WATCHDOG_RESET hw_watchdog_reset
            #define WATCHDOG_DISABLE hw_watchdog_disable
        #endif /* __ASSEMBLY__ */
    #else
        ....
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    1. 由于不支持DM,wdt-uclass.c(DM接口)未使用。

    验证

    • 这种方式,整体上执行流程比较固定,uboot启动wdt就会自动运行,支持配置项较少,验证方法只能代码调试。
    • 由于不支持DM,这种模式,不支持wdt cmd。

    支持DM

    配置项

    1. 核心配置
    CONFIG_WDT
    CONFIG_WATCHDOG // enable uboot内部使用的喂狗接口,该方式下必需enable
    
    • 1
    • 2
    • 配置CONFIG_WDT后会自动开启CONFIG_WATCHDOG, 如下:
    // file: drivers/watchdog/Kconfig
    config WDT
        bool "Enable driver model for watchdog timer drivers"
        depends on DM
        imply WATCHDOG
        ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 自动启动配置(可选配置)
    CONFIG_WATCHDOG_AUTOSTART=y   // 自动启动
    CONFIG_WATCHDOG_TIMEOUT_MSECS //wdt timeout时间, 默认60s
    
    • 1
    • 2
    1. 具体型号的wdt,例如:dw wdt。
    CONFIG_DESIGNWARE_WATCHDOG
    
    • 1

    驱动代码

    1. 按照DM模型,实现probe等相关接口
    2. 实现DM定义的 wdt 操作接口
    //file: include/wdt.h
    struct wdt_ops {
        int (*start)(struct udevice *dev, u64 timeout_ms, ulong flags);
        int (*stop)(struct udevice *dev);
        int (*reset)(struct udevice *dev);
        int (*expire_now)(struct udevice *dev, ulong flags);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    uboot中使用

    1. wdt cmd使用的是wdt-uclass.c中的统一接口,wdt-uclass.c中的函数再调用具体驱动的接口。
    2. 头文件(watchdog.h)中会定义统一的宏(WATCHDOG_RESET)指向wdt-uclass.c中实现的对外喂狗接口,具体使用后面统一说明。
    // file: include/watchdog.h
    #ifdef CONFIG_HW_WATCHDOG
        ...
    #else
        /*
         * Maybe a software watchdog?
         */
        #if defined(CONFIG_WATCHDOG)
                #if defined(__ASSEMBLY__)
                        #define WATCHDOG_RESET bl watchdog_reset
                #else
                        /* Don't require the watchdog to be enabled in SPL */
                        #if defined(CONFIG_SPL_BUILD) &&                \
                                !defined(CONFIG_SPL_WATCHDOG)
                                #define WATCHDOG_RESET() {}
                        #else
                                extern void watchdog_reset(void);
    
                                #define WATCHDOG_RESET watchdog_reset
                        #endif
                #endif
        #else
                /*
                 * No hardware or software watchdog.
                 */
                #if defined(__ASSEMBLY__)
                        #define WATCHDOG_RESET /*XXX DO_NOT_DEL_THIS_COMMENT*/
                #else
                        #define WATCHDOG_RESET() {}
                #endif /* __ASSEMBLY__ */
        #endif /* CONFIG_WATCHDOG && !__ASSEMBLY__ */
    #endif /* CONFIG_HW_WATCHDOG */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    验证

    1. 使用cli命令验证
    • enable wdt命令(cmdline)
    CONFIG_CMD_WDT=y // wdt cmd
    
    • 1
    • 运行效果
    uboot# wdt 
    wdt - Watchdog sub-system
    
    Usage:
    wdt list - list watchdog devices
    wdt dev [] - get/set current watchdog device
    wdt start  [flags] - start watchdog timer
    wdt stop - stop watchdog timer
    wdt reset - reset watchdog timer
    wdt expire [flags] - expire watchdog timer immediately
    
    uboot# wdt list
    dw-wd@0x27000000 (designware_wdt) // dts配置
    uboot# wdt dev dw-wd@0x27000000
    uboot# wdt start 30000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    uboot中使用

    • 两种配置(是否支持DM)方式,uboot中都是使用统一的宏(WATCHDOG_RESET等)去操作wdt,不同的是宏指向的函数。
    1. 不支持DM,WATCHDOG_RESET指向的是wdt驱动中hw_watchdog_reset函数。
    2. 支持DM,WATCHDOG_RESET指向的是wdt-uclass.c中watchdog_reset函数。
    • uboot初始化时会主动调用INIT_FUNC_WATCHDOG_INIT初始化wdt,不支持DM配置(CONFIG_HW_WATCHDOG),wdt初始化时会直接enable wdt。
    //file: common/board_f.c
    #if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)
    static int init_func_watchdog_init(void)
    {
    # if defined(CONFIG_HW_WATCHDOG) && \
        (defined(CONFIG_M68K) || defined(CONFIG_MICROBLAZE) || \
        defined(CONFIG_SH) || \
        defined(CONFIG_DESIGNWARE_WATCHDOG) || \
        defined(CONFIG_IMX_WATCHDOG))
        hw_watchdog_init(); //该函数,默认实现会配置好wdt,并enable
        puts("       Watchdog enabled\n");
    # endif
        WATCHDOG_RESET();
    
        return 0;
    }
    
    int init_func_watchdog_reset(void)
    {
            WATCHDOG_RESET();
    
            return 0;
    }
    #endif /* CONFIG_WATCHDOG */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • uboot是裸机程序,所有操作都是顺序执行,开启wdt后,如有耗时操作需要自己调用WATCHDOG_RESET进行喂狗,进到cli时,uboot cli会间隔调用WATCHDOG_RESET喂狗。
  • 相关阅读:
    (附源码)springboot校园商铺系统 毕业设计 052145
    webpack--性能优化之打包构建速度和代码调试优化
    JVM内存模型:理解Java程序的内存管理
    音频转文字怎么操作?快来看看这几个方法吧
    KoTime:v2.3.4新增堆内存、物理内存和CPU使用情况统计
    java注解反射之自定义Retrofit 项目实战
    linux下离线安装JDK,GeoServer,tomcat,nginx,redis,rabbitmq,postgresql。
    【k8s】1、基础概念和架构及组件
    Flink系列-背压(反压)
    解析List接口中的常用的被实现子类重写的方法
  • 原文地址:https://blog.csdn.net/qazw9600/article/details/134310735