📄 rio.c
字号:
/********************************************************************************/
/* 本程序用来测试Xilinx Virtex II Pro系列FPGA MGT通信的性能 */
/* 本程序在c6416的环境下运行通过,CCS版本2.20.03 */
/* 版权所有(c)2004 北京邮电大学 电信工程学院 马健 045498 */
/********************************************************************************/
#include <std.h>
#include <csl_irq.h>
#include <stdio.h>
#include <csl_irq.h>
#include "reg1.h"
#define INTERVAL 0x7fffff /* FPGA两次发送数据的时间间隔 */
#define TOTAL_TIME 0x10000000 /* */
#define TX_RAM 0x80000000 /* 发送RAM的首地址(位于DSP EMIFA的ce0空间) */
#define TX_Ctrl_Reg 0x80040000 /* FPGA的发送控制寄存器(位于EMIFA的ce0空间)*/
#define RX_RAM 0x60000000 /* 接收RAM的首地址(位于DSP EMIFB的ce0空间) */
#define RX_Ctrl_Reg 0x60040000 /* FPGA的接收控制寄存器(位于EMIFB的ce0空间)*/
#define BUF_SZ 0x100 /* 进行数据校验的长度 */
#define true 1
#define false 0
#define Inc 1
#define Dec 0
/********************************************************************************/
/* 子函数,中断函数声明 */
/********************************************************************************/
void MGT_Reset(); /* MGT复位子函数 */
void MGT_Start(); /* MGT开始自程序 */
void FillData(); /* 向缓冲区写入校验图样数据子函数 */
void CompareData(); /* 校验数据子函数 */
void PrintResult(); /* 打印结果子函数 */
void timer0_start(); /* 定时器开启子函数 */
interrupt void EX5_ISR(); /* 外部中断5服务子程序 */
interrupt void Timer0_ISR(); /* 定时器中断服务子程序 */
/********************************************************************************/
/* 全局变量定义 */
/********************************************************************************/
int Err_Flag = false, PingPong = Inc, Finish_Flag = true, Start_Flag = true;
int Total_times = 0, Err_times = 0, Errors = 0, int_times = 0;
short Pre_Data[256], Current_Data[256];
void main(void)
{
int i; /* main函数局部变量定义 */
IER |= 0x4023; /* 中断使能寄存器配置,打开EXT_INT5以及定时器中断 */
CSR |= 0x1; /* 打开全局中断使能 */
T0CTL = 0x200;
T0PRD = 0x0FFF;
for (i = 0; i <= 0x10000000; i++){ /* 对FPGA的MGT通信进行i次的校验 */
Total_times++; /* 总的校验次数,用来计算错误概率 */
timer0_start(); /* 插入一段等待时间,使MGT更好同步 */
while(true){ /* 阻塞,等待MGT通信开始 */
if (Start_Flag == false)
break;
}
Start_Flag = true; /* 建立MGT通信开始阻塞标志 */
MGT_Reset(); /* MGT复位 */
FillData(); /* 填充新的数据 */
MGT_Start(); /* 开启MGT的通信传输 */
while(true){ /* 阻塞,等待MGT通信以及数据校验完成 */
if (Finish_Flag == false)
break;
}
Finish_Flag = true; /* 建立MGT通信完成阻塞标志 */
if( Err_Flag ){ /* 接收到的数据是否存在错误 */
Err_Flag = false;
Err_times++; /* 记录总的错误次数 */
PrintResult(); /* 打印错误情况,以帮助判断FPGA问题 */
}
}
}
/********************************************************************************/
/* FPGA的MGT 复位子函数 */
/* 通过DSP的EMIFA/B分别控制FPGA MGT的收发状态 */
/********************************************************************************/
void MGT_Reset()
{
//reset MGT_tx
*(unsigned volatile int *)TX_Ctrl_Reg = 0;
*(unsigned volatile int *)TX_Ctrl_Reg = 1;
*(unsigned volatile int *)TX_Ctrl_Reg = 0;
//reset MGT_rx
*(unsigned volatile int *)RX_Ctrl_Reg = 0;
*(unsigned volatile int *)RX_Ctrl_Reg = 1;
*(unsigned volatile int *)RX_Ctrl_Reg = 0;
}
/********************************************************************************/
/* 填充发送数据子函数 */
/* 通过DSP的EMIFA给FPGA的发送缓冲区交替写入正序和倒序的数据 */
/* 这样可以更方便的鉴别是否MGT通信是否存在边界问题 */
/********************************************************************************/
void FillData()
{
int i, j;
if ( PingPong ){ /* 给发送缓充区填入正序的数据 */
i = 0;
for (j = 0; j < BUF_SZ; j++){
*((unsigned volatile short *)TX_RAM + j) = i++;
}
PingPong = Dec; /* 修改乒乓开关,下次写入倒序数据 */
}
else{
i = 0xff; /* 给发送缓充区填入倒序的数据 */
for (j = 0; j < BUF_SZ; j++){
*((unsigned volatile short *)TX_RAM + j) = i--;
}
PingPong = Inc; /* 修改乒乓开关,下次写入正序数据 */
}
}
/********************************************************************************/
/* MGT发送子函数 */
/* 通过FPGA的MGT控制寄存器开启,MGT的发送 */
/********************************************************************************/
void MGT_Start()
{
//start MGT TX
*(unsigned volatile int *)TX_Ctrl_Reg = 0x0;
*(unsigned volatile int *)TX_Ctrl_Reg = 0x2;
*(unsigned volatile int *)TX_Ctrl_Reg = 0x0;
}
/********************************************************************************/
/* 进行数据比较的子函数 */
/* 可以得出发送错误数据的位置以及错误图样 */
/********************************************************************************/
void CompareData()
{
int j;
short Data_Receive;
Errors = 0; /* 子函数局部错误个数变量清零 */
if (PingPong == Dec ){ /* 比较倒序数据 */
for ( j = 0; j < BUF_SZ; j++){
Data_Receive = *((unsigned volatile short *)RX_RAM + j);
if ( Data_Receive != j ){ /* 发现错误 */
Current_Data[Errors] = Data_Receive;
Pre_Data[Errors] = j; /* 记录错误的数据,即发生错误的位置 */
Err_Flag = true; /* 建立错误标志,后面打印错误结果 */
Errors++; /* 记录本次错误个数 */
}
}
}
else{ /* 比较正序数据 */
for ( j = 0; j < BUF_SZ; j++){
Data_Receive = *((unsigned volatile short *)RX_RAM + j);
if ( Data_Receive != (0xff - j) ){
Current_Data[Errors] = Data_Receive;
Pre_Data[Errors] = 0xff - j;/* 发现错误 */
Err_Flag = true; /* 建立错误标志,后面打印错误结果 */
Errors++; /* 记录本次错误个数 */
}
}
}
}
/********************************************************************************/
/* 外部中断EXT_INT5的中断服务子程序 */
/* 根据需要打印出需要的数据,以判断MGT通信的性能 */
/********************************************************************************/
void PrintResult()
{
int i, Errors_local;
printf("Error!! Total_times = %d Err_Times = %d \n", Total_times, Err_times);
Errors_local = Errors;
if ( Errors_local > 10 )
{
Errors_local = 10;
}
if ( PingPong == Dec )
{
printf("Increase: \n");
for( i = 0; i < Errors_local; i++)
{
printf("0x%x: 0x%x ---> 0x%x \n", Pre_Data[i]*2, Pre_Data[i], Current_Data[i]);
}
printf("\n");
}
else
{
printf("Decrease \n");
for( i = 0; i < Errors_local; i++)
{
printf("0x%x: 0x%x ---> 0x%x \n", (0xff-Pre_Data[i])*2, Pre_Data[i], Current_Data[i]);
}
printf("\n");
}
}
/********************************************************************************/
/* 定时器timer0的开启子函数 */
/********************************************************************************/
void timer0_start()
{
T0CTL=0x00000200;
T0CTL=0x000002c0;
}
/********************************************************************************/
/* 外部中断EXT_INT5的中断服务子程序 */
/* MGT传输已经完成,可以开始进行数据的比较校验 */
/********************************************************************************/
interrupt void EX5_ISR()
{
Finish_Flag = 0; /* 清除MGT通信结束阻塞标志 */
CompareData(); /* 比较数据 */
}
/********************************************************************************/
/* 定时器中断服务子程序 */
/********************************************************************************/
interrupt void Timer0_ISR()
{
Start_Flag = 0; /* 清除MGT通信开始阻塞标志 */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -