EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
转——给NIOS II CPU增加看门狗定时器并使用
Q+ J7 a5 G# O! L$ v* N配置看门狗定时器: - 设置计时溢出时间为1秒
* {0 f* Q8 d" ]& J Y' A; N: s - 计数器位宽为32位: k, Y) j4 {4 B$ H; @. T4 x7 X* x( p
- 勾选No Start/Stop control bits
2 m8 h( p6 ~2 z/ k2 r+ [! O - 勾选Fixed period& F. P, C0 B. N% l. Q: f' @
- 不勾选Readable snapshot
! i' O+ y- ?) u+ b* B2 G/ k$ U - 勾选System reset on timeout.(Watchdog)
7 x9 a8 L- n* F( S) x% e - 不勾选Timeout Pulse (1 clock wide)
M: S, o; k; ]% X, J1 M2 J) ]/ x1 D: z0 Y0 J& W: ]5 a3 _$ P
这部分配置可以参见"Embedded Peripheral IP User Guide.pdf"中Interval Timer Core章下的Configuration节下的Configuring the Timer as a Watchdog Timer小节相关内容。 添加完成后,将核名字改为watchdog(当然也可以自己定义),然后将clk信号连接到系统clk上,reset与所有reset网络信号相连(不包括clk核的reset_in),将s1连接到nios cpu的data_master上,点击连接irq,将resetrequest连接到所有核的reset输入上。 然后生成QSYS系统。 创建Quartus II工程并编写顶层文件。如果是在上一节实验的基础上增加的看门狗核,则不需要对Quartus II工程做任何更改,直接全编译即可。否则请按照我们提供的示例工程创建Quartus II工程并编写顶层文件。 打开NIOS II 开发软件,切换工作空间到当前工程目录,如果整个工程是直接复制上一个实验的工程得到的,则工作空间中还会有上一个实验的软件工程,这里需要首先删除工作空间中已经有的工程,注意,不要删除工程源文件,因为这时候工程源文件还是指向了上一个工程的源文件所在位置,直接删除源文件会破坏上一个实验的工程。然后在software目录下手动删除原有的工程文件。 接着点击【File】->【New】->【Nios II Application and BSP from Template】打开创建新工程和板级支持包向导。 然后选择sopcinfo文件为本工程目录下的sopcinfo文件(注意,软件总是记住上一次选择sopcinfo文件时的路径,因此这里特别容易出错,我们需要手动重新定位目录,软件自动打开的那个目录下的sopcinfo文件往往都是上一个实验的,不能使用)创建hello world模版工程,命名工程为watchdog_test。然后点击finish即可创建新工程。 复制上一个工程中软件工程中的【hardware】文件夹到本工程下的【watchdog_test】文件夹下,最好直接在电脑的文件管理器中进行(对Eclipse使用非常熟练的,请尽情使用拖拽添加的方式)。复制完成后,选中【watchdog_test】工程,单击右键,选择【Refresh】,就可以在工程中看到【hardware】文件夹了。 接着我们添加【hardware】下的【inc】路径到工程头文件包含路径中来。我们选中【watchdog_test】工程,按下键盘组合键"ATRL + Enter"键打开【Properties】设置界面,选择Nios II Application Properties下的Nios II Application Paths,在右侧的Application include directories下,点击Add按钮,添加hardware/inc到包含路径中。然后在弹出的对话框中点击Yes,即可将此路径添加为我们的头文件包含路径。如果用户之后自己有其他的头文件路径需要添加,也是按照这种方法进行。 接着我们查看下Project References中是否勾选了watchdog_test_bsp工程,如果没有勾选的话,当工程关闭了重新打开时,工程有可能会报各种无法理解的错误(当一个workspace中有多个应用工程时)。这里我们需要确认这个选项被勾选上了。 然后我们再在C/C++ General下的Indexer下,勾选按照下图中所示进行勾选。通过这样勾选后,一般工程不管怎么折腾,都不会出现xxxx 'xxxx' could not be resolved的报错了。 设置完成后,我们点击Apply,然后点击OK退出。 然后我们选中【watchdog_test_bsp】工程,单击右键选择【Nios II】->【BSP Editor】,设置sys_clk_timer为none,(软件会默认搜索工程中存在的定时器外设并添加为sys_clk_timer),因此我们这里可能看到打开时默认将watchdog设置为了sys_clk_timer,所以我们要手工更改为none,如果不更改,系统将不能正常运行。Timestame_timer设置为none。Stdin、stdout、stderr都设置为uart_0。(默认为jtag_uart,但是jtag_uart容易导致Eclipse崩溃,因此我一般不用)。设置完毕后点击generate,然后点击exit退出。 接着我们在hardware/src目录下创建一个"watchdog.c"文件,编写内容如下: #include "watchdog.h" ( s$ U* z1 v( U
/****************************************** * 驱动使用的看门狗定时器基地址,独立定义,然后初 * 始化时由用户输入具体基地址名称,避免不同用户对看 * 门狗定时器不同的命名带来的程序移植性问题。 ******************************************/ alt_u32 WTD_BASE;
$ K2 x) D& n" V9 }0 B4 D/****************************************************************** * 名称:WatchDog_Init() * 功能:初始化WatchDog,即开启看门狗定时器; * 需要注意的是,看门狗定时器一旦开启,无法关闭。 * 入口参数:WATCHDOG_BASE :看门狗定时器基地址 * 出口参数:无 ******************************************************************/ void WatchDog_Init(void *MyWatchDog_BASE) { //将系统的watchdog基地址传递给驱动使用的基地址 WTD_BASE = MyWatchDog_BASE; /* 启动 WATCHDOG */ IOWR_ALTERA_AVALON_TIMER_CONTROL(WTD_BASE, ALTERA_AVALON_TIMER_CONTROL_START_MSK); }
" \$ |5 W$ b% @% E# [/****************************************************************** * 名称:WatchDog_Feed() * 功能:看门狗喂狗操作,向看门狗寄存器写入任意值即可完成看门狗复位 * 入口参数:无 * 出口参数:无 ******************************************************************/ void WatchDog_Feed(void) { IOWR_ALTERA_AVALON_TIMER_PERIODL(WTD_BASE, 0x1234); } | - N2 P- c3 R& m0 H9 e0 d" F" {
3 I9 I7 h' H8 Y' s& R
接着我们在hardware/inc目录下创建一个"watchdog.h"文件,编写内容如下: #include "system.h" #include "altera_avalon_timer_regs.h" #include "alt_types.h" //Altera定义的数据类型 & i" ^3 w2 R8 L/ n/ d0 h4 n7 k) e
#ifndef WATCHDOG_H_ #define WATCHDOG_H_ 5 z! E1 W" S" J& n3 ], w, y
void WatchDog_Init(void *MyWatchDog_BASE); void WatchDog_Feed(void);
4 E/ c- {) C4 o5 X0 G#endif /* WATCHDOG_H_ */ | % m9 T) [/ c7 Z% j- I
最后我们编写main文件函数如下所示: /****************************************************************** * 文件名:main.c * 功能:运行WDT,并控制LED0--LED3显示输出。程序开始先对LED0--LED3进行闪烁控制 * 和喂狗处理;然后只点亮LED1,并进入死循环,等待WDT复位。 * 说明: ******************************************************************/ #include <stdio.h> #include "key.h" #include "led.h" #include "uart.h" #include "string.h" #include "stdlib.h" #include "priv/alt_busy_sleep.h" #include "watchdog.h" 2 O! Y: [1 z# R$ f* e2 t
//#define USE_WTD 1 //该宏定义决定系统中的看门狗是否被使用
$ T% v% q/ |+ h3 s* b' B/****************************************************************** * 名称:DelayNS() * 功能:长软件延时,具有喂狗功能。 * 入口参数:dly 延时参数,值越大,延时越久 * 出口参数:无 ******************************************************************/ void DelayNS(alt_u32 dly) { alt_u32 i; for(; dly>0; dly--) { for(i=0; i<1000; i++) { #ifdef USE_WTD WatchDog_Feed(); //喂狗 #endif } } }
# Z9 y* V) w: A3 Z8 u2 t6 K/****************************************************************** * 名称:main() * 功能:初始I/O口及WDT,然后开始先对LED0--LED3闪烁控制,并进行喂狗处理; * 然后只点亮LED1,并进入死循环,等待WDT复位。 * 说明:如果main函数中InitWDT()被使用,则系统会自动复位,现象就是led永远不停的闪烁 * 如果main函数中InitWDT()被屏蔽,则系统无法自动复位,现象就是led闪烁8次后 * 停止下来,led0保持点亮 ******************************************************************/ int main(void) { alt_u8 i; $ {/ I' k: j7 i9 ~+ t
LED_HANDLE hLED; hLED = LED_Init(PIO_LED_BASE); if (!hLED) { printf("Failed to init LED\n"); }
6 J: G8 b8 i/ @) Q3 U8 ?+ d F0 a: I#ifdef USE_WTD //屏蔽此句可以禁止使用看门狗,用来测试不使用看门狗时的系统运行情况 WatchDog_Init(WATCHDOG_BASE); // 初始化看门狗 WatchDog_Feed(); // 进行喂狗操作 #endif
1 |" D9 x* O! d) efor(i=0; i<8; i++) { //点亮LED0和LED2,熄灭LED1和LED3 LED_WriteData(hLED, LED0 | LED2); DelayNS(300); % ?8 D @2 M; X R
//点亮LED1和LED3,熄灭LED0和LED2 LED_WriteData(hLED, LED1 | LED3); DelayNS(300); } //关闭LED0~3 LED_Off(hLED, LED0 | LED1 | LED2 | LED3); LED_On(hLED, LED1); //打开LED1 while(1); return(0); } |
& M* ~/ @9 v' V4 z) O9 ]- o这样我们的软件就编写完成了,接着我们点击键盘的组合键"CTRL + B"(或者依次点击【Project】【Build All】)来编译整个工程。 接着我们在Quartus II中打开配置下载窗口将sof文件下载到FPGA中,然后在Eclipse中点击【Run】->【Run Configuration】,在弹出的界面中,双击左侧的【Nios II Hardware】新建一个下载设置,将name更改为Watchdog_test,与工程名保持一致。右侧Project Name选择Watchdog_test,如下图所示: 然后切换到Target Connection选项卡,查看如果Connections下能找到USB Blaster就行,如果不能找到,就点击Refresh Connections,以让软件找到连接。在System ID Checks下勾选忽略System ID和timestamp,如下图所示: 然后点击Apply,再点击Run即可开始下载。下载完成后,我们看到开发板上的4个LED灯闪烁8次后停止下来,这是因为没有使用watchdog的缘故,程序正常运行到while(1)处进入死循环。 接着,我们将"//#define USE_WTD 1"这一行前面的"//"注释标识符取消,然后重新编译工程,并运行下载。这里我们可以看到,开发板上的4个LED灯将持续不停的闪烁。这是因为当程序运行到while(1)死循环中后,不再有喂狗操作,因此看门够计数溢出,然后复位系统,系统重新开始运行,则LED重新开始闪烁,如此持续不断的进行。 / O3 S1 }3 ]" m) k; P
|