正点原子 发表于 2020-10-13 10:17:21

【正点原子FPGA连载】第五章串口中断实验--摘自【正点原子】达芬奇之Microblaze 开发指南

本帖最后由 正点原子 于 2020-10-16 16:42 编辑

1)实验平台:正点原子达芬奇FPGA开发板
2)购买链接:https://detail.tmall.com/item.htm?id=624335496505
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz_dafenqi.html
4) 正点原子官方B站:https://space.bilibili.com/394620890
5)对正点原子FPGA感兴趣的同学可以加群讨论:876744900 点击加入:                                                                                                                              
6)关注正点原子公众号,获取最新资料





第五章串口中断实验

我们在使用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接口相连。如图 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”字符串,说明本次实验在达芬奇开发板上面下载验证成功。

页: [1]
查看完整版本: 【正点原子FPGA连载】第五章串口中断实验--摘自【正点原子】达芬奇之Microblaze 开发指南