AM437X uboot增加硬件看门狗

一、说明

刚开始想的方案是利用uboot中的看门狗定时器,在中断里面进行喂狗。但是经过几天的折腾,内部看门狗打开后达到溢出条件就会直接复位,没办法进入中断,而且复位动作没找到屏蔽的方法,所以只能放弃这个方案。
之后在网上搜到了一篇关于am335x uboot 看门狗喂狗的文章,写的很详细,根据这篇文章解决了这个问题。

参考:335x uboot 看门狗喂狗
链接:https://blog.csdn.net/zjy900507/article/details/78797833

二、uboot 代码修改

1、在include/watchdog.h文件中有宏定义

#ifdef CONFIG_HW_WATCHDOG 
       #if defined(__ASSEMBLY__) 
               #define WATCHDOG_RESET bl hw_watchdog_reset 
       #else 
               extern void hw_watchdog_reset(void); 
               #define WATCHDOG_RESET hw_watchdog_reset 
       #endif 

其实,在uboot已经在源码中比较耗时、需要喂狗的地方穿插了喂狗函数。
所以,我们只需要打开CONFIG_HW_WATCHDOG开关以及实现hw_watchdog_reset喂狗函数。

2、打开硬件看门狗,在板级头文件中include/configs/am437x_evm.h文件中加上宏定义

#define CONFIG_HW_WATCHDOG 1 
#define GPIO_WATCHDOG         (3<<5 | 23)

GPIO_WATCHDOG这个值的设置是通过分析uboot源码中gpio_set_value()函数才知道如何设置。
根据原理图找到引脚,然后在数据手册中搜索,查看复用GPIO引脚
根据原理图找到引脚,然后在数据手册中搜索,查到看门狗复用GPIO引脚为gpio3_23

3、然后在板级文件board/ti/am437x/board.c中加入看门狗初始化函数以及喂狗函数hw_watchdog_reset

#ifdef CONFIG_HW_WATCHDOG
void hw_watchdog_reset(void)
{
	if (gpio_get_value(GPIO_WATCHDOG))
	{
		gpio_set_value(GPIO_WATCHDOG, 0);
	}
	else
	{
		gpio_set_value(GPIO_WATCHDOG, 1);
	}
}

void hw_watchdog_init(void)
{
	enable_wdt_pin_mux();
	gpio_request(GPIO_WATCHDOG, "gpio_watchdog");
	gpio_direction_output(GPIO_WATCHDOG, 0);
}
#endif

4、在board/ti/am437x/mux.c添加引脚初始化代码,并在board/ti/am437x/board.h中加上函数声明。

static struct module_pin_mux wdt_pin_mux[] = {
	    {OFFSET(spi2_d1), (MODE(7) | PULLUDEN)},	/* SPI2_D1 */
	    {-1},
};

void enable_wdt_pin_mux(void)
{
	    configure_module_pin_mux(wdt_pin_mux);
}

5、在common/board_f.c里面已经调用了看门狗初始化函数并喂狗。最后编译,uboot烧写后即可使用。

三、问题

用SD卡烧写文件系统即大文件的时候系统会重启,原因应该是读写SD卡文件的函数没有进行喂狗,
解决办法:
SD卡烧写文件系统时喂狗
在drivers/mmc/omap_hsmmc.c文件中加上头文件
#include <watchdog.h>
修改函数如下:

static int mmc_read_data(hsmmc_t *mmc_base, char *buf, unsigned int size) 
{ 
…………………………………….. 
      while (size) { 
             /*add gpio3_23 for watchdog*/ 
             WATCHDOG_RESET(); 
              
             ulong start = get_timer(0); 
             do { 
                    mmc_stat = readl(&mmc_base->stat); 
                    if (get_timer(0) - start > MAX_RETRY_MS) { 
                           printf("%s: timedout waiting for status!\n", 
                                         __func__); 
                           return TIMEOUT; 
                    } 
             } while (mmc_stat == 0); 
………………………………. 
} 
static int mmc_write_data(hsmmc_t *mmc_base, const char *buf, unsigned int size) 
{ 
……………………… 
while (size) { 
             /*add gpio3_23 for watchdog*/ 
             WATCHDOG_RESET(); 
              
             ulong start = get_timer(0); 
             do { 
                    mmc_stat = readl(&mmc_base->stat); 
                    if (get_timer(0) - start > MAX_RETRY_MS) { 
                           printf("%s: timedout waiting for status!\n", 
                                         __func__); 
                           return TIMEOUT; 
                    } 
             } while (mmc_stat == 0); 
………………………. 
}

猜你喜欢

转载自blog.csdn.net/qq_34743935/article/details/94838991