找回密码
 注册
关于网站域名变更的通知
查看: 704|回复: 1
打印 上一主题 下一主题

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

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-3-27 13:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
转——给NIOS II CPU添加一颗澎湃的心——系统时钟的使用# V( H! ?! E# P5 |, d
本实验介绍如何在Qsys中添加一个定时器作为NIOS II的心跳定时器,并在NIOS II中软件编程使用该定时器。
将上一个实验watchdog工程复制、粘贴并重命名为08_sysclk_timer。在Quartus II中打开该工程,然后点击Qsys快捷图标打开Qsys组件,如下图所示:
在Qsys中,打开工程目录(08_sysclk_timer)下的mysystem.qsys工程。
打开后,在左侧的IP列表中输入“timer”,然后双击Interval Timer打开参数配置界面:
  o, x$ V& a3 Q% I; D) _
设置Period 为20,单位(Units)为ms,勾选上Fixed period。其他保持不变,点击finish,则Timer被加入到了我们之前的已有的系统中。
& t$ @* I4 r! g0 N
修改timer的名字为sys_clk按照上一节看门狗的连线内容将所有信号连接到对应总线上。
! c3 r  Q1 a( F; a
添加的过程中下面信息栏会有报错,暂时不用理会,等我们后面的操作完成后,报错会自动消失。
然后在菜单栏中点击【System】->【Assign Base Addresses】自动分配基地址。如下图所示:
8 _) T  y6 c( s) M  ]
这个时候,应该所有错误都消失了。接着我们在菜单栏中点击【Generate】->【Generate HDL】来生成Quartus II软件可用的设计文件,如下图所示:
& j+ _$ L8 G5 v. G4 n
生成完成之后,我们点击finish即可关闭Qsys系统,同时Quartus II软件弹出提示对话框,点击OK以关闭。
5 V) }; k5 J  Q0 [8 z
因为本实验中我们依然没有添加需要引出到外部引脚的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。如下图所示:

+ q1 j& j$ o' {# f8 Y4 k
选中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】文件夹了。
  w7 ~5 S# S7 \+ V
接着我们添加【hardware】下的【inc】路径到工程头文件包含路径中来。我们选中【sys_clk_test】工程,按下键盘组合键“ATRL + Enter”键打开【Properties】设置界面,选择Nios II Application Properties下的Nios II Application Paths,在右侧的Application include directories下,点击Add按钮,添加hardware/inc到包含路径中。然后在弹出的对话框中点击Yes,即可将此路径添加为我们的头文件包含路径。如果用户之后自己有其他的头文件路径需要添加,也是按照这种方法进行。
0 ?- m0 k6 k* P/ v# }- y
接着我们查看下Project References中是否勾选了sys_clk_test_bsp工程,如果没有勾选的话,当工程关闭了重新打开时,工程有可能会报各种无法理解的错误(当一个workspace中有多个应用工程时)。这里我们需要确认这个选项被勾选上了。

% G. p% c: s2 x) z' N3 f  Z
然后我们再在C/C++ General下的Indexer下,勾选按照下图中所示进行勾选。通过这样勾选后,一般工程不管怎么折腾,都不会出现xxxx 'xxxx' could not be resolved的报错了。
我们可以选择将系统创建时默认的main函数所在文件hello_world.c文件改名为main.c,修改时只需要选中hello_world.c文件,单击右键,选择rename,然后改为main.c即可。
最后我们编写main文件函数如下所示:

1 Z5 r' N- v% g' M) N/****************************************************************** * 文 件 名: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) < 0) {        printf("No system clock available\n");    }    while (1)        ;  //等待时钟事件发生    return 0;}. v9 H6 W  m( M1 ~* m& ]7 ]4 U6 [% }
$ x4 Q3 r8 }5 F. R3 ?2 H/ h3 A/ \

; O2 N. M: Q- C& y& S- x
. T; e) |$ @" M. S1 A7 x
  Q7 @6 ^% r( t  l7 k. A: A$ Q
这样我们的软件就编写完成了,接着我们点击键盘的组合键“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,如下图所示:
7 L+ I, S  P  _* x  k  Z) I
运行后在芯航线FPGA开发板上可以看到,4个LED每隔1秒闪烁一次。
7 L0 j9 K' u+ o0 A5 X; e8 B
补充阅读:
不常用操作系统的工程师很少碰到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)% g: ]8 G+ V5 W2 m8 f
$ h; f& K; A* h% ^
函数功能:启动系统时钟服务。
输入参数:
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)* e) ~* F8 S5 i9 P

/ {! i) Q2 T) N4 g
输人参数:
context —— alt_alarm_start()函数传人的参数,函数名可以自己定义,但是函数原型一定要按上述格式书写。
注意:不要在回调函数中实现复杂的功能,因为回调函数实际是定时器中断服务函数的
一部分。
③停止系统时钟服务函数alt_alarm_stop()
函数原型:
void alt_alarm_stop ( alt_alarm * alarm ). A, h, ~9 f3 |+ i7 w, K. g
" Y7 y6 s$ K/ V: x9 [+ p
输入参数:
alarm—— —个指向ah_alarm结构体类型的指针变量,用户希望停止哪一个系统时钟服务,即把该时钟服务对应的alarm变童传给alt_alarm_stop()。至此,通过HAL API函数使用系统时钟服务的方法已总结完毕,其它API函数本文不再叙述,读者可参阅Altera公司提供的API函数手册。

+ W7 m7 x4 h! N& Z1 c8 o; |+ {
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-7-29 03:43 , Processed in 0.109375 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表