测试环境
操作系统:Windows10
综合仿真:Vivado 2018.3
芯片验证:Zynq7010
处理器类型:MicroBlaze
AXI总线
关于AXI总线的介绍百度已经有很多,这里不再赘述。 这里主要确定一下类型,AXI总线分为3类:AXI4-Full、AXI4-Lite 和 AXI4-Stream,AXI4-Full写一个地址可以最大连续传输256个数据,而AXI4-Lite用于单个寄存器的数据传输,是AXI4-Full的简化版,所以我们串口完全没必要用到AXI4-Full,用简化版AXI4-Lite即可。
MicroBlaze和UART
下边的操作在上边两篇文章基础上进行操作。
打包我们的IP
之后Vivado会自动给我们生成一个示例代码,我们在他代码基础上做少量修改即可,主要是关注下边的4个寄存器:
把我们之前设计的UART代码导入到工程中:
将串口的tx和rx通过顶层文件引出:
在AXI设计文件中引入tx和rx:
串口主要是需要关注收发寄存器,收发标志位和分频系数,所以做以下分配(rflag表示收到数据标志位):
例化串口:
对代码做一下修改(截图中低8位表示[7:0],第8位是[8]):
设置标志位及数据同步:
重新打包IP:
重新打包后会自动关闭IP工程,返回到主工程,之后在我们的块设计中导入我们的uart:
自动连线,并从块设计文件中引出RX、TX端口:
可以修改映射地址:
重新生成块设计顶层文件:
修改顶层文件top.v
导出硬件,给SDK用:
程序设计
启动SDK,实现启动代码。因为此处理器设计时不带MMU,待会儿新建应用工程也不使用操作系统,所以直接使用结构体列出成员分布,直接指向外设地址即可:
新建应用工程:
测试代码:
下载:
连接到串口:
附上uart.c代码:
/***************************** Include Files *******************************/
#include "uart.h"
/************************** Function Definitions ***************************/
/* 寄存器分布
slv_reg0[1:0] - {rflag, tflag}
slv_reg1 - division
slv_reg2[7:0] - rdata
slv_reg3[7:0] - tdata
*/
typedef struct
{
u32 flag;
u32 division;
u32 rdata;
u32 tdata;
} UART;
volatile UART *uart = (UART *)0x44A00000;
void uart_putchar(char ch)
{
// 发送
uart->tdata = ch;
// 等待发送完成
while(!(uart->flag & 0x1));
// 清除标志位
uart->flag &= ~0x1;
}
char uart_getchar(void)
{
char retval;
// 等待接收完成
while(!(uart->flag & 0x2));
// 读取数据
retval = (char)uart->rdata;
// 清除标志位
uart->flag &= ~0x2;
return retval;
}
void uart_puts(char *s)
{
while(*s) uart_putchar(*s++);
}
// 串口初始化
void uart_init(u32 baud)
{
// 设置波特率 公式: division = clock/2/baud - 1;
uart->division = SYS_CLOCK/2/baud - 1;
// 清除标志位
uart->flag = 0;
}