SOPC之NiosⅡ系统(五)

news2024/12/23 22:07:16

NIOS Ⅱ系统实例 

目录

2.创建BSP工程

2.1 创建BSP工程

2.2 BSP Editor

2.3 创建C代码文件

3.Nios Ⅱ实例

3.1 Hello NIOS Ⅱ

3.2 System ID与Timestamp

3.3 蜂鸣器定时鸣叫

3.4 拨码开关输入GIO控制

4.FPGA器件的代码固化

4.1 嵌入式软件HEX文件生成

4.2 程序存储器初始化文件加载

4.3 JIC文件生成和烧录配置


2.创建BSP工程

2.1 创建BSP工程

进行Nios Ⅱ嵌入式软件开发

点击Tool->Nios Ⅱ Software Buid Tools for Eclipse,创建工作空间

点击File->New->Nios Ⅱ Application and BSP from Template新建项目

点击Target hardware information中的[...] 按钮选择Quartus工程下的.sopcinfo文件,Nios II SBT for Eclipse软件会自动识别Qsys系统中CPU的名称

然后给创建的 Nios Ⅱ工程命名(名称需要以英文字母开头,可以包含字母、数字和下划线,不能有中文及特殊字符)

在取消勾选Use default location后可以修改然后将工程存放的位置

在Project template一栏中列出了一些工程模板,也可以选择创建空白工程 (Bland Project)

点击下方Next系统会自动创建一个BSP(Board Support Package,板级支持包)工程,提供了访问底层硬件(Qsys 系统)的函数库

 .sopcinfo文件是Qsys系统生成时一同产生,包含了所有Qsys系统的硬件信息,将它导入到BSP工程使得BSP获得全部硬件信息

在Project Explorer下出现了nios2bsp_bsp工程,可以看到这个文件夹下包含了各种和当前Qsys系统相关的板级动源文件和头文件,供应用软件调用。

头文件system.h将Qsys系统中的 Nios Ⅱ处理器和所有外设的名称、基地址、中断有无以及优先级号码等相关硬件信息进行了定义。

其中nios2bsp是C/C++应用工程,nios2bsp_bsp是函数库

2.2 BSP Editor

在BSPEditor中可以对板级驱动层进行一些定制化的配置,比如代码裁剪、标准输入/输出外设和定时器外设的设置等。

在Project Explorer下工程名右键点击Nios Ⅱ->BSP Editor

在左侧一栏选中Common,然后在右侧勾选两个选项:

enable_reduced_device_drivers: BSP为处理器的外设提供了两个版本的驱动库:一种是执行速度快但代码量比较大的版本:另一种是封装小的版本。默认使用的是代码量大的版本,这里通过[enable reduced device drivers]选项来选择封装小的版本,从而减少代码量。

enalbe_small_c_library: 完整的ANSIC标准库通常不适用于嵌入式系统,BSP提供了一系列经过裁剪的ANSIC标准库,占用资源比较少,通过[enalbe small c lbrary]选项来选择精简的ANSIC标准库。

在左侧一栏选中Settings,将右侧两个选项(默认勾选) 取消勾选:

enable_c_plus_plus: 使用 C 语言来编写软件程序,因此不需要使能 C+。

enable clean exit: 当选中该选项时,系统库在主函数main()返回时会调用exit()。调用 exit0时,首先会清理I/O的缓冲区,然后再调用exit()。当不选中该选项时,系统库会只调用exit(),这样将会节省程序空间。对于嵌入式系统程序来说,一般都不会从 main()返回,所以可以不勾选该选项。

设置完成后先点击Generate然后再点击Exit

2.3 创建C代码文件

在Project Explorer下工程名右键点击New->Source File新建C代码源文件

 

 在Project Explorer下工程名右键Build Project (CTRL+B)进行软件工程编译

3.Nios Ⅱ实例

3.1 Hello NIOS Ⅱ

通过JTAG UART在Nios Console中每隔3s打印一串“Hello NIOS II”的字符串

#include "system.h"     //定义Qsys中各个外设的地址、中断优先级等基本硬件信息
#include <stdio.h>      //定义标准输入、输出函数
#include <unistd.h>     //包含了延时函数usleep()函数的生命

