我们在使用MicroBlaze进行嵌入式系统设计的时候,通常会用到AXI Uartlite IP核与外部设备通信。AXI UART IP核实现了RS-232通讯协议,并使得大家可以设置串口通信相关的波特率、奇偶校验位、停止位和数据位等参数。本章我们进一步向大家介绍利用AXI UART IP核的中断进行通信的方法。
本章包括以下几个部分:
55.1简介
5.2实验任务
5.3硬件设计
5.4软件设计
5.5下载验证
5.1简介
AXI UART IP核提供UART信号和AMBA(高级微控制器总线体系结构高级可扩展接口)之间的AXI接口,并提供异步串行数据传输的控制器接口。
AXI UART Lite IP核具有以下特点:
对通过axi4-lite接口接收的字符执行并行到串行转换,并对从串行外围设备接收的字符执行串行到并行转换。
发送和接收8、7、6或5位字符,有一个停止位,并支持奇数、偶数或无奇偶位的配置。AXI UART Lite可以独立传输和接收数据。
下图为AXI UART IP核的顶层框图:
图 5.1.1 AXI UART IP核的顶层框图
AXI Interface(AXI接口):该模块实现了用于寄存器访问和数据传输的AXI4-LITE从接口。
UART Lite Registers(UART Lite寄存器模块):此模块包括内存映射寄存器。它由一个控制寄存器、一个状态寄存器和一对发射/接收FIFO组成,两个FIFO都有16个字符的深度。当接收FIFO变为非空或当发送FIFO变为空时,生成上升沿敏感的中断。此中断可以通过使用中断启用/禁用信号来屏蔽。
UART Control(UART控制模块):该模块包括Rx Control(接收控制)、Tx Control(发送控制)、BRG (Baud Rate Generator)和Interrupt Control(中断控制)四个模块。
AXI UART IP核提供了AXI4-Lite接口,我们可以通过AXI4-Lite接口读取状态寄存器或配置UART Control模块(复位收发FIFO、启用中断)。当AXI UART接收到上位机发送的数据后,Rx Control模块根据BRG模块产生的波特率将串行的数据转化成并行数据,写入接收FIFO,然后处理器通过AXI4-Lite接口读出接收FIFO中的数据;处理器中的数据也可以通过AXI4-Lite接口写入发送FIFO,然后经Tx Control根据BRG模块产生的波特率将并行数据转化为串行数据发送出去。
5.2实验任务
本章的实验任务是根据AXI UART IP核产生的中断信号,完成串口数据的收发。
5.3硬件设计
根据实验任务可以画出系统框图,如图 5.3.1所示:
图 5.3.1 系统框图
由上图系统框图可知,AXI UART模块产生中断信号,中断控制器检测到中断信号后,产生输出中断信号,最终传入MicroBlaze软核处理器。可以看出本实验的系统框图跟《Hello World》实验基本相同,只是多添加了AXI Inlerrupt Controller(中断控制器)模块。本实验我们将在《Hello World》实验的基础上进行硬件设计。
我们先打开《Hello World》实验的Vivado工程,打开后依次点击栏的“File-> Project->Save As...”,如图 5.3.2所示:
图 5.3.2 选择另存为
在弹出的另存为界面中可以输入新的工程名或更改保存位置,此处我们输入新的工程名“uart_interrupt”,工程位置保持默认即可然。
在Flow Navigator中,点击IP INTEGRATOR下的“Open Block Design”,打开Block Design。添加AXI Inlerrupt Controller IP核。如图 5.3.3所示:
图 5.3.3 添加AXI Inlerrupt Controller IP核
添加好IP核后将我们然后点击“Run Connection Automation”,在弹出的界面选中所有信号,点击“OK”,如图 5.3.4所示:
图 5.3.4 自动连线
我们在Diagram页面空白处右击,在弹出的菜单栏选择“Regenerate Layout”重新生成布局。如图 5.3.5所示:
图 5.3.5 重新生成布局
然后将AXI Interrupt Controller的输出信号“interrupt”接口与MicroBlaze的“INTERRUPT”接口相连,将新添加的AXI Uartlite的“interrupt”接口与AXI Interrupt Controller的intr[0:0]接口相连。如图 5.3.6所示:
图 5.3.6 手动连线
再次重新生成布局,最终的硬件设计连线图如图 5.3.7所示:
图 5.3.7 整体系统架构连接图
到这里我们的Block Design就设计完成了,在Diagram窗口空白处右击,然后选择“Validate Design”验证设计。验证完成后弹出对话框提示“Validation Successful”表明设计无误,点击“OK”确认。最后按快捷键“Ctrl + S”保存设计。
接下来在Source窗口中右键点击Block Design设计文件“system.bd”,然后依次执行“Generate Output Products”和“Create HDL Wrapper”。
由于本章实验用到的外部设备与《Hello World》实验相同,所以我们不需要修改管脚约束。
在左侧Flow Navigator导航栏中找到PROGRAM AND DEBUG,点击该选项中的“Generate Bitstream”,对设计进行综合、实现、并生成Bitstream文件。
在生成Bitstream之后,在菜单栏中依次点击“File->Export->Export hardware”导出硬件,并在弹出的对话框中,勾选“Include bitstream”,在导出路径最后添加“/vitis”。然后在菜单栏依次点击“Tools->Launch Vitis”,启动Vitis软件。
5.4软件设计
在将硬件导出至Vitis,并打开Vitis开发环境后,创建应用工程的步骤都是一样的,这里不再赘述,新创建的空白应用工程命名为“uart_interrupt”。
首先我们在uart_interrupt/src目录上右键,依次点击“New->Source File”,将源文件命名为“main.c”。
我们在新建的main.c文件中输入以下代码:
- 1 #include "xil_exception.h"
- 2 #include "xdebug.h"
- 3 #include "xparameters.h"
- 4 #include "xintc.h"
- 5 #include "xuartlite.h"
- 6 #include "xuartlite_l.h"
- 7
- 8 #define UART_DEVICE_ID XPAR_UARTLITE_0_DEVICE_ID //串口器件ID
- 9 #define UART_INTR_ID XPAR_INTC_0_UARTLITE_0_VEC_ID //串口中断ID
- 10 #define INTC_ID XPAR_INTC_0_DEVICE_ID //中断控制器ID
- 11
- 12 #define RX_NOEMPTY XUL_SR_RX_FIFO_VALID_DATA // 接收FIFO非空
- 13
- 14 static XIntc Intc; //中断控制器实例
- 15 static XUartLite Uart; //串口实例
- 16
- 17 void uart_handler(void *CallbackRef);
- 18
- 19 int main(void){
- 20 //初始化串口设备
- 21 XUartLite_Initialize(&Uart , UART_DEVICE_ID);
- 22 //初始化中断控制器
- 23 XIntc_Initialize(&Intc, INTC_ID);
- 24 //关联处理函数
- 25 XIntc_Connect(&Intc, UART_INTR_ID,(XInterruptHandler)uart_handler,&Uart);
- 26 //使能串口
- 27 XUartLite_EnableInterrupt(&Uart);
- 28 //打开中断控制器
- 29 XIntc_Start(&Intc, XIN_REAL_MODE);
- 30 //使能中断控制器
- 31 XIntc_Enable(&Intc,UART_INTR_ID);
- 32 //设置并打开中断异常处理功能
- 33 Xil_ExceptionInit();
- 34 Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
- 35 (Xil_ExceptionHandler)XIntc_InterruptHandler , &Intc);
- 36 Xil_ExceptionEnable();
- 37 while(1);
- 38 }
- 39
- 40 void uart_handler(void *CallbackRef)//中断处理函数
- 41 {
- 42 u8 Read_data;
- 43 u32 isr_status;
- 44 XUartLite *InstancePtr= (XUartLite *)CallbackRef;
- 45
- 46 //读取状态寄存器
- 47 isr_status = XUartLite_ReadReg(InstancePtr->RegBaseAddress ,
- 48 XUL_STATUS_REG_OFFSET);
- 49 if(isr_status & RX_NOEMPTY){ //接收FIFO中有数据
- 50 //读取数据
- 51 Read_data=XUartLite_ReadReg(InstancePtr->RegBaseAddress ,
- 52 XUL_RX_FIFO_OFFSET);
- 53 //发送数据
- 54 XUartLite_WriteReg(InstancePtr->RegBaseAddress ,
- 55 XUL_TX_FIFO_OFFSET, Read_data);
- 56 }
- 57 }
这里我们介绍一下这段代码,我们可以看到主函数部分与《按键控制中断实验》框架基本相同,不同的是本次实验使用的IP是AXI UART Lite,连接的外设是USB UART。首先代码第21行,对AXI UART初始化;代码第23行,初始化中断控制器;代码第25行XIntc_Connect函数,将中断源UART_INTR_ID(代码第9行)和中断服务函数uart_handler关联起来;接着就是使能串口中断,打开中断控制器,使能中断控制器,中断异常处理一系列操作,如代码第27到36行所示。
代码第40到53行是中断处理函数部分,当AXI UART接收到数据后,产生中断并进入中断处理函数。在代码第47和48行,我们调用了XUartLite_ReadReg函数,来读取状态寄存器(Status Register)。状态寄存器包含了启用中断后或出现错误时数据接收FIFO和数据发送FIFO的状态,共有八种状态,分别是:奇偶校验错误、帧错误、数据溢出、使能中断、发送FIFO满、发送FIFO空、接收FIFO满、接收FIFO空和接收FIFO有数据。
读取到状态寄存器后,就根据状态寄存器判断接收FIFO是否有数据,当检测到接收FIFO中有数据后(RX_NOEMPTY,接收FIFO非空),读出接收FIFO的数据,如代码第51和52行所示。代码第54、55行,将读出的数据写入发送FIFO,最后通过串口发送出去。这样我们就完成了用串口接收数据并发送的环回。
右键uart_interrupt_system,点击“Build Project”,编译工程。
5.5下载验证
首先我们将下载器与达芬奇开发板上的JTAG接口连接,下载器另外一端与电脑连接。然后使用USB连接线将USB_UART接口与电脑连接,用于串口通信。最后连接开发板的电源,并打开电源开关。
下载程序(过程不再赘述),软件程序下载完成后,打开资料提供的串口助手而非Vitis自带的Terminal,串口助手设置信息与Terminal相同。正确连接之后就可以发送数据。如图 5.5.1所示:
图 5.5.1 接收数据界面
串口成功打印出了“uart test”字符串,说明本次实验在达芬奇开发板上面下载验证成功。
|