给NIOS II CPU添加一颗澎湃的心——系统时钟的使用

本实验介绍如何在Qsys中添加一个定时器作为NIOS II的心跳定时器,并在NIOS II中软件编程使用该定时器。

将上一个实验watchdog工程复制、粘贴并重命名为08_sysclk_timer。在Quartus II中打开该工程,然后点击Qsys快捷图标打开Qsys组件,如下图所示:

在Qsys中,打开工程目录(08_sysclk_timer)下的mysystem.qsys工程。

打开后,在左侧的IP列表中输入“timer”,然后双击Interval Timer打开参数配置界面:

设置Period 为20,单位(Units)为ms,勾选上Fixed period。其他保持不变,点击finish,则Timer被加入到了我们之前的已有的系统中。

修改timer的名字为sys_clk按照上一节看门狗的连线内容将所有信号连接到对应总线上。

添加的过程中下面信息栏会有报错,暂时不用理会,等我们后面的操作完成后,报错会自动消失。

然后在菜单栏中点击【System】->【Assign Base Addresses】自动分配基地址。如下图所示:

这个时候,应该所有错误都消失了。接着我们在菜单栏中点击【Generate】->【Generate HDL】来生成Quartus II软件可用的设计文件,如下图所示:

生成完成之后,我们点击finish即可关闭Qsys系统,同时Quartus II软件弹出提示对话框,点击OK以关闭。

因为本实验中我们依然没有添加需要引出到外部引脚的IP,引出在Quartus II中对系统的例化文件不需要进行任何修改,直接点击“Start Compilation”(或者使用Ctrl + L组合键)对工程进行全编译即可。

打开NIOS II IDE开发软件。创建NIOS II软件工程和板级支持包工程,选择sopcinfo文件为“E:\easy_sopc\NiosOnlyExp\08_sysclk_timer\mysystem.sopcinfo”(自己根据具体路径修改,注意切换路径)。创建工程名字为sys_clk_test,选择Hello World模版工程,然后点击Finish。如下图所示:

选中bsp工程(sys_clk_test_bsp),进入BSP Editor。

1. 设置sys_clk_timer为“sys_clk”,

2. 设置timestamp_timer为none,

3. 设置stdin、stdout、stderr、为uart_0。

其他不变,点击generate,然后点击exit退出。

复制上一个工程中软件工程中的【hardware】文件夹到本工程下的【sys_clk_test】文件夹下,最好直接在电脑的文件管理器中进行(对Eclipse使用非常熟练的,请尽情使用拖拽添加的方式)。复制完成后,选中【sys_clk_test】工程,单击右键,选择【Refresh】,就可以在工程中看到【hardware】文件夹了。

接着我们添加【hardware】下的【inc】路径到工程头文件包含路径中来。我们选中【sys_clk_test】工程,按下键盘组合键“ATRL + Enter”键打开【Properties】设置界面,选择Nios II Application Properties下的Nios II Application Paths,在右侧的Application include directories下,点击Add按钮,添加hardware/inc到包含路径中。然后在弹出的对话框中点击Yes,即可将此路径添加为我们的头文件包含路径。如果用户之后自己有其他的头文件路径需要添加,也是按照这种方法进行。

接着我们查看下Project References中是否勾选了sys_clk_test_bsp工程,如果没有勾选的话,当工程关闭了重新打开时,工程有可能会报各种无法理解的错误(当一个workspace中有多个应用工程时)。这里我们需要确认这个选项被勾选上了。

然后我们再在C/C++ General下的Indexer下,勾选按照下图中所示进行勾选。通过这样勾选后,一般工程不管怎么折腾,都不会出现xxxx 'xxxx' could not be resolved的报错了。

我们可以选择将系统创建时默认的main函数所在文件hello_world.c文件改名为main.c,修改时只需要选中hello_world.c文件,单击右键,选择rename,然后改为main.c即可。

最后我们编写main文件函数如下所示:

/******************************************************************
* 文 件 名:main.c
* 功 能:利用系统时钟服务产生1s的周期性事件,并借此控制LED闪烁,
*
* 说 明:观察LED闪烁效果。
******************************************************************/
#include <stdio.h>
#include "system.h" //包含基本的硬件描述信息
#include "led.h"
#include "sys/alt_alarm.h" //系统时钟服务头文件
#include "altera_avalon_pio_regs.h" //包含基本的IO寄存器信息
#include "alt_types.h" //Altera定义的数据类型 static alt_alarm alarm; //按调用API函数规定定义的变量 alt_u8 led_data; LED_HANDLE hLED; /******************************************************************
* 名 称:my_alarm_callback
* 功 能:按调用规定系统时钟回调函数,在该函数中实现用户功能
* 入口参数:context,系统传给回调函数的参数
* 出口参数:返回下一次的系统时钟服务的周期值
******************************************************************/
alt_u32 my_alarm_callback(void* context) {
if (led_data == 0x0f) {
led_data = 0x00;
} else {
led_data = 0x0f;
}
LED_WriteData(hLED, led_data); //一次性控制所有LED的亮灭
return alt_ticks_per_second();
} int main() {
//初始化LED
hLED = LED_Init(PIO_LED_BASE); if (!hLED) {
// printf("Failed to init LED\n");
} //熄灭所有LED
LED_Off(hLED, LED0 | LED1 | LED2 | LED3); printf("test alarm...\n"); //打印提示信息
printf("alt_ticks_per_second() is %ld", alt_ticks_per_second()); //启动系统时钟服务
if (alt_alarm_start(&alarm, alt_ticks_per_second()
, my_alarm_callback, NULL) < ) {
printf("No system clock available\n");
}
while ()
; //等待时钟事件发生
return ;
}