///
//功能:每隔3s通过JTAG UART打印一条字符串“Hello NIOS Ⅱ”
///

int main(void)
{
	while(1)
	{
		printf("Hello NIOS II!\n");
		usleep(3000000);
	}
	return 0;
}

printf对应的设备在BSP Editor中设定

下载验证

先把.sof文件下载到开发板中,下载完成后开发板上没有任何实验现象

再下载.elf 文件(注意一定要先下载 sof 文件,再下载 elf 文件),Nios Ⅱ SBT for Eclipse中工具栏Run->Run AS->Nios II Hardware,将编译生成可执行文件.elf下载到硬件系统中。 

如果在程序下载的过程中弹出了“Run Configurations”窗口,提示找不到与Nios II硬件系统的连接

那么在这个窗口中点击Target Connection标签,点击Refresh Connections按钮,软件使会自动识别开发板上的 Qsys 系统,并显示 Qsys 系统的相关信息,接着点击[Apply] [Run],软件会把.elf 文件下载至开发板中

 下载结束后,程序自动开始运行,在软件下方的“Nios II Console”中会打印“Hello,Nios Ⅱ!”信息

3.2 System ID与Timestamp

读取 System ID外设的两个寄存器值,一个是id 值,另一个是Testamp值

地址偏移寄存器名称读/写功能描述
0id基于Qsys系统定义的唯一的32位数值,该id值类似于校验和;不同组件、不同选项配置的Qsys系统产生不同的id值
1timestamp基于系统生成时间的唯一32位值,该值等效于从1970年1月1日以来所经过的总秒数
#include "alt_types.h"                      //对altera定义的数据类型进行宏定义声明,alt_u32表示32位的无符号整型
#include "system.h"
#include <stdio.h>  
#include "altera_avalon_sysid_qsys_regs.h"  //定义了System ID硬件寄存器访问的接口函数

///
//功能:读取System ID的ID值核timestamp值,通过JTAG UART打印
///

int main(void)
{
	//读取%sy_id值
	alt_u32 hardware_id = IORD_ALTERA_AVALON_SYSID_QSYS_ID(SYSID_BASE);                //读取定义的System ID外设的id值,SYSID_BASE是定义的System ID外设的基址
	//读取%sy_id的timestap值
	alt_u32 hardware_timestamp = IORD_ALTERA_AVALON_SYSID_QSYS_TIMESTAMP(SYSID_BASE);  //读取定义的System ID外设的Timestamp值
	
	printf("System ID is 0x%8x\n",hardware_id);
	printf("System timestamp is 0x%8x\n",hardware_timestamp);
	
	while(1);
	return 0;
}

3.3 蜂鸣器定时鸣叫

使用Timer定时器产生秒中断信号,驱动蜂鸣器发出响声

Timer 定时器组件内部有可编程的32位定时计数器,通过编程访问该组件的控制和状态寄存器实现定时中断功能。

Timer定时器外设寄存器定义

地址偏移寄存器名称

读/写

功能描述
0status读写

bit 15~2:保留

bit 1:运行指示位。当计数寄存器运行时,该位置高。

bit 0:定时结束指示位。当计数回零时,该位置高。一旦定时结束事件发生,该位置高,直到对该寄存器读写后该位清零

1control读写

bit 15~4:保留

bit 3:停止位。该位写1将停止当前定时计数功能。

bit 2:启动位。该位写1将启动定时计数功能。

bit 1:运行指示位。该位置1后,计数器清零后将继续计数,即执行连续计数;该位清0后,计数器清零后将停止计数,即只执行一次计数。

bit 0:中断表示位。该位提高后,一旦status寄存器的bit 0拉高,即产生IRQ中断。

2periodl读写定时计数周期值-1(高16位)
3periodh读写定时计数周期值-1(低16位)
4snapl读写当前计数值(高16位)
5snaph读写当前计数值(低16位)

