1、背景介绍
最近项目中需要做一个JTAG测试功能,该功能是需要在DDR的一段空间中准备一组数据,发送出去,再用DDR的另一段空间收数,判断收到的数是否和发送的数据相同,以此加以验证。为此,需要在ZYNQ PL中实现GPIO通过HP读写DDR实地址的操作,同时在PS中通过ARM实现对发送和接收两段内存区域的读写操作。
2、实现方法
linux中提供了dev/mem来对DDR进行读写,让应用程序可以直接读写DDR实地址,很显然,这里也将采用这一方法。需要注意的是,在映射的过程中一定要加上O_SYNC标志位,这样才能保证Dcache和DDR中数据的一致性,确保读写时不光写入Dcache,也写入DDR中。
代码如下:
/*
* Copyright (c) 2012 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#include
#include
#include
#include
//#include
#include "gpio.h"
void gpio_init()
{
int temp;
int Delay;
SetGpioReg(GPIO_STATE_ADDR,0,0);
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp|jtx07_sbs;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp|jtx07_tlr_trst;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp|jtx07_tlr_trst6;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp|jtag_oe_n;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
//set ddr send addr and recv addr
SetGpioReg(GPIO_ADDR,0,0x10000000);
SetGpioReg(GPIO_ADDR,8,0x20000000);
//set test data length
SetGpioReg(GPIO_WR_LEN_ADDR,0,sector_length);
SetGpioReg(GPIO_WR_LEN_ADDR,8,sector_length);
//set jtag test clk
SetGpioReg(GPIO_JTAG_SEL_ADDR,0,TCK_1_MHz);
//release reset signal
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp|FPGA_RSTn;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp|jtx07_reset;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
for (Delay = 0; Delay < 8000000; Delay++);
//enable jtag test
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp|jtag_oe_n;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
for (Delay = 0; Delay < 8000000; Delay++);
//led trigger
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp|LED0;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
}
int main()
{
int i;
int fd;
int temp;
int Delay;
int *start;
int *start_test;
int buf[1024*1024];
for(i=0;i<1024;i++)
{
buf[i]=i;
}
#if 1
gpio_init();
#endif
//open /dev/mem with read and write mode
fd = open ("/dev/mem", O_RDWR | O_SYNC);
if (fd < 0)
{
printf("cannot open /dev/mem.");
return -1;
}
//map physical memory 0-80M bytes
start = (int *)mmap(NULL, 0x400000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x10000000);
if(start < 0)
{
printf("mmap failed.");
return -1;
}
//write memory
memcpy(start, buf, 1024*1024);
// cacheflush(start,1024*4,DCACHE);
// flush_cache_all();
#if 1
//Read value
for (i = 0;i <1024;i++)
{
printf("old mem[%d]:%x\n", i,*(start + i));
}
#endif
munmap(start, 0x400000); //destroy map memory
#if 1
printf("################################show new ddr################################\n");
start_test = (int *)mmap(NULL, 0x400000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x20000000);
if(start_test < 0)
{
printf("mmap failed.");
return -1;
}
for (i = 0;i <1024;i++)
{
printf("new mem[%d]:%x\n", i,*(start_test + i));
}
munmap(start_test, 0x400000); //destroy map memory
printf("################################before jtag start################################\n");
#endif
#if 1
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp|sjtag_test_prepare;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
for (Delay = 0; Delay < 80000000; Delay++);
temp=GetGpioReg(GPIO_STATE_ADDR,8);
printf("JTAG STATE IS 0x%x\n",(temp & 0xFFF00000)>>20);
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp|sjtag_test_start;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
printf("JTAG TEST START\n");
for (Delay = 0; Delay < 80000000; Delay++);
temp=GetGpioReg(GPIO_STATE_ADDR,8);
printf("JTAG STATE IS 0x%x\n",(temp & 0xFFF00000)>>20);
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp&~sjtag_test_start;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp&~FPGA_RSTn;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp&~sjtag_test_prepare;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
temp=GetGpioReg(GPIO_STATE_ADDR,8);
printf("JTAG STATE IS 0x%x\n",(temp & 0xFFF00000)>>20);
temp=GetGpioReg(GPIO_STATE_ADDR,0);
temp=temp|FPGA_RSTn;
SetGpioReg(GPIO_STATE_ADDR,0,temp);
temp=GetGpioReg(GPIO_STATE_ADDR,8);
printf("JTAG STATE IS 0x%x\n",(temp & 0xFFF00000)>>20);
#endif
printf("###########################after jtag start################################\n");
start = (int *)mmap(NULL, 0x400000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x20000000);
if(start < 0)
{
printf("mmap failed.");
return -1;
}
for (i = 0;i <1024;i++)
{
printf("new mem[%d]:%x\n", i,*(start + i));
}
munmap(start, 0x400000); //destroy map memory
close(fd); //close file
return 0;
}
上面代码中DDR发送区域物理起始地址为0x10000000,大小为0x400000
接收区域物理起始地址为0x20000000,大小为0x400000。