这样我们的软件就编写完成了,接着我们点击键盘的组合键“CTRL + B”(或者依次点击【Project】【Build All】)来编译整个工程。

接着我们在Quartus II中打开配置下载窗口将sof文件下载到FPGA中,然后在Eclipse中点击【Run】->【Run Configuration】,在弹出的界面中,双击左侧的【Nios II Hardware】新建一个下载设置,将name更改为sys_clk_test,与工程名保持一致。右侧Project Name选择sys_clk_test,如下图所示:

运行后在芯航线FPGA开发板上可以看到,4个LED每隔1秒闪烁一次。

补充阅读:

不常用操作系统的工程师很少碰到alarm这个概念,在他们心目中 alarm实质上就是一个简单的定时器周期中断事件。在操作系统中,alarm却是一个常用的概念,比如,当一个进程需要等待某个事件发生又不想永远等待下去时.该进程会设置一个超时(timeout)值。当这个超时值到达时,操作系统会向进程发送一个alarm(警告信号),提醒进程不要再等待。在Nios II中,alarm也可以同样理解为是打断正在执行的流程,提醒系统不要等待的信号。

如何初始化系统时钟服务?按照一般思路,先初始化定时器,再编写定时器中断服务程序。但是,在HAL层上进行应用程序开发不必如此,因为与硬件细节相关的初始化过程都由系统替用户完成了。用户在使用某项服务前,只需要开启该项服务即可。

使用HAL提供的系统时钟服务大致分为3个步骤:

1) 调用alt_alarm_start()开启系统时钟服务,该函数位于BSP工程下的HAL\src 文件夹下的 alt_alarm_start. c 中。

2) 按照格式要求编写回调函数。该回调函数将实现用户的功能。

3) 调用alt_alarm_stop()关闭系统时钟服务。该函数位于BSP工程下的HAL\src 文件夹下的 alt_tick. c中。

通过接口函数访问定时器对象中的变量,为了达到隐藏信息的目的,Altera公司提 供了一个接口函数alt_ticks_per_second()供用户获得一个设定alarm服务周期为1 s的变量值。

系统时钟服务API函数分析:

1 开启系统时钟服务函数:alt_alarm__start()

函数原型:

int alt_alarm_start (
alt_alarm * alarm,
alt_u32 nticks,
alt_u32 (* callback) (void* context),
void* context)

函数功能:启动系统时钟服务。

输入参数:

alarm——一个指向alt_alarm结构体类型的指针变量,用户需要为每个系统时钟服务创建一个alt_alarm类型变量。系统由该变量对系统时钟服务进行维护。例如,用户需要两个系统时钟服务,则需要定义alt_alarm alarm_1和alt_alarm alarm_2。

nticks——指示每隔nticks执行一次回调函数。如果定时器预设的中断周期为1 ms,则每个tick的时间间隔为1 ms。如果用户希望获得1 s—次的服务, 则nticks的输人值为1 s/1 ms=1000。

Callback——用户回调函数指针。

Context—-传给回调函数的参数,一般为寄存器的地址,也可以是其它参数。如果不需要传递参数则此处填入NULL。

② 用户回调函数:my_alarm_callback()

函数原型:

alt_u32 my_alarm_callback (void * context)

输人参数:

context —— alt_alarm_start()函数传人的参数,函数名可以自己定义,但是函数原型一定要按上述格式书写。

注意:不要在回调函数中实现复杂的功能,因为回调函数实际是定时器中断服务函数的

一部分。

③停止系统时钟服务函数alt_alarm_stop()

函数原型:

void alt_alarm_stop ( alt_alarm * alarm )

输入参数:

alarm—— —个指向ah_alarm结构体类型的指针变量,用户希望停止哪一个系统时钟服务,即把该时钟服务对应的alarm变童传给alt_alarm_stop()。至此,通过HAL API函数使用系统时钟服务的方法已总结完毕,其它API函数本文不再叙述,读者可参阅Altera公司提供的API函数手册。

最后留一个问题供读者思考,如何开启 3个系统时钟服务,使得3个LED分别以2 Hz、l Hz和0.5 Hz的频率闪烁?

如有更多问题,欢迎加入芯航线 FPGA 技术支持群交流学习:一群 472607506(已满)  二群  615381411