#include "alt_types.h"                      
#include "altera_avalon_pio_regs.h"     //声明PIO外设函数,如IOWR_ALTERA_AVALON_PIO_DATA()函数
#include "altera_avalon_timer_regs.h"   //声明Timer定时器外设函数,如IOWR_ALTERA_AVALON_TIMER_STATUS()/CONTROL()
#include "sys/alt_irq.h"                //声明中断相关的函数,如all_irq_register
#include "system.h"

int flag,second;

///
//功能:Timer定时器初始化函数
///
void init_timer(void)
{
	//注册定时器中断函数
	//TIMER_IRQ是system.h中定义的Timer定时器组件的中断号,TIMER_BASE是Timer定时器组件的基址,handle_time_interrupts为中断函数
	alt_irq_register(TIMER_IRQ,TIMER_BASE,handle_time_interrupts);
	//对Timer定时器组件的control寄存器写数据7,即启动timer定时计数功能,持续循环计数产生IRQ中断中断
	IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_BASE,7);
	//清除标志位
	flag = 0;
	//初始化函数没有对periodl和periodh寄存器进行设置,使用默认的计数值,即在Qsys中定义的1s计数周期
}


///
//功能:秒定时中断处理函数
///
static void handle_time_interrupts(void)
{
	//函数写Timer定时器组件的status寄存器,即清TO标志
	IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_BASE,0); 
	flag = 1;
	second++;
}


///
//功能:秒定时中断处理函数
///
int main(void)
{
	IOWR_ALTERA_AVALON_PIO_DATA(PIO_BEEP_BASE,0);  //拨码开关OFF
	init_timer();                                  //Timer定时器初始化函数
	
	while(1)
	{
		if(flag)
		{
			flag = 0;
			//该函数对基址为PIO_BEEP_BASE的PIO外设写数据1/0
			if(second & 0x01) IOWR_ALTERA_AVALON_PIO_DATA(PIO_BEEP_BASE,1);  //拨码开关ON
			else IOWR_ALTERA_AVALON_PIO_DATA(PIO_BEEP_BASE,0);               //拨码开关OFF
		}
	}

	return 0;
}

3.4 拨码开关输入GIO控制

使用4个拨码开关产生中断,对不同拨码开关值进行判断,相应驱动蜂鸣器发出1~4此响声

PIO组件寄存器定义

地址偏移寄存器名称

读/写

功能描述
0data读写

作为输入PIO时,读控制获取当前输入PIO的电平值;

作为输出PIO时,写控制将数据输出到PIO上

1direction读写

每个PIO引脚单独的方向控制。电平0设置PIO为输入;电平1设置PIO为输出

2interruptmask读写每个PIO引脚对应的IRQ中断使能。电平1设置IRQ中断使能
3edgecapture读写每个PIO引脚的边沿变化状态捕获

#include "alt_types.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_irq.h"
#include "system.h"
#include <stdio.h>
#include <unistd.h>
#include <io.h>

/
//函数申明
void init_switch_pio(void);	//switch GIO初始化函数
void beep_didi(alt_u8 time);	//蜂鸣器发出“滴滴”响声函数

/
//宏定义

/
//变量申明
alt_u8 edge_capture_value;	//当前拨码开关值

/
//功  能:	拨码开关中断服务函数
/
static void handle_switch_interrupts(void)
{
    //捕获当前PIO值
    edge_capture_value = IORD_ALTERA_AVALON_PIO_DATA(PIO_SWITCH_BASE);
    //清除边沿中断标志位
    IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_SWITCH_BASE,0x00);
}

/
//功  能:	主函数,拨码开关从off到on拨动时,蜂鸣器发出几声清脆的“滴”响声
/
int main(void)
{

	IOWR_ALTERA_AVALON_PIO_DATA(PIO_BEEP_BASE,0);	//beep off
	init_switch_pio();	//switch GIO初始化函数
	
    while(1)
    {
    	if(~edge_capture_value & 0x01)	//蜂鸣器发出1声“滴”
        {
			beep_didi(1);
        }
    	else if(~edge_capture_value & 0x02)	//蜂鸣器发出2声“滴”
        {
			beep_didi(2);	
        }
    	else if(~edge_capture_value & 0x04)	//蜂鸣器发出3声“滴”
    	{
			beep_didi(3);
    	}
    	else if(~edge_capture_value & 0x08)	//蜂鸣器发出4声“滴”
    	{
			beep_didi(4);
    	}
    }
    return 0;
}

