怎样使用nios里的sys

怎样使用nios里的sys,第1张

步骤1 在SOPC Builder中例化Interval Timer核:

1. 在SOPC Builder中例化Interval Timer核,命名为sys_clk_timer。

图1 例化Interval Timer核

注意:命名为sys_clk_timer只是为了和BSP中sys_clk_timer一致,也可以命名为其他名称。

图2 BSP中的相关设置

2. 配置Interval Timer核

图3 配置Interval Timer核

Timerout period配置为1ms,表示每个tick是1ms;关于tick的概念,后面会提到。Timer counter size默认为32位。Hardware options可以自行配置;因为此处只是用到了sys_clk_timer服务,所以选择默认选项之一Simple periodic interrupt即可,即简单的周期中断。关于Timerout period的概念,手册中的介绍如下,大家可自行阅读。

图4 手册中的Timerout period的概念

注意:由于Writeable period选项没有用,所以Timerout period是固定的。

步骤2 NIOS II EDS中编写相应的C程序

1. 查看system.h中的相应内容

#define ALT_MODULE_CLASS_sys_clk_timer altera_avalon_timer

#define SYS_CLK_TIMER_ALWAYS_RUN 1

#define SYS_CLK_TIMER_BASE 0x1002000

#define SYS_CLK_TIMER_COUNTER_SIZE 32

#define SYS_CLK_TIMER_FIXED_PERIOD 1

#define SYS_CLK_TIMER_FREQ 125000000u

#define SYS_CLK_TIMER_IRQ 2

#define SYS_CLK_TIMER_IRQ_INTERRUPT_CONTROLLER_ID 0

#define SYS_CLK_TIMER_LOAD_VALUE 124999ULL

#define SYS_CLK_TIMER_MULT 0.0010

#define SYS_CLK_TIMER_NAME "/dev/sys_clk_timer"

#define SYS_CLK_TIMER_PERIOD 1

#define SYS_CLK_TIMER_PERIOD_UNITS "ms"

#define SYS_CLK_TIMER_RESET_OUTPUT 0

#define SYS_CLK_TIMER_SNAPSHOT 0

#define SYS_CLK_TIMER_SPAN 32

#define SYS_CLK_TIMER_TICKS_PER_SEC 1000u

#define SYS_CLK_TIMER_TIMEOUT_PULSE_OUTPUT 0

#define SYS_CLK_TIMER_TYPE "altera_avalon_timer"

第5行,固定的Timerout period,为1;第13行,是Timerout period的单位。

第17行,由于每个tick是1ms,因此1s有1000个ticks。

第6行,Nios II软核的输入时钟频率,此处为125MHz。

2. 示范程序

#include "system.h" // SOPC Builder配置后的存储映射头文件

#include "altera_avalon_pio_regs.h" // PIO核的存储映射头文件

#include "alt_types.h" // Altera的数据类型

#include "sys/alt_alarm.h" // Interval Timer核的驱动头文件

#include "unistd.h" // NULL

// 用户回调函数

alt_u32 timer_CallBackFunc(void* context)

alt_alarm timer_addr // 指向结构体alt_alarm的指针

alt_u32 ticks_num = 100 // 100 ticks * 1 ms/tick = 100 ms

int main()

{

/*

* 函数功能:启动sys_clk_timer服务

* 函数备注:#include "sys/alt_alarm.h"

* 入口参数:timer_addr,指向结构体alt_alarm的指针

*ticks_num,每隔ticks_num执行一次回调函数

*timer_CallBackFunc,用户回调函数

*context,传给用户回调函数的参数,此处为NULL

*/

alt_alarm_start(&timer_addr, ticks_num, timer_CallBackFunc, NULL)

while(1)

return 0

}

/*

* 函数功能:用户回调函数

* 函数备注:用户自己编写

* 入口参数:*context, 从alt_alarm_start()传来的参数

* 出口参数:ticks_num, sys_clk_timer服务的周期数

*/

alt_u32 timer_CallBackFunc(void* context)

{

static alt_u8 temp = 0 // static 定义时,只可赋值一次

IOWR_ALTERA_AVALON_PIO_DATA(Q_LED_BASE, temp)

temp = ~temp// 翻转temp

return ticks_num// 返回下一次sys_clk_timer服务的ticks_num

}

对应前面提到的Simple periodic interrupt,34行到40行的用户回调函数,可以看作是定时器中断服务程序;23行的alt_alarm_start()可以看作是定时器中断的注册函数。ticks_num有什么用呢,前面已经提到1个tick是1ms(SOPC Builder中配置的),那么一旦定时器使用alt_alarm_start()运行起来,回调函数就会每ticks_num*1ms/tick执行一次。