小梅哥

芯航线电子工作室

【小梅哥SOPC学习笔记】系统时钟的使用的更多相关文章

  1. 【小梅哥SOPC学习笔记】SOPC开发常见问题及解决办法集锦

    SOPC开发常见问题及解决办法集锦 一.Symbol 'NULL' could not be resolved 近期在评估使用NIOS II处理器进行项目的开发,我使用的软件是Quartus II 1 ...

  2. 【小梅哥SOPC学习笔记】切换NIOS II CPU的主内存后软件中需要注意的几点设置

    切换NIOS II CPU的主内存后软件中需要注意的几点设置 有时候,我们可能面对这样一种情况: 1. 我们创建一个SOPC系统,并在QSYS中设置NIOS II的复位地址和异常地址都指向SRAM: ...

  3. 【小梅哥SOPC学习笔记】NIOS II处理器运行UC/OS II

    SOPC开发流程之NIOS II 处理器运行 UC/OS II 这里以在芯航线FPGA学习套件的核心板上搭建 NIOS II 软核并运行 UCOS II操作系统为例介绍SOPC的开发流程. 第一步:建 ...

  4. 【小梅哥SOPC学习笔记】sof与NIOS II的elf固件合并jic得到文件

    sof与NIOS II的elf固件合并jic得到文件 注意,本方法已经有更加简便的方法,小梅哥提供相应的脚本文件,可以一键生成所需文件,脚本请前往芯航线FPGA技术支持群获取. 7.1 为什么需要将S ...

  5. 【小梅哥SOPC学习笔记】NIOS II工程目录改变时project无法编译问题

    解决NIOS II工程移动在磁盘上位置后project无法编译问题 说明:本文档于2017年3月4日由小梅哥更新部分内容,主要是增加了讲解以Quartus II13.0为代表的经典版本和以15.1为代 ...

  6. 【小梅哥SOPC学习笔记】给NIOS II CPU增加看门狗定时器并使用

    给NIOS II CPU增加看门狗定时器并使用 配置看门狗定时器: 1. 设置计时溢出时间为1秒 2. 计数器位宽为32位 3. 勾选No Start/Stop control bits 4. 勾选F ...

  7. 【小梅哥SOPC学习笔记】设置Eclipse在编译(build)前自动保存源代码文件

    设置Eclipse在编译(build)前自动保存源代码文件 Eclipse 常用设置之让Eclipse在编译(build)前自动保存源代码文件 一.让Eclipse在编译(build)前自动保存源代码 ...

  8. 【小梅哥SOPC学习笔记】Altera SOPC嵌入式系统设计教程

    Altera SOPC嵌入式系统设计教程 第1章 概述 SOPC(System On Programmable Chip,可编程的片上系统)是Altera公司提出来的一种灵活.高效的SOC解决方案.它 ...

  9. 《A Tour of PostgreSQL Internals》学习笔记——系统表和数据类型

    上周末学习了<A Tour of PostgreSQL Internals>的第一部分(View 1),今天我们继续打开书本,继续View 2 部分. View 2 Postgresql的 ...

随机推荐

  1. win系统主机上的虚拟机NAT模式可修改3389端口做远程登录

    当你只有一个公网IP的时候,那么这个IP基本上是要分给物理主机的,那么本机的虚拟机就只能选NAT网络模式了,那么想在外网直接远程虚拟机的话,修改虚拟机的远程登录端口(不修改也可以,主要是主机的3389 ...

  2. sgdisk基本用法

    简介 sgdisk是Linux下操作GPT分区的工具,就像fdisk是操作MBR分区的工具.关于GPT和MBR的区别请参考: http://www.anchor.com.au/blog/2012/10 ...

  3. php中$_POST接收不到参数问题

    问题描述:PHP可以接收_GET._SERVER._COOKIE等参数,php://input可以读取没有处理过的POST数据,独独_POST接收不到post参数.  原因: php://input可 ...

  4. Linux6系统安装

  5. leetcode278

    /* The isBadVersion API is defined in the parent class VersionControl. bool IsBadVersion(int version ...

  6. delphi 线程 TTask

    http://docwiki.embarcadero.com/Libraries/Seattle/en/System.Threading.TTask http://docwiki.embarcader ...

  7. “数据提供程序或其他服务返回 E_FAIL 状态”

    “数据提供程序或其他服务返回 E_FAIL 状态” 的问题 ADO 连接SQL SERVER

  8. [转]DWZ表单验证规则一览表(留着自己用)

    <form onsubmit="return validateCallback(this)" class="pageForm" action=" ...

  9. VS Code 在新Tabs打开文件

    添加如下设置即可 "workbench.editor.enablePreview": false

  10. 如何设置tomcat,直接通过IP 访问

    找到tomcat的主目录,进入conf文件夹,找到server.xml文件,并打开:   修改tomcat的监听端口为80端口: 在server.xml文件中找到: <Connector por ...