/
//功  能:	switch GIO初始化函数
/
void init_switch_pio(void)
{
    //初始化拨码开关状态值
    edge_capture_value = 0xff;
    //使能3个拨码开关中断
    IOWR_ALTERA_AVALON_PIO_IRQ_MASK(PIO_SWITCH_BASE, 0xff);
    //复位拨码开关边沿状态
    IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_SWITCH_BASE, 0x00);
    //拨码开关输入GIO中断复位申明
    alt_irq_register(PIO_SWITCH_IRQ,PIO_SWITCH_BASE,handle_switch_interrupts);
}

/
//功  能:	蜂鸣器发出“滴滴”响声函数
//参  数:	alt_u8 time 发出响声的次数
/
void beep_didi(alt_u8 time)
{
	alt_u8 i;
	for(i=0;i<time;i++)
	{
		IOWR_ALTERA_AVALON_PIO_DATA(PIO_BEEP_BASE,1);	//beep on
		usleep(20000);	//delay 100ms
		IOWR_ALTERA_AVALON_PIO_DATA(PIO_BEEP_BASE,0);	//beep off
		usleep(20000);	//delay 100ms	
	}
}

其他实例可参照参考书籍进行

4.FPGA器件的代码固化

4.1 嵌入式软件HEX文件生成

基于Nios Ⅱ处理器的FPGA器件代码固化和一般只有 FPGA 逻辑的代码固化不同

除了正常的FPGA逻辑部分代码需要固化外,还有Nios Ⅱ处理器的程序代码也需要固化。

使用FPGA片内存储器作为Nios Ⅱ处理器的代码存储器,在生成逻辑代码部分的烧录文件时,将 Nios Ⅱ处理器的代码集成在一起,就可以使用一个烧录文件完成 FPGA 器件的固化

打开工程的BSP Editor页面,选择Setting->Advanced->hal->linker,勾选allow_code_at_reset选项,然后重新编译C/C++软件工程文件和函数库文件

设置该选项的目的是在确保FPGA使用了片内存储器作Nios Ⅱ处器代码存储器时,在FPGA逻辑运行起来以后,Nios Ⅱ处理器复位后直接可以从片内存储器开始运行代码

 然后右键软件工程文件->Make Targets->Build,选择men_init-generate,点击Build

然后就可以在软件工程文件夹下发现.hex文件,为软件工程代码对应的十六进制HEX文件,即Nios Ⅱ处理器的软件代码

4.2 程序存储器初始化文件加载

进入Qsys界面,双击onchip_men组件进入配置界面的Memery initialization

勾选Initialize memory content和Enable non-default initialization file,并在User created initialization file中添加刚才生成的.hex文件

重新生成Qsys工程并且重新编译整个Quartus工程并产生新的.sof 文件

此时.sof 文件通过JTAG在线烧录到FPGA器件中则会直接运行软件程序

但.sof 文件只能在线烧录,因此需要将.sof文件转换为jic文件,实现SPI Flash的固化

4.3 JIC文件生成和烧录配置

在Quartus中选择File->Convert Programming Files

在Programming file type中选择JTAG Indirect Configuration File(.jic)

Configuration device选择配置设备,File name输入转换后的文件名(output_files 文件夹下)

在Input files to convert中

单击Flash Loader所在的行,然后单击右侧Add Device按钮在Select Devices 窗口中选择设备

单击SOF Data所在行,然后单击右侧的Add File按钮,在弹出的窗口中选择output files文件夹下的 .sof文件

完成设置后,单击 Generate 生成 *.jic,弹出如图所示的提示信息,表示成功生成jic文件

打开 Quartus的 Programmer 页面,单击Add File按钮加载的jic 文件(File下若有其他文件,请删除),并且确保勾选 Program/Configure 所在列

单击 Start 按钮执行下载操作,完成下载后,开发板默认处于不工作状态,需要重启开发板,重启后就能看到最新下载的代码已经固化到 SPI Flash 中并且掉电后重启仍然可以运行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/767310.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RocketMQ环境搭建

