SOPC之NiosⅡ系统(四)

news2024/11/28 14:39:54

NIOS Ⅱ系统实例,参考自特权同学《勇敢的芯-伴你玩转NIOS Ⅱ》

一些基础操作就不再赘述

目录

1.创建Quartus项目

1.2 进入Platform Designer添加组件并设置

1.2.1 设置时钟频率50MHz;

1.2.2 添加Nios Ⅱ组件

1.2.3 添加RAM组件

1.2.4 设置Nios Ⅱ复位向量与异常向量地址,使其指向RAM

1.2.5 添加System ID组件

1.2.6 添加JTAG UART组件

1.2.7 添加Timer组件

1.2.8 添加UART组件

1.2.9 添加蜂鸣器PIO组件

1.2.10 添加拨码开关PIO组件

1.2.11 数码管组件

1.2.12 ADC组件

1.2.13 DAC组件

1.2.14 超声波测距组件

1.215 RTC组件

1.2.16 矩阵按键组件

1.3 信号连接

​1.4 中断连接

​1.5 地址分配

1.6 系统生成并例化模板

1.7 完成Quartus工程

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文件生成和烧录配置


1.创建Quartus项目

1.2 进入Platform Designer添加组件并设置

1.2.1 设置时钟频率50MHz;

1.2.2 添加Nios Ⅱ组件

选择Nios II/f模式;

1.2.3 添加RAM组件

设置Data width为32,Total memory size为22528,其他设置为默认

1.2.4 设置Nios Ⅱ复位向量与异常向量地址,使其指向RAM

1.2.5 添加System ID组件

设置32 bit System ID为0x01223344 

1.2.6 添加JTAG UART组件

设置Write FIFO和Read FIFO得存储量为16,勾选Construct using registers instead of memory blocks,其他为默认

1.2.7 添加Timer组件

设置模式为Full-featured,周期Period为1,单位为s,其他默认

1.2.8 添加UART组件

设置校验位(Parity)为NONE、8个数据位(Data bits)、1个停止位(Stop bits)、同步周期(Synchronizer stages)为 2、波特率(Baud rate)为9600、不勾选Fixed baud rate(即波特率为Nios Ⅱ处理器软件可更改)

 

1.2.9 添加蜂鸣器PIO组件

设置位宽(Width)为1、方向(Direction)Output、默认值(Output Port Reset Value)为0x0,其他默认。

1.2.10 添加拨码开关PIO组件

设置位宽(Width)为4、方向(Direction)为Input、勾选Edge capture register-Synchronously capture选项,同时选中边沿类型(Edge Type)为 ANY、勾选InterruptGenerate IRQ选项,中断类型(IRQ Type)为 EDGE

 

1.2.11 数码管组件

数码管组件通过Avalon-MM总线从机接口实现 Nios Ⅱ处理器将4位数字显示到数码管上。该组件定时进行数码管显示驱动刷新,将 Nios Ⅱ处理器发送到数据寄存器的32位数据显示到数码管上。

将source_code/digital_tube_controller下三个.v文件添加自定义数码管组件并设置信号相应参数,然后添加数码管组件

Parameters中可以设置组件源码中定义的参数是否在用户加载组件时可配置

这里ADDR_SIZE为固定值,因此不勾选

 

注意dtube_cs_n和dtube_data的export名字不能相同 

1.2.12 ADC组件

ADC组件通过Avalon-MM总线机接口实现Nios Ⅱ处理器与ADC芯片TLC549之间的数据传输。该组件产生TLC549芯片数据读取所需的接口时序,定时读取ADC芯片的采样数据存储到Avalon-MM 总线可访问的数据寄存器中,供Nios Ⅱ处理器读取。

将source_code/adc_controller下三个.v文件添加自定义ADC组件并设置信号相应参数,然后添加ADC组件

1.2.13 DAC组件

DAC组件通过Avalon-MM总线从机接口实现 Nios Ⅱ处理器与DAC芯片DAC5571之间的数据传输。该组件产生DAC5571芯片读写访问的IIC总线接口所需的时序,在Avalon-MM总线可访问的数据寄存器值发生变化时,执行DAC5571芯片DAC转换数据的写入。

