microblaze与zynq共存情形(之一) - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

测试:配置模式1

mb的cache配置为ocm_remap区域,并且ic/dc只使用M_AXI_DC/IC => S_AXI_HP0 =>OCM_remap区域。这个时候mb到zynq的总线访问路径如下。

image image image

测试结果:

  • a. ddr运行:可以正确运行。ps_uart不能打印,符合预期,因为没有从mb的m_axi_dp到zynq的s_axi_gp0的路径。(这个时候led灯的闪烁速度很正常,跟以前在ddr中运行结果不一样)。从axi_uartlite打印的结果看,ocm_lower_addr可以读写,ocm_high_addr不能读写,甚至连ocm3的地址都不能读写。

  • b. local memory运行:可以正确运行。ps_uart不能打印,符合预期。 也是一样,从axi_uartlite打印的结果看,ocm_lower_addr可以读写,ocm_high_addr不能读写,甚至连ocm3的地址都不能读写。

  • c. ocm_higher_addr运行:完全不能运行。分析:这个从前面a,b的结果,已经可以看出端倪了。无论是否配置ocm_remap,ocm_higher_addr都不能正确读写,也就意味着,用ocm_higher_addr运行代码是不可行的。

  • d. ocm_lower_addr运行:可以运行,无论是否用zynq做ocm_remap都可以运行。分析:这个从前面a,b的结果,已经可以看出端倪了,由于无论是否配置ocm_remap, ocm_lower_addr都可以正确读写,因此意味着从ocm_lower_addr运行代码是可能的。实际确实如此

  • e. 以上有一个很有意思的点。虽然我们在地址分配中,没有给ddr分配地址,但是实际效果是它是可以读/写/执行程序。

image image image

以上分别是a, b, d的运行结果。因为c完全不能运行,所以没有结果。

测试:配置模式2

mb的cache配置为ocm_remap区域,并且ic使用M_AXI_IC => S_AXI_HP0 =>OCM_remap区域,而dp使用M_AXI_DP => S_AXI_HP0 => OCM_remap。这个时候mb到zynq的总线访问路径如下。 image image image

这种情形,可以理解:只有Icache,没有Dcache。另外,指令走HP通道,而数据走GP通道。 测试结果:

  • a. ddr运行:可以正确运行。ps_uart可以打印。ocm_lower_addr可以读写,ocm_high_addr不能读写,甚至连ocm3的地址都不能读写。这个情况与前面一样

  • b. local memory运行:可以正确运行。结果与情况a完全一样。

  • c. ocm_higher_addr运行:完全不能运行。与前面的情况一样。

  • d. ocm_lower_addr运行:可以运行,结果与前面一样。

  • e. 这个例子说明了,dp和dc都可以用来执行程序和读写数据。在功能上没有什么差别,当然在性能上肯定有差别

测试:配置模式3

在总线上,去掉dp,用dc去连接axi_gpio和axi_uartlite,是否可以?

测试:配置模式4

为什么ocm_higher_addr不能用?与什么有关系?

测试:配置模式5

有了前面基础,现在可以考虑,去掉local memory,是否可以运行了?

附录1: 地址分配错误的情形

image image

如果地址分配,HP与GP都指向同一个地址区域,那么将是错误的。如上图所示。也就是说,对于mb来说,dp和dc接口都可以读写数据,他们不允许指向同一个地址区间。

附录2:mb程序ld文件说明

ddr运行模式

image

imlb/dmlb运行模式

image

ocm_higher_addr运行模式

image

附录3:典型测试程序:

mb的程序

#include <stdio.h>
#include "xparameters.h"
#include "xgpio.h"
#include "sleep.h"
#include "xil_cache.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;

    usleep(50000);
    Xil_DCacheDisable();

    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) {
//        scanf("%c",&c);
//        while(c!='c');

    	xil_printf("Microblaze Print Now!\r\n");
        //test_ddr(0x10000000,16,0); //test ddr
		test_ddr(0xfffc0000,16,0); //test ocm, remap模式才可以访问
		test_ddr(0xfffd0000,16,0); //test ocm, remap模式才可以访问
		test_ddr(0xfffe0000,16,0); //test ocm, remap模式才可以访问
		test_ddr(0xffff0000,16,0); //test ocm, remap模式才可以访问
		test_ddr(0x00000000,16,0); //test ocm0, 默认非remap模式可以访问
		test_ddr(0x00010000,16,0); //test ocm1, 默认非remap模式可以访问
		test_ddr(0x00020000,16,0); //test ocm2, 默认非remap模式可以访问
		test_ddr(0xFFFF0000,16,0); //test ocm3, 默认非remap模式可以访问


        // 依次翻转四个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;
}

zynq的程序, 只负责ocm_remap_to_higher_addr

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xgpio.h"

void Xil_Remap_OCM(void)
{
    xil_printf("%x\r\n",Xil_In32(0xf8000910));  //read slcr.ocm_cfg
    Xil_Out32(0xf8000000+0x08,0xdf0d); //slcr.unlock
    Xil_Out32(0xf8000910,0x000f);      //slcr.ocm_cfg(remap ocm from 0x00000000->0xfffc0000)
    Xil_Out32(0xf8000000+0x08,0x0);    //slcr_unlock
    xil_printf("%x\r\n",Xil_In32(0xf8000910));  //read slcr.ocm_cfg again
}

int main()
{
    init_platform();
    Xil_Remap_OCM();

    cleanup_platform();
    return 0;
}
⚠️ **GitHub.com Fallback** ⚠️