注意:第36行,用户回调函数内,变量的声明必须加上关键字static,以防止被编译器优化以致错误出现。第23行的ticks_num为首次sys_clk_timer服务的ticks_num;第39行的ticks_num为下一次sys_clk_timer服务的ticks_num;两者可以不同;读者可以在第36行用数字替换试试。还有每个tick的时间只与SOPC Builder中的配置有关,和Nios II软核的输入时钟没有太大的关系。

至于为什么叫回调函数,我们可以打开sys/alt_alarm.h,查看相关函数的原型。此处由于水平有限,不做相关解析。请读者自行分析。

/*

* "alt_alarm" is a structure type used by applications to register an alarm

* callback function. An instance of this type must be passed as an input

* argument to alt_alarm_start(). The user is not responsible for initialising

* the contents of the instance. This is done by alt_alarm_start().

*/

typedef struct alt_alarm_s alt_alarm

/*

* alt_alarm_start() can be called by an application/driver in order to register

* a function for periodic callback at the system clock frequency. Be aware that

* this callback is likely to occur in interrupt context.

*/

extern int alt_alarm_start (alt_alarm* the_alarm,

alt_u32nticks,

alt_u32(*callback) (void* context),

void* context)

/*

* alt_alarm_stop() is used to unregister a callback. Alternatively the callback

* can return zero to unregister.

*/

extern void alt_alarm_stop (alt_alarm* the_alarm)

/*

* Obtain the system clock rate in ticks/s.

*/

static ALT_INLINE alt_u32 ALT_ALWAYS_INLINE alt_ticks_per_second (void)

{

return _alt_tick_rate

}

/*

* alt_sysclk_init() is intended to be only used by the system clock driver

* in order to initialise the value of the clock frequency.

*/

static ALT_INLINE int ALT_ALWAYS_INLINE alt_sysclk_init (alt_u32 nticks)

{

if (! _alt_tick_rate)

{

_alt_tick_rate = nticks

return 0

}

else

{

return -1

}

}

/*

* alt_nticks() returns the elapsed number of system clock ticks since reset.

*/

static ALT_INLINE alt_u32 ALT_ALWAYS_INLINE alt_nticks (void)

{

return _alt_nticks

}

AVALON总线的reset信号有两种,就像你说的那样,reset_n是低有效,而reset是高有效。

在Qsys中把不同组件的reset_n和reset管脚连在一起不是说它们在电气上就是等电势的了,只是说它们会一同有效或者无效。所以把所有的reset_n和reset连在一起是没问题的。

至于CPU不能运行,你又怀疑reset有问题的话,你可以试试把这几个信号都引出至FPGA外部,人为给它们施加信号或是用示波器直接测量,应该能找到问题。

先说它们分别是什么:

QuartusII是Altera的软件,用来开发FPGA和CPLD的,就像keil用来开发51单片机一样

NiosII是一个32位处理器软核,就像51一样是一个单片机,只不过不是像51单片机那样的硬件实物,而是由硬件描述语言构成的一个软核,配置到FPGA里面就能当单片机用了

FPGA板当然是指的上面有FPGA的一块电路板啦,一般是学习版开发板什么的,供学习开发用,好比51开发板

它们之间的联系是:

QuartusII是Altera公司生产的专门针对他们公司生产的FPGA和CPLD的开发软件,NiosII也是他们公司2004年推出的一个32位软核,它的软件开发工具是NiosII IDE,硬件配置工具是SOPC Builder(这个工具在QuartusII软件里面集成了,在QuartusII的Tool里面能看到)

它们的联系具体表现在基于NiosII的开发过程:

1、一般开发NiosII的过程是先通过SOPC Builder配置一个拥有特定外设NiosII(这步生成的是VHDL或Verilog文件)

2、然后在QuartusII里面综合,配置,分配引脚,(这步可以说是生成了特定的硬件NiosII的CPU了,其实是一个FPGA的配置网表文件)

3、然后在NiosII IDE里面为上面生成的NiosIICPU编写软件,编译,连接,调试什么的

4、上面的都完成后,就可以将第二步生成的FPGA配置文件下到FPGA开发板上的FPGA里面了(这里终于用到FPGA板了,汗!),然后再通过NiosII IDE将它的软件下到RAM或flash里面,这样就可以运行了

其实上面的开发过程类似于对51的开发过程,只是51直接从第三步开始,并且不用下载硬件配置文件,直接上软件而已

至于各个工具的具体使用就不是这样能说清楚的了,自己到网上去下教程吧


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/bake/11558173.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-17
下一篇2023-05-17

发表评论

登录后才能评论

评论列表(0条)

    保存