将source_code/dac_controller下三个.v文件添加自定义DAC组件并设置信号相应参数,然后添加DAC组件

 

1.2.14 超声波测距组件

ultrasound_controller组件通过Avalon-MM总线从机接口实现 Nios Ⅱ处理器对超声波模块获取的最新距离数据信息的采集。该组件定时产生超声波测距模块所需的触发脉冲信号,回采反馈脉冲,并且对反馈脉冲进行中值滤波和距离值换算,最终获得以毫米为单位的距离信息。该距离信息存储到 Avalon-MM总线可访问的数据寄存器中,供 Nios Ⅱ处理器读取。

将source_code/ultrasound_controller下六个.v文件以及mult文件夹(乘法器IP核)下mul.qip文件添加自定义超声波测距组件并设置信号相应参数,然后添加超声波测距组件

 

1.215 RTC组件

RTC组件通过Avalon-MM总线从机接口实现Nios Ⅱ处理器对RTC芯片PCF8563T的时间和日期数据进行读写操作。该组件定时读取最新的RTC数据,存储到Avalon-MM总线可访问的数据寄存器中,Nios Ⅱ处理器随时可以读取最新的RTC数据也可以写人修改的数据更新到RTC芯片中。

将source_code/rtc_controller下五个.v文件添加自定义RTC组件并设置信号相应参数,然后添加RTC组件

1.2.16 矩阵按键组件

矩阵按键组件通过Avalon-MM总线从机接口实现 Nios Ⅱ处理器对4X4矩阵按键值的采集。该组件定时产生矩阵按键扫描所需的各种电平变换,采集到按键扫描值存储到Avalon-MM总线可访问的数据寄存器中并且产生可配置开关状态的中断信号给Nios Ⅱ处理器,Nios Ⅱ处理器可通过中断状态实时读取按键值。

将source_code/Button_controller下四个.v文件添加自定义RTC组件并设置信号相应参数,然后添加矩阵按键组件

1.3 信号连接

将各个组件的时钟、复位信号连接到Clock组件的相应信号上

为了Nios Ⅱ处理器能够访问到各个组件,实现对组件数据的读取、传输等功能,则需要将Nios Ⅱ处理器的数据总线(data_master)连接到各个组件(s1、control_slave、avalon_jtag_slave)上

此外UART外设接口(RX和TX信号)需要引出到QSYS系统外部连接到FPGA的引脚上,因此需要双击UART外设external_connection一行的Double-click to,当出现接口符号,说明该接口已引出

PIO和自定义组件同理

1.4 中断连接

在IRQ一列中与Nios Ⅱ处理器相连接中断信号有timer、pio_switch、jtag_uart、uart 和 ButtonController组件。

点击这些IRQ和 NiosⅡ处理器的空心圆连接点进行连接,连接后出现的数字表示中断号,数字越低优先级越高

 

1.5 地址分配

在Address Map窗口列出了所有外设的地址范围。目前地址还未分配,默认都是从0x0000开始作为基地址,所以各个外设间出现了地址冲突


在菜单栏中选择System一Assign Base Address让工具自动进行地址分配,以8bit为单位进行寻址

这这里应该所有报错都解决了

1.6 系统生成并例化模板

菜单栏Generate->Genarate HDL...

 

 在Quartus的工具栏Assignments->Settings->Files->File name中找到生成的.qip文件并添加

添加成功后会在Project Navigator窗口中看到添加的qip文件

1.7 完成Quartus工程

最后建立工程的顶层模块,在Platform Designer中点击Generate->Show Instantiation Template生成例化代码

将例化代码复制到顶层文件cy4.v中并连接好端口