环境搭建 环境准备 下载地址: https://downloads.apache.org/rocketmq/4.9.5/安装 上传至服务器 mkdir /usr/soft #上传至此目录/usr/softmkdir /usr/soft 解压 cd /usr/soft unzip rocketmq-all-4.9.5-bin-release.zip移动 mkdir /usr/local/rocketmq cd /usr/soft mv r…

Mysql 修改group_concat_max_len的默认值

1.前言 最近在进行递归查询组织及其下属组织时&#xff0c;发现数据查询不全&#xff0c;子组织数据查询不出来的问题。经排查发现是group_concat_max_len的长度不足引起的&#xff0c;默认情况下group_concat_max_len1024&#xff0c;所以我们需要修改这个默认参数。 2.SQL语…

.net core控制台应用程序在linux运行

1&#xff09;创建.net 6.0控制台应用程序 2&#xff09;在应用根目录执行cmd命令发布应用&#xff1a;dotnet publish -o .\deploy 3&#xff09;将发布文件上传到服务器 4&#xff09;运行控制台应用程序&#xff08;dotnet /home/app/ConsoleApp/ConsoleApp5.dll&#xff09…

卡尔曼与扩展卡尔曼的区别与推导

1.卡尔曼的推导&#xff1a; 1&#xff09;先看系统随机系统状态空间模型&#xff1a;&#xff08;线性&#xff09; 所谓线性是指递推或者状态转移方程是线性的 至于参数解释自己去看书&#xff0c;本文旨在捋顺推导思路。 2&#xff09;k-1时刻值减去k-1的状态最优估计k-1时…

Vscode设置忽略文件,忽略node-modules、dist

####看图 files.exclude 设置排除和显示的文件夹 search.exclude 设置搜索时忽略的文件夹

WEB:Cat

背景知识 命令执行漏洞 Django框架 题目 先ping一下&#xff0c;输入127.0.0.1 这个输入可能存在命令执行的操作&#xff0c;但是经过尝试之后并不能正常执行 127.0.0.1&&dir、127.0.0.1&&ls、127.0.0.1|ls均被屏蔽&#xff0c;但经过尝试可知&#xff0c;网…

matplotlib笔记:qbstyle设置matplotlib 主题

0 原始matplotlib import numpy as np import matplotlib.pyplot as pltxnp.linspace(0,100) ynp.sin(100*x)plt.plot(x,y); 1 light from qbstyles import mpl_style mpl_style(darkFalse) #开启light主题 plt.plot(x,y); 2 dark from qbstyles import mpl_style mpl_styl…

实现大文件传输的几种方法,并实现不同电脑间大文件传输

随着网络技术的快速发展&#xff0c;大文件的传输需求越来越多&#xff0c;如何在不同的电脑之间实现大文件的快速传输&#xff0c;是一个挑战&#xff0c;下面介绍几种常用的方法可以解决这个问题。 1、利用局域网传输&#xff1a;把两台电脑接入同一个网络环境&#xff0c;通…

关于硬件加速器FPGA的异构加速流程龙蜥CI框架及实践介绍 | 第 87-88 期

本周「龙蜥大讲堂」预告来啦&#xff01;我们邀请了浪潮信息异构加速软件工程师刘科分享《基于 FPGA 的数据库硬件加速研究》、 CICD SIG Maintainer 李晔做《龙蜥社区 CI 框架及实践》主题演讲&#xff0c;精彩多多&#xff0c;快入群&#xff0c;预定前排小板凳观看直播&…

项目名称:无源在线词典项目

一&#xff0c;概述 基于C语言的网络电子词典项目&#xff0c;使用到了tcp协议的并发服务器设计、网络编程、文件I/O、数据库等多方面的知识。可以满足多用户同时登陆&#xff0c;用户登陆后可以查询单词及历史记录&#xff0c;具有查找快速&#xff0c;保密性好等优点。 开…

19.删除链表的倒数第N个节点

