本篇首先简单介绍NiosIIIDE开发环境的使用;然后重点介绍了硬件抽象层(HAL)系统库,包括HAL下的基本应用程序开发和实操训练,包括了字符型外设的应用和中断机制的实现。
以下为本篇的目录简介:
5.1NiosIIIDE简介
5.2设置工程系统库属性和编译选项
5.3调试/运行程序
5.4下载程序到Flash
5.5使用HAL开发应用程序
5.6UART-JTAG开发和实验
5.7LCD开发和实验
5.8SYSTEMID实验
5.9中断机制和软件调试
+
NiosIIIDE为软件开发提供4个主要功能:
一、工程管理
二、编辑器和编译器
三、调试器
四、闪存编程器
统一开发平台,用于所有NiosII处理器系统。
一、工程管理器
1、新工程向导
[File]→[New]→[C/C++Application]
PIO内核结构框图
2、软件工程模板
3、软件组件
1、文本编辑器
成熟的全功能源文件编辑器,包括:语法高亮显示C/C++程序代码、全面的搜索工具、文件管理、在线帮助和教程、快速定位及自动纠错、内置调试等功能。
2、C/C++编译器
NiosIIIDE使用GCC编译器,并为其提供了一个图形化用户界面。图形化用户界面为GCC编译器提供了一个易用的按钮式流程,同时允许开发人员手工设置高级编译选项,使得操作更简单方便。
软件调试器(GDB):是强大的、在GNU调试器基础之上的软件调试器。该调试器提供许多基本调试功能以及一些在低成本处理器开发套件中不会经常用到的高级调试功能。
基本调试功能包括:运行控制、调用堆栈查看、软件断点、反汇编代码查看、调试信息查看、指令集仿真器。
高级调试功能包括:硬件断点调试ROM或闪存中的代码、数据触发、指令跟踪。
多数使用NiosII处理器的设计都需要采用闪存(Flash)来存储FPGA配置数据和/或应用程序。NiosIIIDE提供了一个方便的闪存编程方法。任何连接到FPGA的兼容通用闪存接口(CFI)的闪存器件以及主动串行配置器件EPCS都可以通过NiosIIIDE闪存编程器来烧写。
C/C++Build设置:
右击C/C++工程文件夹→[SystemLibraryProperties]
C/C++Indexer设置:
SystemLibrary设置:
选择Debug的目标器件:
对话框操作:[RUN]→[Debug]/[DebugAs]
调试器目标连接设置--(TargetConnection):
对话框操作:[RUN]→[Debug]→[NiosIIHardware]→TargetConnection
JTAGcable:进行JTAG下载电缆的选择。
JTAGdevice:进行连接在JTAG下载电缆上带JTAG接口器件的选择。
NiosIITerminal…:进行NiosII系统中断通信工具选择。
调试器设置--(Debugger):
对话框操作:[RUN]→[Debug]→[NiosIIHardware]→Debugger
调试器设置--(Debugger视窗模式):
对话框操作:NiosIIIDE切换到Debug视窗模式
运行程序--(Debugger视窗模式)
对话框操作:[RUN]→[RUN]/[RUNAs]
当调试工作完成并确保程序无错后,就可以把程序下载到Flash中了。
NiosIIIDE工程结构:
NiosIIIDE工程结构
一个NiosIIIDE工程
System.h文件构成过程
程序清单5.1system.h描述的UART设备:
数据宽度及HAL类型定义:
表5.1HAL数据类型定义
表5.2Altera提供的GNU编译器下的ANSIC数据类型宽度
实验目的:
使用UART-JTAG可以方便的通过下载线建立主机与SOPC的联系,这种串口方式把复杂的硬件驱动隐藏,从代码的角度来看我们可以很方便操作。
在ANSIC库的支持下,用户既可以把JTAGUART设备当作标准I/O设备使用,也可以将其当作文件操作。其实质是通过ANSIC库函数调用JTAGUART设备驱动函数访问硬件设备。
通过上面的设置,将器件JTAG_UART的输入输出映射到STDOUT\STDERR\STDIN等,那么我们就可以利用下面这些函数,操作JTAG_UART。
在上面红色部分设置好后,在CONSOLE窗口可以显示PC方的内容。
例程一:
#include
完成一个识别键盘字符V和T的程序,要求识别到T后,利用fwrite打印出关于识别T的信息,识别到V后关闭JTAG,打印出V的信息,程序停止。
TheLCDcontrollercoreconsistsoftwouser-visiblecomponents:
aredefinedintheOptrex16207datasheet.
同样的LCD显示也是用写文件的方式(LCD只有输出)。如下例子:
通过实验了解SYSTEMID的意义和作用。
实验说明:
SOPCBUILDER生成该系统的时候,将为每一个NIOS系统生成一个标志符。该标志符会被填入SYSTEMID寄存器中,供编译器和用户辨别所运行的程序是否与目标系统匹配。当程序运行在与之不匹配的系统上会出现错误。
使用系统ID有两种基本方法:
实现方法:
访问SYSTEMID的HAL函数为ALT_AVALON_SYSID_TEST(),该函数返回一个值来指示软件期望的系统ID是否匹配。使用头文件是
利用JTAG-UART功能将SYSTEMID功能加入实验中,要求程序运行首先检查ID,根据不同情况打印不同信息。
中断定义:
在特定的事件(中断源,也称中断请求信号)触发下引起CPU暂停正在运行的程序(主程序),转而先去处理一段为特定事件而编写的处理程序(中断处理程序),等中断处理程序处理完成后,再回到主程序被打断的地方继续运行。
NIOSⅡ中断类型:
(1)status寄存器(ctl0)的PIE位为l;
(2)有一个中断请求输入irq产生;
(3)ienable寄存器(ctl3)的响应位n为l。
中断控制机制:
NiosII的中断处理方式带有典型的RISC处理器的特征,所有的中断处理都从同一入口进入,然后由软件加以分配。负责分配工作的软件叫系统ISR,它是由开发系统提供的,自动的连接到可执行程序上。系统ISR维护着一个中断向量表,表中的每一项代表着一个专项处理程序的入口。所有的专项处理程序都是由用户定义然后注册到中断向量表中的,叫做用户ISR。系统ISR的入口地址是在SOPC_Builder中定义的,叫ExceptionAddress。和中断有关的CPU寄存器有:ctl0、ctl1、ctl3、ctl4。Ctl0是程序状态字,它的bit0位是全局中断允许位,1代表允许,0代表禁止。Ctl1是程序状字的堆栈,当发生中断时,由它保留一个程序状态字的备份。Ctl3是中断允许寄存器,其中每一位控制着一个中断源,1代表允许,0代表禁止,共计32位。Ctl4是中断申请寄存器,每一位对应着一个中断源的中断请求,1代表有中断,0代表没有……计32位。
NiosII的中断处理过程:
软中断处理程序是用来处理由软件发起的中断事件的,包括调试指令引起的中断及未定义指令引起的中断。目前未定义指令的处理主要为乘、除法运算指令的处理,不支持用自定义的操作码,除用户自己修改系统程序。如果软中断处理程序遇到了一个不识别的操作码,将返回一个不确定的结果。
完成中断的步骤:
1、注册中断函数ISR,它的函数原型如下:
Intalt_irq_register(alt_u32id,void*context,void(*handler)(void*,alt_u32));
id:中断优先级,即所注册的ISR是为哪个中断优先级的中断服务的
Context,为所注册的ISR传递参数,可以是NULL;
Handler,中断服务函数ISR的指针。
返回值是0时,表示中断注册成功;返回为负数,表明中断注册失败。这里面有一个需要注册的地方,如果handler不是NULL,则该优先级中断在注册成功后将自动使能,也即是说,只要我们在handler处有相应的ISR,我们就不需要再进行使能处理了。
2、编写ISR函数,这个函数由我们自己来写,而不是HAL系统提供的。它跟一般的函数定义没什么区别,只是对ISR的函数原型有特定的要求:voidISR_handler(void*context,alt_u32id);
context:传给ISR的形参,可以是NULL;
id:中断优先级
举例说明:
voidISR_key(void*context,unsignedlongid){IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_BASE,0x0);key_flag++;IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_BASE,0x0);}intinit_key(void){IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_BASE,0xf);IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_BASE,0x0);returnalt_irq_register(BUTTON_IRQ,NULL,ISR_key);}大体上的思路是,先判断初始化是否成功,如果init_key()函数返回值是0函数返回值是0,说明注册成功,打印register。
1、alt_irq_register()是向系统ISR注册用户ISR的API函数。其原形为:intalt_irq_register(alt_u32id,void*context,void(*isr)(void*,alt_u32))id代表被服务的中断向量号;context是运行参数指针,将来作为第一个参数传给用户ISR;Isr是一个函数指针,指向用户ISR入口;如果注册成功,函数返回0,并允许全局中断及被服务中断;不成功返回非0值。
2、alt_irq_disable()用来禁止某个中断服务。
原形为:Intalt_irq_disable(alt_u32id)
Id为对应的中断号;
返回值为0;
3、alt_irq_enable()与alt_irq_disable()对应,用来开启某个中断服务。
原形为:intalt_irq_enable(alt_u32id)
4、alt_irq_disable_all()用于关闭全局中断,
原形为:alt_irq_contextalt_irq_disable_all(void)
返回值为中断控制寄存器的值。
5、alt_irq_enable_all()用于开启全局中断,
原形为:voidalt_irq_enable_all(alt_irq_contextcontext)