//Qsys系统
module cy4(
			input ext_clk_25m,	            //外部输入25MHz时钟信号
			input ext_rst_n,	               //外部输入复位信号,低电平有效
			input uart_rx,		               //UART接收数据信号
			output uart_tx,		            //UART发送数据信号
			input[3:0] switch,	            //拨码开关SW3输入,ON-低电平、OFF-高电平
			output beep,	                  //蜂鸣器控制信号,1-响、0-不响
			output[3:0] dtube_cs_n,	         //7段数码管位选信号
			output[7:0] dtube_data,	         //7段数码管段选信号(包括小数点为8段)
			input adc_data,						//ADC芯片TLC549的SPI数据信号										
			output adc_cs_n,						//ADC芯片TLC549的SPI片选信号,低电平有效										
			output adc_clk,		            //ADC芯片TLC549的SPI时钟信号
			output dac_iic_sck,		         //DAC5571的IIC接口SCL
			inout dac_iic_sda,		         //DAC5571的IIC接口SDA
			output ultrasound_trig,	         //超声波测距模块脉冲激励信号,10us的高脉冲
			input ultrasound_echo,	         //超声波测距模块回响信号
			output rtc_iic_sck,	            //RTC芯片的IIC时钟信号
			inout rtc_iic_sda,               //RTC芯片的IIC数据信号
			input[3:0] key_v,	               //4个列按键输入,未按下为高电平,按下后为低电平
			output[3:0] key_h				      //4个行按键输入
		);												

wire clk_12m5;                            //PLL输出12.5MHz时钟
wire clk_25m;	                           //PLL输出 25 MHz时钟
wire clk_50m;	                           //PLL输出 50 MHz时钟
wire clk_100m;	                           //PLL输出100 MHz时钟
wire sys_rst_n;	                        //PLL输出的locked信号作为FPGA内部的复位信号,低电平复位,高电平正常工作
		
//-------------------------------------
//PLL例化	
		
pll_controller	pll_controller_inst (
	.rst ( !ext_rst_n ),
	.refclk ( ext_clk_25m ),
	.outclk_0 ( clk_12m5 ),
	.outclk_1 ( clk_25m ),
	.outclk_2 ( clk_50m ),
	.outclk_3 ( clk_100m ),
	.locked ( sys_rst_n )
	);
	
//-------------------------------------
//Qsys系统例化

cy4_qsys  uun_cy4_qsys (
        .adc_controller_1_conduit_end_export_clk          (adc_clk),           //adc_controller_1_conduit_end.export_clk
        .adc_controller_1_conduit_end_export_cs_n         (adc_cs_n),          //.export_cs_n
        .adc_controller_1_conduit_end_export_data         (adc_data),          //.export_data
        .buttoncontroller_0_conduit_end_1_export_v        (key_v),             //buttoncontroller_0_conduit_end_1.export_v
        .buttoncontroller_0_conduit_end_1_export_h        (key_h),             //.export_h
        .clk_clk                                          (clk_50m),           //clk.clk
        .dac_controller_0_conduit_end_export_scl          (dac_iic_sck),       //dac_controller_0_conduit_end.export_scl
        .dac_controller_0_conduit_end_export_sda          (dac_iic_sda),       //.export_sda
        .digital_tube_controller_conduit_end_export_cs_n  (dtube_cs_n),        //digital_tube_controller_conduit_end.export_cs_n
        .digital_tube_controller_conduit_end_export_data  (dtube_data),        //.export_data
        .pio_beep_external_connection_export              (beep),              //pio_beep_external_connection.export
        .pio_switch_external_connection_export            (switch),            //pio_switch_external_connection.export
        .reset_reset_n                                    (sys_rst_n),         //reset.reset_n
		  .rtc_controller_0_conduit_end_export_rtcsda       (rtc_iic_sda),       //rtc_controller_0_conduit_end.export_rtcsda
        .rtc_controller_0_conduit_end_export_rtcsck       (rtc_iic_sck),       //.export_rtcsck
        .uart_external_connection_rxd                     (uart_rx),           //uart_external_connection.rxd
        .uart_external_connection_txd                     (uart_tx),           //.txd
        .ultrasound_controller_0_conduit_end_export_trig  (ultrasound_trig),   //ultrasound_controller_0_conduit_end.export_trig
        .ultrasound_controller_0_conduit_end_export_echo  (ultrasound_echo)    //.export_echo
    );

endmodule

添加一个PLL IP核

进行语法分析,引脚分配,系统编译,完成Quartus Ⅱ工程

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/763818.html

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

相关文章

【每日随笔】摩托车安全驾驶 ① ( 摩托车骑行准备 | 买好保险 | 摩托车必要改装 - 护杠 + 行车记录仪 | 骑行护具 )

文章目录 一、摩托车骑行准备1、买好保险2、摩托车必要改装 - 护杠 行车记录仪3、骑行护具 德州考驾照归来 , 提了一辆 铃木 UY125 , 注意安全驾驶 , 以后上班就骑摩托车了 ; 由于居住证上的地址是海淀区 , 目前住在学院路 , 导致无法把车落户到自己名下 , 只能上公户了 ; 车…

G1垃圾收集器-JVM(十三)

上篇文章说了CMS垃圾收集器使用以及三色标记如何解决cms的一些问题。分别有初始标记&#xff0c;并发标记&#xff0c;重新标记&#xff0c;并发清理&#xff0c;并发重置。 CMS垃圾收集器&三色标记-JVM&#xff08;十二&#xff09; G1收集器&#xff08;Garbage-First&a…

浅析缓存一致性的解析方案

各位同学们平时开发的时候除了使用到数据库&#xff08;这里以mysql为例&#xff09;还会用到相关的缓存&#xff08;这里以redis为例&#xff09;操作。 举一个常用的场景当我们写的接口性能相对比较慢的时候&#xff08;高并发场景需要响应速度很快&#xff09;为了保证性能的…

LeetCode144. 二叉树的前序遍历

144. 二叉树的前序遍历 文章目录 [144. 二叉树的前序遍历](https://leetcode.cn/problems/binary-tree-preorder-traversal/)一、题目二、思路及代码&#xff08;1&#xff09;递归&#xff08;2&#xff09;迭代&#xff08;两种方法&#xff09; 一、题目 给你二叉树的根节点…

AlienSwap 首期 Launchpad — 偶像女团 NFT+RWA 的创新探索

NFT 是整个加密市场一致看好&#xff0c;并认为会继续爆发的领域。随着更多的 NFT 平台和 NFT 项目的推出&#xff0c;NFT 市场的格局也在不断变化。从开始的 OpenSea 占据绝对领先地位&#xff0c;到 Blur 的横空出世风头无两&#xff0c;在加密领域&#xff0c;局势更迭总是在…

【Java面试丨并发编程】线程中并发安全

一、Synchronized关键字的底层原理 1. Synchronized的作用 Synchronized【对象锁】采用互斥的方式让同一时刻至多只有一个线程能持有【对象锁】&#xff0c;其他线程再想获取这个【对象锁】时就会阻塞住 2. Monitor Synchronized【对象锁】底层是由Monitor实现&#xff0c;…

泰裤辣!这是什么操作,自动埋点,还能传参?

目录 前言 参数放在注释中 准备入口文件 编写插件 运行代码 完整代码 参数放在局部作用域中 准备源代码 编写插件 运行代码 完整代码 总结 前言 在上篇文章讲了如何通过手写babel插件自动给函数埋点之后&#xff0c;就有同学问我&#xff0c;自动插入埋点的函数怎么…

基于IMX6ULL的AP3216C的QT动态数据曲线图显示

前言&#xff1a;本文为手把手教学 LinuxQT 的典型基础项目 AP3216C 的数据折线图显示&#xff0c;项目使用正点原子的 IMX6ULL 阿尔法( Cortex-A7 系列)开发板。项目需要实现 AP3216C 在 Linux 系统下的驱动&#xff0c;使用 QT 设计 AP3216C 的数据显示页面作为项目的应用层。…

消息中间件RabbitMQ简介

1.1消息队列中间件简介 消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用耦合&#xff0c;异步消息&#xff0c;流量削锋等问题实现高性能&#xff0c;高可用&#xff0c;可伸缩和最终一致性[架构] 使用较多的消息队列有ActiveMQ&#xff0c;RabbitMQ&#xff…

人工智能安全风险:零信任的作用

人工智能&#xff08;AI&#xff09;和机器学习技术飞速发展&#xff0c;我们所处的时代正在经历前所未有的创新。但是&#xff0c;技术飞速发展的同时也带来了各种挑战。人工智能技术越来越复杂&#xff0c;与之相关的网络安全风险也越来越棘手&#xff0c;随之产生了一个新的…

TortoiseGit 入门指南10:贮藏

有时&#xff0c;当你在项目的一部分上已经工作一段时间后&#xff0c;所有东西都进入了混乱的状态&#xff0c; 而这时你想要切换到另一个分支做一点别的事情。 问题是&#xff0c;你不想仅仅因为过会儿回到这一点而为做了一半的工作创建一次提交。 针对这个问题的答案是贮藏 …

【Linux指令集】---unzip指令(超详细)

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【Linux专栏】&#x1f388; 本专栏旨在分享学习Linux的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 演示环境&#xff1…

JVM系统优化实践(19):GC生产环境案例(二)

您好&#xff0c;这里是「码农镖局」CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 接昨天的问题继续来说&#xff0c;在高并发场景中&#xff0c;对象过多容易导致OOM。由于高并发导致Young GC存活对象过多&#xff0c;因此会有太多对象进入老年代&#xf…

关于unity Content Size Fitter 套 Content Size Fitter

首先&#xff1a;最好不要unity Content Size Fitter 套 Content Size Fitter 这样最后得到的变化可能会错误 unity也提示了&#xff0c;父物体如果有了&#xff0c;那么子物体就不要再加了。 但是你们要的需求&#xff1a; 一级父物体 ➡自适应大小➡二级父物体&#xff08…

经典目标检测R-CNN系列(2)Fast R-CNN

经典目标检测R-CNN系列(2)Fast R-CNN Fast R-CNN是作者Ross Girshick继R-CNN后的又一力作。 同样使用VGG16作为网络的backbone&#xff0c;与R-CNN相比训练时间快9倍&#xff0c;测试推理时间快213倍&#xff0c;准确率从62%提升至66%(Pascal VOC数据集上)。 1 Fast R-CNN的…

Java List 与数组互转

前言 略 数组转 List 方法1 Employee[] array new Employee[]{emp1, emp2, emp3}; List<Employee> list Arrays.asList(array);Arrays.asList 返回的是固定长度的数组&#xff0c;扩大或缩小列表的操作将返回UnsupportedOperationException。 数组转 List 方法2 E…

【C++STL】“vector“容器的模拟实现

vector的模拟实现 模拟实现成员变量构造函数无参构造函数初始化n个val的构造函数迭代器区间构造函数 拷贝构造析构函数begin&#xff08;&#xff09;end&#xff08;&#xff09;swap&#xff08;&#xff09;reserve()resize()capacity()size()重载[]运算符重载赋值运算符ins…

自学网络安全(黑客)为什么火了?

网安专业从始至终都是需要学习的&#xff0c;大学是无法培养出合格的网安人才的。这就是为啥每年网安专业毕业生并不少&#xff0c;而真正从事网安岗位的人&#xff0c;寥寥无几的根本原因。 如果将来打算从事网安岗位&#xff0c;那么不断学习是你唯一的途径。 网络安全为什…

应对 618、双十一等大促期间的高负载,API 性能测试应该怎么做?负载测试、基线测试、冒烟测试、浸泡测试、峰值测试和尖峰测试详解

随着应用程序和服务交付速度的不断提高&#xff0c;在按时交付应用程序的竞赛中&#xff0c;性能测试往往会退居其次。但是&#xff0c;在节假日期间&#xff0c;购物额都会大幅增长。在这种一年中的成败时刻&#xff0c;公司是无法接受他们的应用程序在高负载下变得不可靠的。…

第四章 云原生架构之Kubernetes基础知识

1、K8S整体架构 1.1、概述 ​ Kubernetes是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化的工作负载和服务&#xff0c;简称 K8S。K8S的本质是一组服务器集群&#xff0c;可以在对应服务器集群的每个节点上运行程序&#xff0c;来对节点中的容器进行管理。类似Mas…