microblaze读写ps端ddr的例程 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki
![image](https://private-user-images.githubusercontent.com/61445559/303012721-5be01290-7c31-4ac2-9661-0e976e1c2272.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMTI3MjEtNWJlMDEyOTAtN2MzMS00YWMyLTk2NjEtMGU5NzZlMWMyMjcyLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWY4NGMzNDhiYzY5Yzc5N2MyNTU1MDIwMzdiZGM5YmI2M2EyZTk4NzQ4NjNiZWU2YmUwMGU3YWZlMWU0NWFiYjEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.Cl85k0F6Fz28XTpMTD_sSzHJni7oxTZ4CB_xLGanSrE)
说明:
- zynq提供100MHz时钟,以及复位
- DDR3_test用按键触发
- MB的Cache用单独的SmartConnect连到Zynq的HP_AXI端口。M_AXI_DC/IC接口,就是Cache输出,用于连接慢速存储器,一般是片外的DDR或Flash。
- Zynq和MB都可以访问AXI_GPIO和AXI_Uartlite
- MB的DP端口还连到Zynq的S_AXI_GP0端口,因此MB还可以访问到Zynq的内部共享外设,例如Uart, Spi, I2c等等
![image](https://private-user-images.githubusercontent.com/61445559/303012753-6171beba-7923-467e-87de-3e6e89ab6ca7.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMTI3NTMtNjE3MWJlYmEtNzkyMy00NjdlLTg3ZGUtM2U2ZTg5YWI2Y2E3LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTc5OTJlMGM3YmM1NDAwM2ZlZWQ0YzUxODUwN2Q5NjY3N2Q5NzUyNGZkOTQ1YmJmYThkMGYwNWQxMmNhMjE5MmImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.D7siYHpeFxBQgXKH9YadCEviKupoCwzSgltxqmSzJqY)
需要手动设置Cache的地址范围为DDR的范围。另外,这里配置了Cache大小后,MB内部会包含block ram以实现Cache(Cache的RAM不需要自己手动加)。这从综合后MB所占用的资源可以看到。
![image](https://private-user-images.githubusercontent.com/61445559/303014306-be83a510-0f17-4895-8f24-d56743e30d19.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMTQzMDYtYmU4M2E1MTAtMGYxNy00ODk1LThmMjQtZDU2NzQzZTMwZDE5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTY2ODU0NWExMDQ4ODQyODZlN2Q4MDE2YmQ5NmVhYzQyZmZmMTYyMDNkMmIyNDQ5ZmQyMDMzMzY1MGZkZTExZmQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.I131L9f5_DkJ86rS9EPBJxuyAlLIFKOCMmEJiXMDjaQ)
这里设置地址范围很有讲究,哪些需要unmapped的,哪些需要mapped的,要根据需求仔细敲定。从这个地址设置看,MB的指令和数据都可以通过S_AXI_HP0接口访问到DDR。
![image](https://private-user-images.githubusercontent.com/61445559/303015660-c43b1888-6f91-463a-86dc-79edc436cb41.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMTU2NjAtYzQzYjE4ODgtNmY5MS00NjNhLTg2ZGMtNzllZGM0MzZjYjQxLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWU3MWU3NDViNzAwMDY0NzQ1YmJjNGVmODIyYTZlYTgyZGFkYjA0YTVkZTFhYTliOWI4OGFjNTFkYTk1NDE5NzMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.96BPOwamdQHJU20lHek1IQ5LSKf2KqhBS35neXUshVE)
mb在dram中运行。串口可以打印,灯可以运行,但速度非常慢,要过很久才能改变一次。看起来是usleep(500000)这个函数执行的有问题,变慢很多倍。追溯这个函数的底层,最终追溯到sleep_common()函数,发现这个函数是用汇编写的,其实就是软件延时了。这就可以解释了:在dram中运行,速度会慢10倍左右,因此导致延时会长接近于10倍。 如果我们把延时函数的数值减少到1/10,那么发现灯的运行速度接近于正常水平。
![image](https://private-user-images.githubusercontent.com/61445559/303016363-75a1dc05-c0c0-4d14-96d0-bb2afdb57498.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMTYzNjMtNzVhMWRjMDUtYzBjMC00ZDE0LTk2ZDAtYmIyYWZkYjU3NDk4LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWYxOTM3YWViOGIwYmZjM2I5Y2U3YmMxYWRhZDYxMTVjY2M3NmFkNWVjMDRlOWVmNDViYmI4ZjFhN2FmOTU0ZDgmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.SHcZXkSlSnyzTB1wToG6Gkr2HHPOMFpD_Ep0xhsPEsg)
![image](https://private-user-images.githubusercontent.com/61445559/303016415-5b2f6f1f-1012-4d03-a123-315582045fc3.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMTY0MTUtNWIyZjZmMWYtMTAxMi00ZDAzLWExMjMtMzE1NTgyMDQ1ZmMzLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWUxY2JjZmRkZmZjMDdlMjEwZmFmZTYzMjU3ZWRiOGM4NjFkZTYzNzk4OTZmZTA4ZDUyMjI2NWViYmM4MWUxZDcmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.24hLx8pKHHUZ0fbl_eH6YNnlpp8PYHl_2LbtQHGG3-w)
![image](https://private-user-images.githubusercontent.com/61445559/303016471-d81af395-4c65-4216-8541-af9b4a7e733e.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMTY0NzEtZDgxYWYzOTUtNGM2NS00MjE2LTg1NDEtYWY5YjRhN2U3MzNlLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWFjYTFhNTM2ZWVlMjk5MjIzNzQxNDY4MmEzNDMxYjUwYTI5YjE1NmEzYWFjMjE4ZTEzNDk5MjBjMjg3YmM2MTAmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.QBJgX6xLWxprX86mHorgYOtmXzZMB7GEpdV6Ms5w0y8)
#include <stdio.h>
#include "xparameters.h"
#include "xgpio.h"
#include "sleep.h"
#define GPIO_DEVICE_ID XPAR_AXI_GPIO_0_DEVICE_ID // 根据实际硬件配置修改
#define LED_CHANNEL 1
void test_ddr(UINTPTR addr, u32 length, u8 mode)
{
for(UINTPTR p=addr; p<addr+length; p+=4){
Xil_Out32(p,0x11223344);
}
for(UINTPTR p=addr; p<addr+length; p+=4){
int v= Xil_In32(p);
if(mode==0){
xil_printf("%p->%x\r\n",p,v);
}
else if(mode==1 && v!=11223344){
xil_printf("%p\r\n",p);
}
}
}
int main() {
XGpio gpio;
int Status;
xil_printf("Microblaze GPIO test!\r\n");
// 初始化GPIO
Status = XGpio_Initialize(&gpio, GPIO_DEVICE_ID);
if (Status != XST_SUCCESS) {
printf("GPIO Initialization failed\n");
return XST_FAILURE;
}
// 设置GPIO为输出
XGpio_SetDataDirection(&gpio, LED_CHANNEL, 0x00);
while (1) {
xil_printf("Microblaze Print Now!\r\n");
test_ddr(0x10000000,100,0); //test ddr
test_ddr(0xFFFC0000,100,0); //test ocm
// 依次翻转四个GPIO引脚
XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0001);
usleep(500000/10); // 等待500毫秒
XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0010);
usleep(500000/10);
XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0100);
usleep(500000/10);
XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b1000);
usleep(500000/10);
}
return 0;
}
![image](https://private-user-images.githubusercontent.com/61445559/303017144-f004cbca-68b2-4958-b906-662566d43643.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMTcxNDQtZjAwNGNiY2EtNjhiMi00OTU4LWI5MDYtNjYyNTY2ZDQzNjQzLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTEwNjliOWQwYzIzM2VlMjRmMzhkNDFiOWViYTE5ODI0YTA0ODAxOTY4ZWJjMmEyMDQ4NGUzNTdhY2RjZWMyYzkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.CAIrJNzOMoU3ca4U5ihmW3EZGAsshcmTZJpwXiodlQk)
可以看到,程序在dram中执行,读写dram正确,读写ocm不正确(原因未知,是否OCM是否需要额外设置?==>后来发现,将地址设为0xffff00000是可以的,这是OCM3的地址。也就是说,OCM0/1/2不行,OCM3可以?)。
修改后的程序如下:
- 注意关闭了ddr的cache
- 注意关闭了OCM3的cache。不关闭也可以读写,但是如果双核通信用OCM做通信,那么为了数据同步,就要关闭cache了
#include <stdio.h>
#include "xparameters.h"
#include "xgpio.h"
#include "sleep.h"
#include "xil_cache.h"
#include "xil_exception.h"
#include "xil_mmu.h"
#define GPIO_DEVICE_ID XPAR_AXI_GPIO_0_DEVICE_ID // 根据实际硬件配置修改
#define LED_CHANNEL 1
#define SHARE_BASE 0xffff0000 //共享OCM首地址,注意这是OCM3的地址
void test_ddr(UINTPTR addr, u32 length, u8 mode)
{
for(UINTPTR p=addr; p<addr+length; p+=4){
Xil_Out32(p,0x11223344);
}
for(UINTPTR p=addr; p<addr+length; p+=4){
int v= Xil_In32(p);
if(mode==0){
xil_printf("%p->%x\r\n",p,v);
}
else if(mode==1 && v!=11223344){
xil_printf("%p\r\n",p);
}
}
}
int main() {
XGpio gpio;
int Status;
Xil_DCacheDisable();
//S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0
Xil_SetTlbAttributes(SHARE_BASE,0x14de2); //禁用Cache缓存。不禁止也可以读写,但是如果双核通信用OCM做通信,那么为了数据同步,就要关闭cache了。
xil_printf("Zynq GPIO test!\r\n");
// 初始化GPIO
Status = XGpio_Initialize(&gpio, GPIO_DEVICE_ID);
if (Status != XST_SUCCESS) {
printf("GPIO Initialization failed\n");
return XST_FAILURE;
}
// 设置GPIO为输出
XGpio_SetDataDirection(&gpio, LED_CHANNEL, 0x00);
while (1) {
xil_printf("Zynq Print Now!\r\n");
test_ddr(0x10000000,100,0); //test ddr
test_ddr(SHARE_BASE,100,0); //test ocm
//Xil_Out8(SHARE_BASE,33);
// 依次翻转四个GPIO引脚
XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0001);
usleep(500000); // 等待500毫秒
XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0010);
usleep(500000);
XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b0100);
usleep(500000);
XGpio_DiscreteWrite(&gpio, LED_CHANNEL, 0b1000);
usleep(500000);
}
return 0;
}
![image](https://private-user-images.githubusercontent.com/61445559/303227954-0d3de208-802c-4d8e-afe1-9cddfe2d1158.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMyMjc5NTQtMGQzZGUyMDgtODAyYy00ZDhlLWFmZTEtOWNkZGZlMmQxMTU4LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWEyOWZmNzk4YjA0Njg3YzNhNmQ0MGNlNmI4ZThmMjYzZWIyYTIzMmJhMGI0OTM1NzU4NjdlNTNhZjA4YzAyZDEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.f7L9UEylzt5xEmpTrnrXzR-r1BgClxqPl4fc9cfA-Tc)
另一个试验,测试DDR3_Test模块功能。右按键触发DDR3_Test写入ddr数据,然后mb读出ddr数据。需要先将测试函数的写功能注释掉:
void test_ddr(UINTPTR addr, u32 length, u8 mode)
{
//for(UINTPTR p=addr; p<addr+length; p+=4){
//Xil_Out32(p,0x11223344);
//}
for(UINTPTR p=addr; p<addr+length; p+=4){
int v= Xil_In32(p);
if(mode==0){
xil_printf("%p->%x\r\n",p,v);
}
else if(mode==1 && v!=11223344){
xil_printf("%p\r\n",p);
}
}
}
运行结果:一旦按下按键启动DDR3_Test,程序就卡死了。因为DDR3_Test写入了0x10000000最低的4k字节,这个范围与程序section链接的范围重合,猜测是DDR3_Test写把程序给冲掉了。
![image](https://private-user-images.githubusercontent.com/61445559/303018051-9ce547d5-a015-4fa6-b355-1d17447d7912.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMTgwNTEtOWNlNTQ3ZDUtYTAxNS00ZmE2LWIzNTUtMWQxNzQ0N2Q3OTEyLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWFlYWJlMWM2M2IwMjdkMTFiZjFlM2FiYTk0OGQ4YWEwZWUxNTA0Y2Q0MjQ0OGUwNGI4NTQ2ODUxN2I5ZGZjZDQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.4fpYLnzDR4s79epCEyhxTympBrMal5M3CawNozjZyzI)
![image](https://private-user-images.githubusercontent.com/61445559/303018126-584da8d0-1758-4ddd-bd63-1d868e7f9077.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMTgxMjYtNTg0ZGE4ZDAtMTc1OC00ZGRkLWJkNjMtMWQ4NjhlN2Y5MDc3LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTJmOTRlMjNmZmEzMWQzZDg5MzVjN2YzZTJiNmY0MTNhMjlkOWY3ZDE2ZTQ2OGJkYjg4OWU1Yjk0N2JkOTI2NTcmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.UVJyYqnO0rrSg4CgoZ73V_VlUZfLLWF6-4WdNQBktVQ)
![image](https://private-user-images.githubusercontent.com/61445559/303018185-a73bb967-b31e-4731-b13c-4138655ed22e.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMTgxODUtYTczYmI5NjctYjMxZS00NzMxLWIxM2MtNDEzODY1NWVkMjJlLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWU2NmVmZDJlYzQ3NjViMjk3ZTFkMjIyNjAwM2M5ZmNkMzEyNDQxOGRmZTFkYTFkMjcxOGQyMmFmODJlNGU4NmImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.CpexEIxup0Ukq2zgFp3YSy0N0LtmeuIoDVuXcBW3x34)
修改程序section地址范围后,就可以正确运行了。初始的时候,ddr内部是随机数。按下按键后DDR3_test写入数据,然后mb再去读,就是写入的值了。
![image](https://private-user-images.githubusercontent.com/61445559/303019162-55fcd12c-7707-4b43-a175-5e1605d47517.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMTkxNjItNTVmY2QxMmMtNzcwNy00YjQzLWExNzUtNWUxNjA1ZDQ3NTE3LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTg4ODkxNjY2Nzg4Mjg1MzI5YjE1OGNiNDQ2MmYxYWRhNGRmMDU3ZmUxNDM0NmMxOTI4ZDNmNjcxOGY0M2YxODUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.bqLSwLB-y_PPA2LZCI4QNPo84UVRDzf0oiQYHdAf2RY)
手动修改程序的Section,放到local memory中。这个时候运行,一切都很正常了。 在程序中加入ddr_wr_test()函数,也可以正确运行。这个程序见前面的,这里不再重复了。
![image](https://private-user-images.githubusercontent.com/61445559/303019726-5410e796-bcac-479d-9b60-c8495691195b.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMTk3MjYtNTQxMGU3OTYtYmNhYy00NzlkLTliNjAtYzg0OTU2OTExOTViLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTIyOWJkYTVhN2ZmZDkzOTI0YjA5YWY0NWY0Y2MxMTJhNDU0YjFhNDU5YTRhZjc1YWIwOThmYWY3NTY4ODU4NDcmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.AeeYYNU1oGPy6IW3FfHXv9ivkDmqEfCWeOkvGGj2_3Q)
可以看到,程序在local memory中执行,读写dram正确,读写ocm不正确(与前面的情况一样)。
测试DDR3_Test模块功能。右按键触发DDR3_Test写入ddr数据,然后mb读出ddr数据。需要先将测试函数的写功能注释掉:
![image](https://private-user-images.githubusercontent.com/61445559/303020024-c2a0a520-966b-44f7-9711-e21cd52ad974.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMjAwMjQtYzJhMGE1MjAtOTY2Yi00NGY3LTk3MTEtZTIxY2Q1MmFkOTc0LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWJmZjg4YmI1YjFhM2JmMjQ4NmVhOWU1MWE1ZWY3ZGNiOTY0YmY0YzUxYzVkMjIwMjg1YjcwMDkxZWJjZDQyMjcmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.-gCWV81eHPEBCvX8FrCLNh8u1apwgmdrKQUDNTkThJs)
![image](https://private-user-images.githubusercontent.com/61445559/303020058-346128a5-f5c1-471c-b970-d23c750d94bc.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMjAwNTgtMzQ2MTI4YTUtZjVjMS00NzFjLWI5NzAtZDIzYzc1MGQ5NGJjLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTY5YzIwYzFlMzFkYTQ2NzA5YWQxZmEyNGM3ZDQzNDlhNDkyMWVhMzZmMmYzZTg1NzI2NDRkZGE2YTFmNjMwYjkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.RLNN8DuGXTzXXXNp6qJGRnBTEKXwVgfXFQerAGgy0J8)
DDR3_Test写之前,读出的都是FF;DDR3_test写入后,读出的是正确的数据。
![image](https://private-user-images.githubusercontent.com/61445559/303020198-fe48f98c-8df1-411b-8e47-794debbc1f0f.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMjAxOTgtZmU0OGY5OGMtOGRmMS00MTFiLThlNDctNzk0ZGViYmMxZjBmLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTZmNWNhMDNmMTZhM2VkYzM5Y2YwNGU3NWFlZmRiMDI5MmU4ZTBiNzgwYTdkOWMzZWQ4Nzc4OTJiYmE1NWRhZTQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.9BVXOHm2u1lRiQ8kvZXYlCeejsMPgvoT1_ttZnUUJMA)
手动修改程序的Section,放到OCM中。这个时候程序不能运行。 从总线的框图看,mb要从OCM取指令必须要经过I/D Cache,而mb的Cache的地址设置范围,没有包括OCM地址范围,应该能够解释。 进一步猜测:如果修改mb的cache的地址范围,让其位于OCM范围,那么应该就可以在OCM中运行(做了进一步的实验,将mb的cache地址范围修改为OCM范围,也不能运行。应该还有其它原因)。
TBD
zynq单独运行,用uartlite输出,运行结果ok。需要注释掉对OCM的读写才可以运行,否则程序运行会卡死(看样子zynq默认不能对OCM进行写,可能需要做一些配置?)。
需要修改outbyte函数,才能支持用uartlite做xil_printf
//#include "xparameters.h"
//#include "xuartps_hw.h"
//
//#ifdef __cplusplus
//extern "C" {
//#endif
//void outbyte(char c);
//
//#ifdef __cplusplus
//}
//#endif
//
//void outbyte(char c) {
// XUartPs_SendByte(STDOUT_BASEADDRESS, 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
}
![image](https://private-user-images.githubusercontent.com/61445559/303021339-cfae9434-0ace-444d-9ed5-2c18bd660b83.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMjEzMzktY2ZhZTk0MzQtMGFjZS00NDRkLTllZDUtMmMxOGJkNjYwYjgzLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTVhMGI2NDhiZmMyMTQ5NDgxYWI1ZjM2NmRmMmQ3MWU5YzMzYjkxYzhhNDA5NzQ4ZDJmOGQwYTkzZWY0OTZmMjQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.kfgcMrCtN_38U5vVpbOtPCAkiIUeTJoqjUm2Ggqchi8)
另一种方式,是打开BSP包的设置,配置stdin/stdout所使用的设备。这个更简单方便,推荐!
![image](https://private-user-images.githubusercontent.com/61445559/303021484-05c88375-d41b-45da-ad62-d631915703f0.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMjE0ODQtMDVjODgzNzUtZDQxYi00NWRhLWFkNjItZDYzMTkxNTcwM2YwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWIzMzU0N2NjNzRkMmExN2Y5ZTcwMzI4MDliMzllYjk2NGMxMTcxMDM3OGE3MzkyZThmZjgwMzU2YjM0NTFhZjImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.EmmVGKA9ilKjGWxX6uzyAUF0ul1DdyRlfxGI1WaGFqQ)
DDR3_test读写,结果不正确。写入了,但是读出的仍然是FF。但,如果重新再烧一遍程序,则读出的是0x01,0x02....0x15...等等,是对的。因此,猜测是cache的问题。写完之后,需要clean cache,让数据真实的写入ddr中(待进一步实验)。
进一步验证,确实是cache的问题。在程序中加入如下一句话,关闭Dcache后,即可正常读写,如下所示。 关于Dcache的更多操作,在xil_cache.h文件中。
#include "xil_cache.h"
Xil_DCacheDisable();
![image](https://private-user-images.githubusercontent.com/61445559/303022606-7b3bebc0-53ae-46fb-bbee-0ca9df507c17.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMjI2MDYtN2IzYmViYzAtNTNhZS00NmZiLWJiZWUtMGNhOWRmNTA3YzE3LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTc3ZDkwMmI1N2JiYmQxOTk2MjBiMzczMmU4YjY1MGEwZDRkM2I5OTljYWMzMTUzN2UwZDBiODNhZWQyZDhhNGEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.AsdfVM4SzVd9wV_DCrfGLLuDosDO0dz0aku2frVIWV4)
![image](https://private-user-images.githubusercontent.com/61445559/303022664-5ef0e6fc-1fa2-451e-9743-26dbae6eb11f.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMjI2NjQtNWVmMGU2ZmMtMWZhMi00NTFlLTk3NDMtMjZkYmFlNmViMTFmLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWU5NmFmMzNkNTJlN2QwNmY5MTdmMTFhOTdjODg0M2E0ZTkwNDA1ZjBmMzllNGU0NGVkODA2YzFkY2RiYTY5ZjEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.KcHGgr4znkYdhOsuysu4as6uxRIpsXb4Uano42Gdk2A)
![image](https://private-user-images.githubusercontent.com/61445559/303022694-4bf61fc6-5162-44fb-b7ba-a4413ae16189.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUxNzMyMDksIm5iZiI6MTcyNTE3MjkwOSwicGF0aCI6Ii82MTQ0NTU1OS8zMDMwMjI2OTQtNGJmNjFmYzYtNTE2Mi00NGZiLWI3YmEtYTQ0MTNhZTE2MTg5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MDElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTAxVDA2NDE0OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWRiZjhmNzc4ZDcwZmQ5NTQ1OGZjYzZhM2NmZWRkMzMxOGYwOTkzMGQ0MzQ0ZDVmNGRmMjBhNDRmNGMyMTg1MTMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.Ox4QzWzvxsXGYKCsfXXP25IlnEes6wzVvhyk2FpmBOE)
运行报错,提示无法取指令。直接这样不能运行(看XAPP1093手册,似乎还需要配置C_BASE_VECTORS,并使用FSBL才行,待研究)
首先,框图中,这条路径必须存在。这样mb才可以访问到ps端的外设。
其次,地址设置必须把PS_IOP纳入到mb的数据总线地址分配中。
编译导出bitstream后,这个时候mb_bsp右键打开bsp设置,可以看到stdin/stdout可以选择ps7_uart_0作为retarget外设。
选择后,重新编译运行,用ps_uart连接电脑,即可正常输出。结果如下: