nios2c语言编程方法Nios2系列教程.doc_第1页
nios2c语言编程方法Nios2系列教程.doc_第2页
nios2c语言编程方法Nios2系列教程.doc_第3页
nios2c语言编程方法Nios2系列教程.doc_第4页
nios2c语言编程方法Nios2系列教程.doc_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

最小的Nios2系统前言2003年Altera推出了第一代32位Nios系统,开创了FPGA内构建高性能单片机的先河。随之2004年,Nios系统升级为Nios2系统,解决了软硬件开发中一些不方便的问题,软件开发环境从命令行编译转移到Eclips的IDE集成开放环境。Nios2开发环境从1.0、1.1到1.2逐步升级。后来为了和QuartusII软件升级同步,从QuartusII5.0版本开始Nios2的版本号正式和QuartusII统一。 作者我亲身经历过整个Nios2发展历程,深知Nios2的不同版本发生的巨大变化。目前网上流行的Nios2教程针对的版本相对较老,已经对初学者学习Nios2起不到指导作用,并且应广大爱好者的强烈要求,我在此使用QuartusII和Nios2的8.0版本详细叙述Nios2的开发流程。构建一个Nios2最小系统需要什么 构建一个Nios2最小系统需要具备以下资源: Nios2软核处理器 内存 Jtag_uart调试接口 1. Nios2软核处理器:这就是Nios2处理器的核心CPU,所有的外设都是和这个CPU通过Avalon总线连接到一起的。 2. 内存:编译后的程序代码需要通过下载线下载到该内存中,然后CPU的程序指针跳转到内存的首地址开始执行程序。 3. Jtag_uart调试接口:想要用单步调试等调试功能控制程序执行和查看程序变量,那么就需要这个调试接口。开始构建一个再简单不过的Nios2工程 整个步骤由2部分组成,第一部分建立Nios2硬件SOPC工程,第二部分建立Nios2软件工程。1建立Nios2硬件SOPC工程 建立Nios2硬件SOPC工程就是设计一个软核CPU和它的外设,编译成硬件电路放到FPGA芯片里面。这时候可以认为FPGA就是一个32位的单片机了,下面的软件开发都是针对这个单片机的。 打开QuartusII软件,新建一个工程选择EP2C8Q208C8芯片。 打开ToolsSOPC Builder菜单,进入SOPC Builder界面,新建一个名为nios32的SOPC文件,语言可以选择VHDL或者VerilogHDL。我们一共要添加3个IP模块:Nios2处理器、片上内存和Jtag_uart调试接口。11在左边的IP导航栏里面双击选择NiosII Processor,然后选择Nios II/e型的处理器。这个处理器占用FPGA逻辑资源最小。此时CPU的Reset Vector和Exception Vector都是不可选的,因为还没有设置内存。在添加了内存后,还要回到这个CPU设置里面设置这两项信息。12在左边的IP导航栏里选择On-Chip Memory(RAM or ROM)使用默认设置就可以了,RAM类型,32位数据宽度,4KB字节容量。13在左边的IP导航栏里选择jtag_uart使用默认设置就可以了。14最后建成的Nios2系统见下面的连接关系图:Avalon总线的连接关系图下图: 图中实心的圆圈代表连接,空心的圆圈代表不连接。cpu做为主设备Onchip_mem和jtag_uart作为从设备,从设备通过数据总线和指令总线连接到主设备上。Onchip_mem比较特殊,它既连接到cpu的指令总线上,又连接到数据总线上。这跟我们设计有关,我们是通过调试接口将程序下载到Onchip_mem中,程序然后从Onchip_mem开始执行指令。程序中产生的变量同时也是存放在Onchip_mem中的。15新建一个Block Diagram/Schematic File作为工程的顶层文件,将刚才制作的Nios32的symbol添加到bdf文件里。添加时钟和复位信号管脚,定义管脚的管脚号。最后编译工程,这样Nios2硬件部分的开发就算完成了,可以看到生成的sof和pof下载文件。2建立Nios2软件工程 建立Nios2软件工程和开发51单片机程序差不多,但是具体细节设置的地方有很多差异的地方。21新建工程打开Nios2软件IDE开发环境,新建一个NiosII C/C+ Application的工程。Nios2开发环境还自带了很多模版例子工程,我们这里选择Hello World Small工程。和51开发不同的是,Nios2可以自定义很多外设。因此不同的Nios2工程添加的外设可能都不同,需要在新建工程的时候指定你所要开发的那个Nios2硬件工程。这点很关键,这就是软件工程和硬件工程结合的地方。 一般新建一个工程时,系统会同时建立一个和该应用程序对应的库工程。库工程里面编译了指定Nios2硬件的外设驱动程序等api函数。这样就将应用程序和驱动库分离开来,方便用户管理。开发不同的应用程序时,可以共享一个驱动库。22编译工程建立工程后我们会在导航栏里面看到又两个新建的工程:hello_world_small_0和hello_world_small_0_syslib。点击编译按钮直接编译工程,最后查看编译结果。最终生成hello_world_small_0.elf二进制文件,程序代码大小为560个直接,内存剩余3536个字节。23软件在线调试工程工程编译成功后就可以用下载线调试你的程序了。在Run-Debug菜单里设置下载线和需要调试的软件工程。 Main页面和Target Connection页面里的设置完成后可以点击Debug按钮进行调试。此时Nios2的开发环境将刚才编译的二进制代码通过USB Blaster下载电缆,下载到FPGA片内的onchip-memory中,然后将Nios2的指令指针指向程序的第一条语句。注意,在调试程序前必须将硬件开发过程中生成的sof文件下载到FPGA里,否则FPGA里面是没有Nios2的CPU软核,程序将无法下载。 这时程序会停在man函数的第一条语句,点击全速运行按键,我们会在控制台里面看到程序运行的结果。程序在控制台里打出一段字符串,这就是整个程序的运行结果。总结 上面我们通过建立一个Nios2的最小系统,带领大家走过了从硬件到软件整个开发流程,看到了Nios2运行的结果。通过这个简单的例子,我们劈开了很多复杂繁琐的设置过程,让Nios2清晰的展现在大家面前。Nios2的开发不是想象中那么神秘,我们只要循序渐进的学习才能真正领会Nios2的强大和灵活。 上面的例子只是展示了一个可以运行的Nios2,它的功能非常简单,简单到只能完成打印一行字符串。由于受到FPGA片内存储器资源的限制,我们不能构建功能更加强大的代码,因此需要片外扩展Sdram来存储更大的程序代码。另外,我们的程序是在线下载到内存里面的,断电后程序代码也会消失,我们需要一个外部非易失的存储器如Flash来存储CPU的软件代码。 下一篇教程,我们将介绍如何扩展外部存储器Sdram和Flash。程序代码:nios2 c语言编程方法Nios2系列教程2nios2的C语言和X86或者单片机C语言很相似,上层的标准C库函数都是一样的,区别在于与底层硬件相关的各个外设寄存器的结构不同。如果我们把访问底层硬件寄存器的函数封装起来供上层调用,平台之间的移植就显得很容易了。 下面我总结了一些外设的寄存器结构以及用于访问寄存器的函数。1.可编程输入、输出口 PIO/Defined in pio_struct.h/ PIO Peripheral/ PIO Registerstypedef volatile structint np_piodata; / read/write, up to 32 bitsint np_piodirection; / write/readable, up to 32 bits, 1-output bitint np_piointerruptmask; / write/readable, up to 32 bits, 1-enable interruptint np_pioedgecapture; / read, up to 32 bits, cleared by any write np_pio;#define IOADDR_ALTERA_AVALON_PIO_DATA(base) _IO_CALC_ADDRESS_NATIVE(base, 0)#define IORD_ALTERA_AVALON_PIO_DATA(base) IORD(base, 0) #define IOWR_ALTERA_AVALON_PIO_DATA(base, data) IOWR(base, 0, data)#define IOADDR_ALTERA_AVALON_PIO_DIRECTION(base) _IO_CALC_ADDRESS_NATIVE(base, 1)#define IORD_ALTERA_AVALON_PIO_DIRECTION(base) IORD(base, 1) #define IOWR_ALTERA_AVALON_PIO_DIRECTION(base, data)IOWR(base, 1, data)#define IOADDR_ALTERA_AVALON_PIO_IRQ_MASK(base) _IO_CALC_ADDRESS_NATIVE(base, 2)#define IORD_ALTERA_AVALON_PIO_IRQ_MASK(base) IORD(base, 2) #define IOWR_ALTERA_AVALON_PIO_IRQ_MASK(base, data) IOWR(base, 2, data)#define IOADDR_ALTERA_AVALON_PIO_EDGE_CAP(base) _IO_CALC_ADDRESS_NATIVE(base, 3)#define IORD_ALTERA_AVALON_PIO_EDGE_CAP(base) IORD(base, 3) #define IOWR_ALTERA_AVALON_PIO_EDGE_CAP(base, data) IOWR(base, 3, data)2。可编程定时器/ Timer Peripheral/ Timer Registerstypedef volatile structint np_timerstatus;/ read only, 2 bits (any write to clear TO)int np_timercontrol; / write/readable, 4 bitsint np_timerperiodl; / write/readable, 16 bitsint np_timerperiodh; / write/readable, 16 bitsint np_timersnapl; / read only, 16 bitsint np_timersnaph; / read only, 16 bits np_timer;/ Timer Register Bitsenumnp_timerstatus_run_bit = 1, / timer is runningnp_timerstatus_to_bit = 0, / timer has timed outnp_timercontrol_stop_bit= 3, / stop the timernp_timercontrol_start_bit = 2, / start the timernp_timercontrol_cont_bit= 1, / continous modenp_timercontrol_ito_bit = 0, / enable time out interruptnp_timerstatus_run_mask = (11), / timer is runningnp_timerstatus_to_mask = (10), / timer has timed outnp_timercontrol_stop_mask= (13), / stop the timernp_timercontrol_start_mask = (12), / start the timernp_timercontrol_cont_mask= (11), / continous modenp_timercontrol_ito_mask = (1np_timerperiodl = (nasys_clock_freq_1000) & 0x0000ffff; na_timer1-np_timerperiodh = (nasys_clock_freq_1000 16) & 0x0000ffff; na_timer1-np_timercontrol = np_timercontrol_start_mask | np_timercontrol_cont_mask | np_timercontrol_ito_mask; running_yet = 1; return milliseconds_count; static void timer_isr_handler(int context) milliseconds_count+; na_timer1-np_timerstatus = 0;/ write to clear the IRQ #endif/ end of file3。通用异步串行口/ UART Registerstypedef volatile structint np_uartrxdata; / Read-only, 8-bitint np_uarttxdata; / Write-only, 8-bitint np_uartstatus; / Read-only, 8-bitint np_uartcontrol; / Read/Write, 9-bitint np_uartdivisor; / Read/Write, 16-bit, optionalint np_uartendofpacket; / Read/Write, end-of-packet character np_uart;/ UART Status Register Bitsenumnp_uartstatus_eop_bit= 12,np_uartstatus_cts_bit= 11,np_uartstatus_dcts_bit = 10,np_uartstatus_e_bit = 8,np_uartstatus_rrdy_bit = 7,np_uartstatus_trdy_bit = 6,np_uartstatus_tmt_bit= 5,np_uartstatus_toe_bit= 4,np_uartstatus_roe_bit= 3,np_uartstatus_brk_bit= 2,np_uartstatus_fe_bit = 1,np_uartstatus_pe_bit = 0,np_uartstatus_eop_mask= (112),np_uartstatus_cts_mask= (111),np_uartstatus_dcts_mask = (110),np_uartstatus_e_mask = (18),np_uartstatus_rrdy_mask = (17),np_uartstatus_trdy_mask = (16),np_uartstatus_tmt_mask= (15),np_uartstatus_toe_mask= (14),np_uartstatus_roe_mask= (13),np_uartstatus_brk_mask= (12),np_uartstatus_fe_mask = (11),np_uartstatus_pe_mask = (10);/ UART Control Register Bitsenumnp_uartcontrol_ieop_bit= 12,np_uartcontrol_rts_bit = 11,np_uartcontrol_idcts_bit = 10,np_uartcontrol_tbrk_bit= 9,np_uartcontrol_ie_bit = 8,np_uartcontrol_irrdy_bit = 7,np_uartcontrol_itrdy_bit = 6,np_uartcontrol_itmt_bit= 5,np_uartcontrol_itoe_bit= 4,np_uartcontrol_iroe_bit= 3,np_uartcontrol_ibrk_bit= 2,np_uartcontrol_ife_bit = 1,np_uartcontrol_ipe_bit = 0,np_uartcontrol_ieop_mask= (112),np_uartcontrol_rts_mask = (111),np_uartcontrol_idcts_mask = (110),np_uartcontrol_tbrk_mask= (19),np_uartcontrol_ie_mask = (18),np_uartcontrol_irrdy_mask = (17),np_uartcontrol_itrdy_mask = (16),np_uartcontrol_itmt_mask= (15),np_uartcontrol_itoe_mask= (14),np_uartcontrol_iroe_mask= (13),np_uartcontrol_ibrk_mask= (12),np_uartcontrol_ife_mask = (11),np_uartcontrol_ipe_mask = (10);#define IOADDR_ALTERA_AVALON_UART_RXDATA(base) _IO_CALC_ADDRESS_NATIVE(base, 0)#define IORD_ALTERA_AVALON_UART_RXDATA(base) IORD(base, 0) #define IOWR_ALTERA_AVALON_UART_RXDATA(base, data) IOWR(base, 0, data)#define IOADDR_ALTERA_AVALON_UART_TXDATA(base) _IO_CALC_ADDRESS_NATIVE(base, 1)#define IORD_ALTERA_AVALON_UART_TXDATA(base) IORD(base, 1)#define IOWR_ALTERA_AVALON_UART_TXDATA(base, data) IOWR(base, 1, data)#define IOADDR_ALTERA_AVALON_UART_STATUS(base) _IO_CALC_ADDRESS_NATIVE(base, 2)#define IORD_ALTERA_AVALON_UART_STATUS(base) IORD(base, 2) #define IOWR_ALTERA_AVALON_UART_STATUS(base, data) IOWR(base, 2, data)#define ALTERA_AVALON_UART_STATUS_PE_MSK (0x1)#define ALTERA_AVALON_UART_STATUS_PE_OFST (0)#define ALTERA_AVALON_UART_STATUS_FE_MSK (0x2)#define ALTERA_AVALON_UART_STATUS_FE_OFST (1)#define ALTERA_AVALON_UART_STATUS_BRK_MSK (0x4)#define ALTERA_AVALON_UART_STATUS_BRK_OFST (2)#define ALTERA_AVALON_UART_STATUS_ROE_MSK (0x8)#define ALTERA_AVALON_UART_STATUS_ROE_OFST (3)#define ALTERA_AVALON_UART_STATUS_TOE_MSK (0x10)#define ALTERA_AVALON_UART_STATUS_TOE_OFST (4)#define ALTERA_AVALON_UART_STATUS_TMT_MSK (0x20)#define ALTERA_AVALON_UART_STATUS_TMT_OFST (5)#define ALTERA_AVALON_UART_STATUS_TRDY_MSK (0x40)#define ALTERA_AVALON_UART_STATUS_TRDY_OFST (6)#define ALTERA_AVALON_UART_STATUS_RRDY_MSK (0x80)#define ALTERA_AVALON_UART_STATUS_RRDY_OFST (7)#define ALTERA_AVALON_UART_STATUS_E_MSK (0x100)#define ALTERA_AVALON_UART_STATUS_E_OFST (8)#define ALTERA_AVALON_UART_STATUS_DCTS_MSK (0x400)#define ALTERA_AVALON_UART_STATUS_DCTS_OFST (10)#define ALTERA_AVALON_UART_STATUS_CTS_MSK (0x800)#define ALTERA_AVALON_UART_STATUS_CTS_OFST (11)#define ALTERA_AVALON_UART_STATUS_EOP_MSK (0x1000)#define ALTERA_AVALON_UART_STATUS_EOP_OFST (12)#define IOADDR_ALTERA_AVALON_UART_CONTROL(base) _IO_CALC_ADDRESS_NATIVE(base, 3)#define IORD_ALTERA_AVALON_UART_CONTROL(base) IORD(base, 3)#define IOWR_ALTERA_AVALON_UART_CONTROL(base, data) IOWR(base, 3, data)#define ALTERA_AVALON_UART_CONTROL_PE_MSK (0x1)#define ALTERA_AVALON_UART_CONTROL_PE_OFST (0)#define ALTERA_AVALON_UART_CONTROL_FE_MSK (0x2)#define ALTERA_AVALON_UART_CONTROL_FE_OFST (1)#define ALTERA_AVALON_UART_CONTROL_BRK_MSK (0x4)#define ALTERA_AVALON_UART_CONTROL_BRK_OFST (2)#define ALTERA_AVALON_UART_CONTROL_ROE_MSK (0x8)#define ALTERA_AVALON_UART_CONTROL_ROE_OFST (3)#define ALTERA_AVALON_UART_CONTROL_TOE_MSK (0x10)#define ALTERA_AVALON_UART_CONTROL_TOE_OFST (4)#define ALTERA_AVALON_UART_CONTROL_TMT_MSK (0x20)#define ALTERA_AVALON_UART_CONTROL_TMT_OFST (5)#define ALTERA_AVALON_UART_CONTROL_TRDY_MSK (0x40)#define ALTERA_AVALON_UART_CONTROL_TRDY_OFST (6)#define ALTERA_AVALON_UART_CONTROL_RRDY_MSK (0x80)#define ALTERA_AVALON_UART_CONTROL_RRDY_OFST (7)#define ALTERA_AVALON_UART_CONTROL_E_MSK (0x100)#define ALTERA_AVALON_UART_CONTROL_E_OFST (8)#define ALTERA_AVALON_UART_CONTROL_DCTS_MSK (0x400)#define ALTERA_AVALON_UART_CONTROL_DCTS_OFST (10)#define ALTERA_AVALON_UART_CONTROL_RTS_MSK (0x800)#define ALTERA_AVALON_UART_CONTROL_RTS_OFST (11)#define ALTERA_AVALON_UART_CONTROL_EOP_MSK (0x1000)#define ALTERA_AVALON_UART_CONTROL_EOP_OFST (12)#define IOADDR_ALTERA_AVALON_UART_DIVISOR(base) _IO_CALC_ADDRESS_NATIVE(base, 4)#define IORD_ALTERA_AVALON_UART_DIVISOR(base) IORD(base, 4) #define IOWR_ALTERA_AVALON_UART_DIVISOR(base, data) IOWR(base, 4, data)#define IOADDR_ALTERA_AVALON_UART_EOP(base) _IO_CALC_ADDRESS_NATIVE(base, 5)#define IORD_ALTERA_AVALON_UART_EOP(base) IORD(base, 5)#define IOWR_ALTERA_AVALON_UART_EOP(base, data) IOWR(base, 5, data)#define ALTERA_AVALON_UART_EOP_MSK (0xFF)#define ALTERA_AVALON_UART_EOP_OFST (0)/ UART Routinesint nr_uart_rxchar(np_uart *uartBase); / 0 for default UARTvoid nr_uart_txcr(void);void nr_uart_txchar(int c,np_uart *uartBase); / 0 for default UARTvoid nr_uart_txhex(int x); / 16 or 32 bitsvoid nr_uart_txhex16(short x);void nr_uart_txhex32(long x);void nr_uart_txstring(char *s);nios2软件开发环境提供了HAL系统库(HAL System Library),它是联系上层应用软件和下层设备驱动软件的接口。它可以让应用软件调用标准的C语言库函数而不必要关心底层硬件如何实现。不同的硬件平台都有各自的HAL硬件抽象层,nios2也不例外。我们软件开发的任务不但要熟悉标准c语言如何与HAL层接口,而且要会开发新扩充硬件的驱动程序以及和HAL层接口。下面我们看看HAL层所提供的函数集。1。首先我们需要了解一个很重要的关于文件的结构体,所有关于文件和设备操作都要用到这个结构体。文件描述符结构定义/* The file descriptor structure definition.*/typedef struct alt_fd_salt_dev* dev;alt_u8*priv;int fd_flags; alt_fd;设备结构定义/* * The device structure definition. */struct alt_dev_s alt_llist llist; /* for internal use */const char*name; int (*open)(alt_fd* fd, const char* name, int flags, int mode);int (*close) (alt_fd* fd);int (*read)(alt_fd* fd, char* ptr, int len);int (*write) (alt_fd* fd, const char* ptr, int len); int (*lseek) (alt_fd* fd, int ptr, int dir);int (*fstat) (alt_fd* fd, struct stat* buf);int (*ioctl) (alt_fd* fd, int req, void* arg);所有对设备操作的函数最终都是由设备结构内定义的相关函数完成的。例如我们用open(file_name,flag,mode)函数对一个设备的文件描述符进行打开操作,经过HAL曾的过滤就会重定向到设备驱动内的open()函数来完成这个操作。理解这一点就能理解标准C语言库函数、HAL硬件抽象层和设备驱动程序三者之间的关系了。这对于理解软件运行的流程和进行跟踪调试都是有很大帮助的。下面我们分析一下一个程序从开始运行到结束的整个过程./* alt_main is the C entry point for the HAL. It is called by the assembler* startup code in the processor specific crt0.S. It is responsible for:* completing the C runtime configuration; configuring all the * devices/filesystems/components in the system; and call the entry point for * the users application, i.e. main().*/alt_main 是C程序的HAL入口,它是由用汇编写的启动代码所调用的。/他的功能是完成C程序的配置运行环境,配置系统内所有的硬件外设、文件系统和组件,/然后再调用用户main()程序的入口.void alt_main (void)/* Initialise the interrupt controller. */初始化中断控制器alt_irq_init (ALT_IRQ_BASE);/* Initialise the operating system */初始化操作系统(如果有的话)ALT_OS_INIT();/* * Initialise the semaphore used to control access to the file descriptor * list. */ /初始化访问文件描述表的信号灯ALT_SEM_CREATE (&alt_fd_list_lock, 1);/* Initia

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论