干货:PSoC SWDT在Standalone下的应用

描述

01、Author

Hank Fu (付汉杰) Staff FAE embedded, Xilinx, Inc. hankf@xilinx.com

02、问题

 有工程师反映,根据 MPSoC SWDT 在 Standalone 下的例子 xwdtps_polled_example.c,不能实现 MPSoC 的 PS 复位。SWDT 例子来自于目录 /Xilinx/SDK/2018.3/data/embeddedsw/XilinxProcessorIPLib/drivers/wdtps_v3_1/examples/。SWDT 例子 xwdtps_polled_example.c 只检查了超时状态,没有实现复位。工程师把其中的“XWdtPs_DisableOutput(&Watchdog, XWDTPS_RESET_SIGNAL)”改为“XWdtPs_EnableOutput(&Watchdog, XWDTPS_RESET_SIGNAL)”,仍然不能复位。


工程师根据 FSBL 的 main.c 中的 InitWatchDog( ),添加代码后,依然不能使 MPSoC 的 PS 复位。

03、分析 

3.1. FSBL 的 main.c

main.c 是 Zynq-7000 的 FSBL 的代码。客户使用 SOurce Insight 分析代码时,使用了错误的文件。

3.2. MPSoC 的 FSBL
MPSoC 的 FSBL 的主文件是 xfsbl_main.c,wdt 的代码在 xfsbl_misc_drivers.c 和 xfsbl_misc_drivers.h 中,初始化 WDT 的函数是 u32 XFsbl_InitWdt(void),宏定义 XFSBL_WDT_EXPIRE_TIME 定义了 FSBL 中 wdt 的超时时间。

在 XFsbl_InitWdt(void)中,初始化并启动 WDT(XWdtPs_RestartWdt( ))后,直接使用 sleep(20),睡眠 20 秒。睡眠过程中,因为 WDT 超时,MPSoC 的 PS 会被复位。这说明 FSBL 关于 WDT 代码是正确的。

3.3. Standalone 下的 WDT
对比 MPSoC FSBL 初始化 WDT 的函数 XFsbl_InitWdt( ),发现它设置了 PMU 的 ERROR_SRST_EN_1 Register 和 ERROR_EN_1 Register。把相关代码复制到 Standalone 下的代码,在初始化 WDT 之前运行。重新编译后,WDT 超时会复位 MPSoC 的 PS。

3.4. 再次运行时,设置 PMU 的 ERROR_SRST_EN_1 后,PS 马上复位。

WDT 超时后,再次使用 Debugger 运行时,设置 PMU 的 ERROR_SRST_EN_1 后,WDT 还没有被初始化时,PS 马上被复位。检查 PMU ERROR_STATUS_1 Register,发现 WDT 的超时状态为 1。于是把读取到的 ERROR_STATUS_1 的值,再写回 ERROR_STATUS_1 Register,清除 WDT 的超时状态。

这样在 WDT 超时后,设置 PMU 的 ERROR_SRST_EN_1 后,PS 不会马上被复位。

3.5. FPD_SWDT 和 LPD_SWDT

工程师发现使用 LPD_SWDT,能复位 PS;换成 FPD_SWDT,不能复位 PS。


在设置 PMU 的 ERROR_SRST_EN_1 Register 和 ERROR_EN_1 Register 时,LPD_SWDT 和 FPD_SWDT 有各自的使能位。增加设置 FPD_SWDT 的使能位后,换成 FPD_SWDT,也能复位 PS。

#define PMU_GLOBAL_ERROR_SRST_EN_1    ( ( PMU_GLOBAL_BASEADDR ) + 0X0000056CU )
#define PMU_GLOBAL_ERROR_SRST_EN_1_LPD_SWDT_MASK    0X00001000U
#define PMU_GLOBAL_ERROR_SRST_EN_1_FPD_SWDT_MASK    0X00002000U


04、Vivado 设置

使用 WDT,要在 Vivado 里的 PCW 里,使能对应的 WDT。


05、相关代码 

5.1. 检查和清除 PMU 寄存器

    xil_printf("/r/n" );
    u32_reg = Xil_In32(0xFFD80530);
    xil_printf("Old PMU ERROR_STATUS_1 (PMU_GLOBAL) Register: %x./r/n", u32_reg );
    Xil_Out32(0xFFD80530, u32_reg); // Clear PMU ERROR_STATUS_1 (PMU_GLOBAL) Register

    u32_reg = Xil_In32(0xFFD80540);
    xil_printf("Old PMU ERROR_STATUS_2 (PMU_GLOBAL) Register: %x./r/n", u32_reg );
    Xil_Out32(0xFFD80540, u32_reg); // Clear PMU ERROR_STATUS_2 (PMU_GLOBAL) Register

    u32_reg = Xil_In32(0xFFD80530);
    xil_printf("New PMU ERROR_STATUS_1 (PMU_GLOBAL) Register: %x./r/n", u32_reg );

    u32_reg = Xil_In32(0xFFD80540);
    xil_printf("New PMU ERROR_STATUS_2 (PMU_GLOBAL) Register: %x./r/n", u32_reg );


5.2. 检查 SWDT 寄存器状态

void CheckWDTRegisterValue( u32 EffectiveAddress )
{
    u32 u32_reg;

    u32_reg = XWdtPs_ReadReg(EffectiveAddress, XWDTPS_ZMR_OFFSET);
    xil_printf("WDT Zero Mode Register: %x./r/n", u32_reg );
    u32_reg = XWdtPs_ReadReg(EffectiveAddress, XWDTPS_CCR_OFFSET);
    xil_printf("WDT Counter Control Register: %x./r/n", u32_reg );
    u32_reg = XWdtPs_ReadReg(EffectiveAddress, XWDTPS_RESTART_OFFSET);
    xil_printf("WDT Restart Register: %x./r/n", u32_reg );
    u32_reg = XWdtPs_ReadReg(EffectiveAddress, XWDTPS_SR_OFFSET);
    xil_printf("WDT Status Register: %x./r/n", u32_reg );
}

审核编辑 黄昊宇

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分