-
Notifications
You must be signed in to change notification settings - Fork 0
microblaze其它例程
minichao9901 edited this page Feb 6, 2024
·
6 revisions
注意,只能用一个AXI Interconnect,地址分配才能正确。最初考虑将microblaze的I/D Cache用一个单独的AXI SmartConnect连接到BlockRam,发现地址不能自动分配,于是放弃了。 实际操作中,只需要把zynq,microblaze,uartlite, axi_gpio拿出来,让vivado自动连线即可。vivado会提示,microblaze使用什么时钟?选择来自zynq即可。
- 注意选择Processer。我们分别对mb和zynq各自创建了一个工程,都测试uart和gpio功能。
- 创建工程的时候,可以选择hello world例程模板。之后,删除helloworld.c文件中的内容,并贴上我们自己的程序。
- 对于mb,直接运行,即可打印,并LED灯轮流闪烁。
- 对于zynq,它的串口retarget默认是使用的ps端的串口,而不是uartlite。为了使用uartlite作为串口的retarget,通过按F3追溯xil_printf函数,我们发现,需要修改outbyte函数,这个函数位于outbyte.c文件中。修改方法如下: 原始outbyte.c,可见它用的是coresight的东西
#include "xparameters.h"
#include "xcoresightpsdcc.h"
#ifdef __cplusplus
extern "C" {
#endif
void outbyte(char c);
#ifdef __cplusplus
}
#endif
void outbyte(char c) {
XCoresightPs_DccSendByte(STDOUT_BASEADDRESS, c);
}
修改后outbyte.c
#include "xparameters.h"
#include "xuartlite_l.h"
#ifdef __cplusplus
extern "C" {
#endif
void outbyte(char c);
#ifdef __cplusplus
}
#endif
void outbyte(char c) {
XUartLite_SendByte(XPAR_AXI_UARTLITE_0_BASEADDR, c); //注意,这里必须手动指定XPAR_AXI_UARTLITE_0_BASEADDR
}
分别运行mb程序和zynq程序,可见都可以工作。
- microblaze闪烁LED1/2,并打印
- zynq闪烁LED3/4,并打印
- mb与zynq通过AXI BlockRam交互数据(前4个字节),其中mb是生产者,zynq是消费者。同时,我们把AXI BlockRam的第10个字节用作锁变量,用来创造临界区
- 效果非常棒!
microblaze的loop
int v=0;
while (1) {
xil_printf("Microblaze Print Now!\r\n");
// 依次翻转四个GPIO引脚
XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0001);
usleep(500000); // 等待500毫秒
XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0010);
usleep(500000);
//produce process
if(Xil_In8(XPAR_MB_CACHE_AXI_BRAM_CTRL_0_S_AXI_BASEADDR+10)==0){ //if lock=0
Xil_Out8(XPAR_MB_CACHE_AXI_BRAM_CTRL_0_S_AXI_BASEADDR+10, 1); //set lock=1
Xil_Out8(XPAR_MB_CACHE_AXI_BRAM_CTRL_0_S_AXI_BASEADDR, v);
Xil_Out8(XPAR_MB_CACHE_AXI_BRAM_CTRL_0_S_AXI_BASEADDR+1, v+1);
Xil_Out8(XPAR_MB_CACHE_AXI_BRAM_CTRL_0_S_AXI_BASEADDR+2, v+2);
Xil_Out8(XPAR_MB_CACHE_AXI_BRAM_CTRL_0_S_AXI_BASEADDR+3, v+3);
}
v++;
// XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0100);
// usleep(500000);
//
// XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b1000);
// usleep(500000);
}
zynq的loop
while (1) {
// // 依次翻转四个GPIO引脚
// XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0001);
// usleep(500000); // 等待500毫秒
//
// XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0010);
// usleep(500000);
xil_printf("Zynq Print Now!\r\n");
XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0100);
usleep(500000);
XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b1000);
usleep(500000);
//consume process
if(Xil_In8(XPAR_MB_CACHE_AXI_BRAM_CTRL_0_S_AXI_BASEADDR+10)==1){ //if lock=1
xil_printf("%d\r\n", Xil_In8(XPAR_MB_CACHE_AXI_BRAM_CTRL_0_S_AXI_BASEADDR));
xil_printf("%d\r\n", Xil_In8(XPAR_MB_CACHE_AXI_BRAM_CTRL_0_S_AXI_BASEADDR+1));
xil_printf("%d\r\n", Xil_In8(XPAR_MB_CACHE_AXI_BRAM_CTRL_0_S_AXI_BASEADDR+2));
xil_printf("%d\r\n", Xil_In8(XPAR_MB_CACHE_AXI_BRAM_CTRL_0_S_AXI_BASEADDR+3));
Xil_Out8(XPAR_MB_CACHE_AXI_BRAM_CTRL_0_S_AXI_BASEADDR+10, 0); //set lock=0
}
}