前情回顾
(1)ZYNQ中PS端MIO操作
(2)ZYNQ中PS端MIO中断
(3)ZYNQ中PS端UART通信(4)ZYNQ中PS端XADC读取(5)Zynq中PL读写PS端DDR数据
PS端程序设计流程为:
输入起始地址和长度
PS端通过BRAM控制器写入BRAM数据
通知PL端控制器读取BRAM数据
PL内部读完后向相同位置写入数据,初始数据由PS端确定:
函数里先通过BRAM控制器写入数据,数据初值为TEST初值,之后配置PLRAM控制器参数,有长度,起始地址,初始数据,以及开始信号。
写完后使能write_end信号,触发GPIO中断
中断读取BRAM数据,打印显示
主循环如下:
while(1)
{
if (Gpio_flag)//如果完成,则进行下一次循环读写
{
Gpio_flag= 0 ;
printf("Please provide start address\t\n") ;
scanf("%d", &Start_Addr) ;
printf("Start address is %d\t\n", Start_Addr) ;
printf("Please provide length\t\n") ;
scanf("%d", &Len) ;
printf("Length is %d\t\n", Len) ;
Status= bram_read_write() ;
if (Status != XST_SUCCESS)
{
Gpio_flag = 1 ;
}
}
}
控制BRAM读写如下:
int bram_read_write()
{
u32 Write_Data = TEST_START_VAL ;//确定PL写的初值
int i ;
//判断是否越界
if ((Start_Addr + Len) > (BRAM_CTRL_HIGH -BRAM_CTRL_BASE + 1)/4)
{
xil_printf("******************************************\r\n");
xil_printf("Error! Exceed BramControlAddress Range!\r\n");
return XST_FAILURE ;
}
//给BRAM中写数据
for(i = BRAM_BYTENUM*Start_Addr ; i <BRAM_BYTENUM*(Start_Addr + Len) ; i += BRAM_BYTENUM)
{
XBram_WriteReg(XPAR_BRAM_0_BASEADDR, i ,Write_Data) ;
Write_Data+= 1 ;
}
//设置BRAM的读长度和读地址
PL_RAM_CTRL_mWriteReg(PL_RAM_BASE,PL_RAM_LEN , BRAM_BYTENUM*Len) ;
PL_RAM_CTRL_mWriteReg(PL_RAM_BASE,PL_RAM_ST_ADDR , BRAM_BYTENUM*Start_Addr) ;
//设置PL初始写数据地址
PL_RAM_CTRL_mWriteReg(PL_RAM_BASE,PL_RAM_INIT_DATA , (Start_Addr+1)) ;
//设置PL读RAM开始
PL_RAM_CTRL_mWriteReg(PL_RAM_BASE,PL_RAM_START , 1) ;
return XST_SUCCESS ;
}
首先是PL控制器从BRAM读数据,之后是写数据,可以看到红色为PL读出的BRAM数据,正是CPU写入的数据,从12开始,共10个数据,PL写入的数据为黄色部分从1开始,共10个数据。
中断处理,打印出读RAM的数据
void GpioHandler(void *CallbackRef)
{
XGpio *GpioInstancePtr = (XGpio *)CallbackRef ;
int Read_Data ;
int i ;
printf("Enter interrupt\t\n");
//clear interrupt status
XGpio_InterruptClear(GpioInstancePtr,GPIO_INTR_MASK) ;
for(i = BRAM_BYTENUM*Start_Addr ; i <BRAM_BYTENUM*(Start_Addr+ Len) ; i +=BRAM_BYTENUM)
{
Read_Data= XBram_ReadReg(XPAR_BRAM_0_BASEADDR , i) ;
printf("Address is %d\t Read data is %d\t\n", i/BRAM_BYTENUM,Read_Data) ;
}
Gpio_flag= 1 ;
}