19.删除链表的倒数第N个节点 这道题是链表问题中双指针的一个经典应用 如果要删除倒数第n个节点&#xff0c;那么我们让fast快指针移动n步&#xff0c;然后让fast和慢指针slow同时开始移动&#xff0c;当fast指针指向链表末尾的时候&#xff0c;删掉slow指针指向的节点即可。 …

ai绘画工具哪个好用?这几款好用的ai绘画生成器安利给你

嘿&#xff0c;小伙伴们&#xff01;你是否曾经想过创作一幅酷炫的人物插画&#xff0c;但由于缺乏绘画技巧而放弃这个想法&#xff1f;别担心&#xff0c;现在有了ai绘画工具&#xff0c;让你轻松成为艺术家的潜力无限&#xff01;今天我就来给大家介绍几个用ai绘画工具生成好…

【iOS】ARC实现

ARC由以下工具来实现&#xff1a; clang&#xff08;LLVM编译器&#xff09;3.0以上objc4 Objective-C运行时库493.9以上 下面我们&#xff0c;我们将围绕clang汇编输出和objc4库的源代码探究ARC实现 1. __strong修饰符 1.1 赋值给附有__strong修饰符的变量 看下面代码 {…

Android TextView 在最后一行末尾加图标

当前有个需求.显示一段文本&#xff0c;文本最多显示两行&#xff0c;点击展开后才显示完全。当没有显示完全的时候&#xff0c;需要在文本的第二行末尾显示图标&#xff0c;点击图标和文本&#xff0c;文本展开。难点在于图标需要和第二行文本显示在同一行&#xff0c;高度和文…

JavaScript的WebAPI

这里写目录标题 DOM 基本概念获取元素事件概念事件的三要素操作元素获取/修改表单元素属性行内样式操作类名样式操作操作节点 DOM 基本概念 DOM 全称为 Document Object Model. W3C 标准给我们提供了一系列的函数, 让我们可以操作: 网页内容 ,网页结构, 网页样式 DOM数的结构如…

【PDFBox】PDFBox操作PDF文档之读取指定页面文本内容、读取所有页面文本内容、根据模板文件生成PDF文档

这篇文章&#xff0c;主要介绍PDFBox操作PDF文档之读取指定页面文本内容、读取所有页面文本内容、根据模板文件生成PDF文档。 目录 一、PDFBox操作文本 1.1、读取所有页面文本内容 1.2、读取指定页面文本内容 1.3、写入文本内容 1.4、替换文本内容 &#xff08;1&#xf…

【C++】STL之list容器的模拟实现

个人主页&#xff1a;&#x1f35d;在肯德基吃麻辣烫 分享一句喜欢的话&#xff1a;热烈的火焰&#xff0c;冰封在最沉默的火山深处。 文章目录 前言一、list的三个类的关系分析图vector和list的区别1.节点的成员变量以及构造函数2.list的迭代器 二、list的增删查改工作2.1inse…

【数据结构】24王道考研笔记——图

六、图 目录 六、图定义及基本术语图的定义有向图以及无向图简单图以及多重图度顶点-顶点间关系连通图、强连通图子图连通分量强连通分量生成树生成森林边的权、带权网/图特殊形态的图 图的存储及基本操作邻接矩阵邻接表法十字链表邻接多重表分析对比图的基本操作 图的遍历广度…

# Linux下替换文件中的颜色等控制字符的方法

Linux下替换文件中的颜色等控制字符的方法 文章目录 Linux下替换文件中的颜色等控制字符的方法1 Linux下的控制字符&#xff08;显示的文字并不是他本身&#xff09;&#xff1a;2 颜色字符范例&#xff1a;3 替换4 最后 我们在shell编程显示输出时&#xff0c;会定义文字颜色&…

ESD放电模式以及电源箝位 (power clamp )电路

目录 1.ESD的基本概念 2.ESD放电模式与泄放路径 2.1 I/O端与 Vcc或者 I/O端与 Vss 2.2 I/O端与 I/O端 2.3 Vcc&#xff08;电源端&#xff09;与Vss&#xff08;地端&#xff09; 2.4不同类型电压源 3. 电源箝位 (power clamp )电路 4.全芯片ESD保护电路系统框图 参考…