复旦微用AXIDMA接收原始图像

参考SD卡移植博客,,移植SD卡相应代码

AXIDMA部分Demo下的bsp包整个pl搬到相应位置,添加相应文件

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include "platform.h"
#include "fmsh_common.h"
#include "ps_init.h"
#include "fmsh_print.h"

#include "fmsh_ps_parameters.h"
#include "fmsh_gic.h"
#include "fmsh_gic_hw.h"
#include "fmsh_dmac_lib.h"
#include "cache.h"

/* SD卡包含库 */
#include "diskio.h"
#include "ff.h"

/* axidma包汉库 */
#include "xaxidma.h"
#include "xparameters.h"
#include "fmsh_parameters.h"

/* Emio包含库 */
#include "fmsh_gpio_public.h"

/* xil_printf should be added the debug file of the pl/inlcude/ path 
 * the compiler's include path can be in the project's options!!!
 */
#define xil_printf 					fmsh_print
#define SD_SAVE
 
#ifdef XPAR_UARTNS550_0_BASEADDR
#include "xuartns550_l.h"       /* to use uartns550 */
#endif

/************************** Constant Definitions *****************************/

/*
 * Device hardware build related constants.
 */

#define DMA_DEV_ID					XPAR_AXIDMA_0_DEVICE_ID

/* Note FMQL's rom is fixed at the 1st MB address, and DDR start
 * from the 1st MB address, it is not the same with zynq!!!!
 * No scu filter function for it!!! 
 */
#define MEM_BASE_ADDR				0x01000000
#define RX_INTR_ID					PL0_INT_ID
// #define RX_INTR_ID				XPAR_FABRIC_AXIDMA_0_S2MM_INTROUT_VEC_ID
#define TX_INTR_ID					XPAR_FABRIC_AXIDMA_0_MM2S_INTROUT_VEC_ID
#define INTC  						FGicPs

/* 
 Timeout loop counter for reset
 */
#define RESET_TIMEOUT_COUNTER		10000
#define TEST_START_VALUE			0xC
/*
 * Buffer and Buffer Descriptor related constant definition
 * 长度取决于axi dma ip的配置: Width of Buffer Length Register(8-26) 设置
 * 驱动默认设置为23bit, 测试vivado工程里配置为26bit
 */
#define CONFIG_SYS_CACHELINE_SIZE  	(64)
#define CONFIG_SYS_CACHELINE_MASK	(CONFIG_SYS_CACHELINE_SIZE - 1)
#define MAX_PKT_LEN					(XAXIDMA_MAX_TRANSFER_LEN & (~CONFIG_SYS_CACHELINE_MASK))
#define PIXEL_LEN					(640 & (~CONFIG_SYS_CACHELINE_MASK))
#define NUMBER_OF_TRANSFERS			10

#define TX_BUFFER_BASE				(MEM_BASE_ADDR)
#define RX_BUFFER_BASE				(MEM_BASE_ADDR + MAX_PKT_LEN)
//#define RX_BUFFER_HIGH			(MEM_BASE_ADDR + 0x004FFFFF)

/* SD卡 */
// #define FWRITE_READ_BUFFER_SIZE_MAX (8*1024*1024)  /*读写压力测试的buffer大小,不需要4字节对齐、64字节对齐或512字节对齐等限制*/
#define FWRITE_READ_BUFFER_SIZE_MAX (2*640*512)  /*读写压力测试的buffer大小,不需要4字节对齐、64字节对齐或512字节对齐等限制*/
#define CONFIG_VOLUMES_NUM 			(4)  /*确保CONFIG_VOLUMES_NUM ≤ 4,给每个sdmmc预留了最多4个分区*/
#define MANUAL_FORCE_FDISK_EN  		0  /*如果想把SD/EMMC里已有的分区删除变成裸盘,配置为1,否则为0*/

/************************** Function Prototypes ******************************/

#ifdef XPAR_UARTNS550_0_BASEADDR
static void Uart550_Setup(void);
#endif

// static int CheckData(int Length, u8 StartValue);
static void TxIntrHandler(void *Callback);
static void RxIntrHandler(void *Callback);

static int 	SetupIntrSystem(INTC * IntcInstancePtr,
			   				XAxiDma * AxiDmaPtr, u16 TxIntrId, u16 RxIntrId);
static void DisableIntrSystem(INTC * IntcInstancePtr,
							u16 TxIntrId, u16 RxIntrId);
/* sd卡 */
u32 		fmsh_SdEmmcInitPartFAT32(u32 ulPhyDriveNo,u32 ulPartitionNum,DWORD plist[]);
FRESULT 	scan_files (TCHAR* path);
FRESULT 	scan_dirs (TCHAR* path);
void 		fdisk_physicaldrive (u32 ulPhyDriveNo);
FRESULT 	remove_file(TCHAR* path);
FRESULT 	rm_all_files_in_dir(TCHAR* path);
FRESULT 	rm_all_empty_dir(TCHAR* path);
void 		show_all_file_info_of_dir(TCHAR* path);
void 		show_all_dir_of_partition(TCHAR* path);
void 		remove_all_dirs(TCHAR* path);
void 		remove_one_dir_or_file(TCHAR* path);
FRESULT 	show_partition_usage(u32 ulPhyDriveNo,u32 ulPartitionNum);
u32 		upload_bin_to_sdmmc(char* host_file,char* dst_path);
u32 		sdmmc_wr_rd_test(u32 ulPhyDriveNo,u32 ulPartitionNum);

void 		FDmaPs_IRQ (void *InstancePtr);


/************************** Variable Definitions *****************************/
/*
 * Device instance definitions
 */


static 	XAxiDma 	AxiDma;		/* Instance of the XAxiDma */
FGpioPs_T 			g_gpios;
// FGpioPs_Config 		*gpio_cfgPpr;
/*
 * Flags interrupt handlers use to notify the application context the events.
 */
volatile int 		TxDone;
volatile int 		RxDone;
volatile int 		Error;
/* sd卡 */
FATFS 				fatfs[FF_VOLUMES];
BYTE 				f_mkfsBuff[FF_VOLUMES][FF_MAX_SS];
/*由于使用了dcache,指定起始地址以cacheline size对齐*/
BYTE 				work[FF_MAX_SS] __attribute__ ((aligned (CONFIG_SYS_CACHELINE_SIZE)));  /* Working buffer */
/*由于使用了dcache,指定起始地址以cacheline size对齐*/
char 				m_dir_buffer[256] __attribute__ ((aligned (CONFIG_SYS_CACHELINE_SIZE)));/*假定目录名最大255个字节,预留一个字符结束符位置*/


/* Volume mapping table (FF_MULTI_PARTITION == 1) */
/*每个物理盘最多4个分区*/
PARTITION VolToPart[FF_VOLUMES] = {
    {0, 1},    /* "0:" ==> 1st partition in PD#0 */
    {0, 2},    /* "1:" ==> 2nd partition in PD#0 */
    {0, 3},    /* "2:" ==> 3nd partition in PD#0 */
    {0, 4},    /* "3:" ==> 4th partition in PD#0 */
    {1, 1},    /* "4:" ==> 1st partition in PD#1 */
    {1, 2},    /* "5:" ==> 2nd partition in PD#1 */
    {1, 3},    /* "6:" ==> 3nd partition in PD#1 */
    {1, 4}     /* "7:" ==> 4th partition in PD#1 */    
};


FDmaPs_T 			g_DMA_dmac;
FDmaPs_Param_T 		g_DMA_param;
FDmaPs_Instance_T 	g_DMA_instance;

#define FMSH_ReadData8(baseAddr, offSet)		*((volatile unsigned char *)(baseAddr + offSet))
#define FMSH_WriteData8(baseAddr, offSet, data)	*((volatile unsigned char *)(baseAddr + offSet)) = data   
#define FMSH_ReadData16(baseAddr, offSet)		*((volatile u16 *)(baseAddr + offSet))
#define FMSH_WriteData16(baseAddr, offSet, data)	*((volatile u16 *)(baseAddr + offSet)) = data   

/* 
	地址adr对齐的示例代码
	const u32 CACHE_LINE = 64U;

	u32 adr = (u32)malloc(DMA_LENGTH + 2*CACHE_LINE);

	    //对齐CACHE_LINE

	    adr += CACHE_LINE;

	    adr &= ~(CACHE_LINE - 1U);

	    g_txDma_mgr.orig_ptr =(u8*) adr;

	长度对齐:从DDR更新DCache

	if(g_tcp_mgr.total_byte_num % CACHE_LINE>0){ dcacheInvalidLen = (g_tcp_mgr.total_byte_num / CACHE_LINE + 1)*CACHE_LINE; }

	else{ dcacheInvalidLen = (g_tcp_mgr.total_byte_num ;  }

	Xil_DCacheInvalidateRange((INTPTR)g_rxDma_mgr.orig_ptr, dcacheInvalidLen );


 */

void FDmaPs_IRQ (void *InstancePtr)
{
	FDmaPs_irqHandler((FDmaPs_T *)InstancePtr);
}

/****************************************************************************************************************
* u32 ulPhyDriveNo---physical drive number : 0 or 1
* u32 ulPartitionNum----logical partition number of a physical drive:1,2,3 or 4
* DWORD plist[]----List of partition size to create on the physical drive eg:
              {50, 50, 0, 0};  Divide the drive into two equal partitions 
              {0x10000000,50,50,0}; 256M sectors for 1st partition and 50% of the left for 2nd partition and 3nd partition each
              {20, 20, 20, 0}; 20% for 3 partitions each and remaing space is left not allocated
              {25, 25, 25, 25}; 25% for 4 partitions each
              {100, 0, 0, 0}; only one partition,all allocated to this partition
*****************************************************************************************************************/
u32 fmsh_SdEmmcInitPartFAT32(u32 ulPhyDriveNo,u32 ulPartitionNum,DWORD plist[])
{
	FRESULT Res = FR_OK;
	TCHAR *Path[] = {"0:","1:","2:","3:","4:","5:","6:","7:"};/*Logical drive number */
	u32 i;

	if(CONFIG_VOLUMES_NUM < ulPartitionNum)
	{
		return FMSH_FAILURE;  
	}

	if(SDMMCPS_0_DEVICE_ID == ulPhyDriveNo)
	{

		FDmaPs_T *pDmac = &g_DMA_dmac;
		FDmaPs_Instance_T *pInstance = &g_DMA_instance;
		FDmaPs_Param_T *pParam = &g_DMA_param;
		FDmaPs_Config *pDmaCfg;
		s32 Status;
		/*step1~step3的顺序不能调整,这3步作为整体放在sdmmc DMA操作之前*/
		/*step1: gic初始化 ,使用DMA中断模式必需*/
		FGicPs_SetupInterruptSystem(&IntcInstance);
		FMSH_ExceptionRegisterHandler(FMSH_EXCEPTION_ID_IRQ_INT,(FMSH_ExceptionHandler)FGicPs_InterruptHandler_IRQ,&IntcInstance); 

		/*step2: Initialize the DMA Driver */
		pDmaCfg = FDmaPs_LookupConfig(FPAR_DMAPS_DEVICE_ID);
		if (pDmaCfg == NULL) {
		  return FMSH_FAILURE;
		}
		FDmaPs_initDev(pDmac, pInstance, pParam, pDmaCfg);
		Status = FGicPs_registerInt(&IntcInstance, DMA_INT_ID,
				(FMSH_InterruptHandler)FDmaPs_IRQ, pDmac);
		if (Status != FMSH_SUCCESS)
		{
		  return FMSH_FAILURE;
		}
		Status = FDmaPs_autoCompParams(pDmac);
		if (Status != FMSH_SUCCESS)
		{
		  return FMSH_FAILURE;
		}

		/*step3: 设置sdmmc工作在DMA模式下,只有sdmmc0支持DMA方式 */
		set_sdmmc_workmode(sdmmc_trans_mode_dw_dma);
	}

	for(i=0;i < ulPartitionNum;i++)
	{
		/* Try to mount FAT file system */
		Res |= f_mount(&fatfs[i+4*ulPhyDriveNo], Path[i+4*ulPhyDriveNo], 1);
	}
	if (Res != FR_OK) 
	{        
		fmsh_print("Volume is not FAT formatted, formatting FAT32,please waiting......\r\n");
		Res = f_fdisk(ulPhyDriveNo, plist, work);  /* Divide physical drive */
		if (Res != FR_OK) 
		{
		  fmsh_print("f_fdisk err[%d]!\r\n",Res);
		  return FMSH_FAILURE;
		}
		else
		{
		  fmsh_print("f_fdisk OK!\r\n");
		}

		for(i=0;i < ulPartitionNum;i++)
		{
		  /*make FAT32 fs for each partition*/
		  Res = f_mkfs(Path[i+4*ulPhyDriveNo], FM_FAT32, 0, f_mkfsBuff[i+4*ulPhyDriveNo], sizeof(f_mkfsBuff[i+4*ulPhyDriveNo]));
		  if (Res != FR_OK) 
		  {
		    fmsh_print("Unable to format FATfs[%d],err[%d]\r\n",i,Res);
		    return FMSH_FAILURE;
		  }
		  else
		  {
			fmsh_print("partition[%d],mkfs FAT32 OK!\r\n",i);
		  }

		  Res = f_mount(&fatfs[i+4*ulPhyDriveNo], Path[i+4*ulPhyDriveNo], 1);
		  if (Res != FR_OK) 
		  {
		    fmsh_print("Unable to mount FATfs[%d],err[%d]\r\n",i,Res);
		    return FMSH_FAILURE;
		  }
		  else
		  {
			fmsh_print("partition[%d],mount FAT32 OK!\r\n",i);
		  }
		}
	}

	// (void)show_partition_usage(ulPhyDriveNo,ulPartitionNum);
	fmsh_print("File system initialization successful\r\n");
	return FMSH_SUCCESS;
}

// FRESULT scan_files (TCHAR* path)
// {
//     FRESULT rc;	 /* Result code */
// 	DIR dir;
// 	static FILINFO fno;
// 	UINT i;
	
// 	rc = f_opendir (&dir,path);
// 	if(FR_OK == rc)
// 	{
// 		for (;;) 
// 		{
// 			rc = f_readdir(&dir, &fno); /* Read a directory item */
// 			if (rc != FR_OK || fno.fname[0] == 0) 
// 				break;  /* Break on error or end of dir */
// 			if (fno.fattrib & AM_DIR) 
// 			{   /* It is a directory */
// 			    i = strlen(path);
// 			    sprintf(&path[i], "/%s", fno.fname);
// 			    rc = scan_files(path);  /* Enter the directory */
// 			    if (rc != FR_OK) 
//                   break;
// 			    path[i] = 0;
// 			} else 
// 			{   /* It is a file. */
// 			    fmsh_print("%s/%s Size: %lu  Timestamp: %u/%02u/%02u, %02u:%02u Attributes: %c%c%c%c%c\r\n",\
// 					path, fno.fname,fno.fsize,(fno.fdate >> 9) + 1980, fno.fdate >> 5 & 15, fno.fdate & 31,\
// 	               fno.ftime >> 11, fno.ftime >> 5 & 63,\
// 	               (fno.fattrib & AM_DIR) ? 'D' : '-',\
// 	               (fno.fattrib & AM_RDO) ? 'R' : '-',\
// 	               (fno.fattrib & AM_HID) ? 'H' : '-',\
// 	               (fno.fattrib & AM_SYS) ? 'S' : '-',\
// 	               (fno.fattrib & AM_ARC) ? 'A' : '-');
// 			}
// 		}
// 		f_closedir(&dir);
// 	}
// 	else
// 	{
// 		fmsh_print("directory [%s] not exist!\r\n",path);
// 		return FR_NO_PATH;
// 	}
//     return rc;
// }

// FRESULT scan_dirs (TCHAR* path)
// {
//     FRESULT rc;	 /* Result code */
// 	DIR dir;
// 	static FILINFO fno;
// 	UINT i;
	
// 	rc = f_opendir (&dir,path);
// 	if(FR_OK == rc)
// 	{
// 		for (;;) 
// 		{
// 			rc = f_readdir(&dir, &fno); /* Read a directory item */
// 			if (rc != FR_OK || fno.fname[0] == 0) 
// 				break;  /* Break on error or end of dir */
// 			if (fno.fattrib & AM_DIR) 
// 			{   /* It is a directory */
// 				fmsh_print("%s/%s Size: %lu  Timestamp: %u/%02u/%02u, %02u:%02u Attributes: %c%c%c%c%c\r\n",\
// 					path, fno.fname,fno.fsize,(fno.fdate >> 9) + 1980, fno.fdate >> 5 & 15, fno.fdate & 31,\
// 	               fno.ftime >> 11, fno.ftime >> 5 & 63,\
// 	               (fno.fattrib & AM_DIR) ? 'D' : '-',\
// 	               (fno.fattrib & AM_RDO) ? 'R' : '-',\
// 	               (fno.fattrib & AM_HID) ? 'H' : '-',\
// 	               (fno.fattrib & AM_SYS) ? 'S' : '-',\
// 	               (fno.fattrib & AM_ARC) ? 'A' : '-');
// 			    i = strlen(path);
// 			    sprintf(&path[i], "/%s", fno.fname);
// 			    rc = scan_dirs(path);  /* Enter the directory */
// 			    if (rc != FR_OK) 
//                   break;
// 			    path[i] = 0;
// 			} else 
// 			{   /* It is a file. */
// 			}
// 		}
// 		f_closedir(&dir);
// 	}
// 	else
// 	{
// 		fmsh_print("directory [%s] not exist!\r\n",path);
// 		return FR_NO_PATH;
// 	}
//     return rc;
// }


// void fdisk_physicaldrive (u32 ulPhyDriveNo)
// {
//    /* 将MANUAL_FORCE_FDISK_EN配置为1,删除已有的分区,变成裸盘,正常流程配置为0,不走该流程*/
// 	DWORD force_fdisk_plist[] = {0, 0, 0, 0}; 
// 	FRESULT rc;	 /* Result code */
	 
// 	fmsh_print("warning!!!,data on disk will lost!\r\n");
// 	rc = f_fdisk(ulPhyDriveNo, force_fdisk_plist, work);  /* Divide physical drive */
// 	if (rc != FR_OK) 
// 	{
// 	  fmsh_print("force f_fdisk err[%d]!\r\n",rc);
// 	  return ;
// 	}
// 	else
// 	{
// 	  fmsh_print("force f_fdisk OK!\r\n");
// 	  return ;
// 	}
// }

// FRESULT remove_file(TCHAR* path)
// {
// 	FRESULT rc; 	/* Result code */

// 	rc = f_unlink(path);
// 	if (rc != FR_OK) 
// 	{
// 	  fmsh_print("remove %s err[%d]!\r\n",path,rc);
// 	}
// 	else
// 	{
// 	  fmsh_print("remove %s OK!\r\n",path);
// 	}
// 	return rc;
// }

// TCHAR path_buf[256]={0};/*假定文件名+目录名最大255个字节,预留一个字符结束符位置*/
// /*遍历删除path指定的目录及其子目录下的所有文件*/
// FRESULT rm_all_files_in_dir(TCHAR* path)
// {
//     FRESULT rc;	 /* Result code */
// 	DIR dir;
// 	static FILINFO fno;
// 	UINT i;
// 	TCHAR* pfname_buf;
// 	u32 ulPathlen;

// 	strcpy(path_buf,path);
	
// 	rc = f_opendir (&dir,path);
// 	if(FR_OK == rc)
// 	{
// 		for (;;) 
// 		{
// 			rc = f_readdir(&dir, &fno); /* Read a directory item */
// 			if (rc != FR_OK || fno.fname[0] == 0) 
// 				break;  /* Break on error or end of dir */
// 			if (fno.fattrib & AM_DIR) 
// 			{   /* It is a directory */
// 			    i = strlen(path_buf);
// 			    sprintf(&path_buf[i], "/%s", fno.fname);
// 			    rc = rm_all_files_in_dir(path_buf);  /* Enter sub directory */
// 			    if (rc != FR_OK) 
//                   break;
// 			    path_buf[i] = 0;
// 			} 
// 			else 
// 			{   /* It is a file,delete the file*/
// 				ulPathlen = strlen(path_buf);
// 				pfname_buf = strcat(path_buf,"/");
// 			    pfname_buf = strcat(pfname_buf,fno.fname);
// 				rc = f_unlink(pfname_buf);
// 				if (rc != FR_OK) 
// 				{
// 				  fmsh_print("remove %s err[%d]!\r\n",pfname_buf,rc);
// 				}
// 				else
// 				{
// 				  fmsh_print("remove %s OK!\r\n",pfname_buf);
//                   path_buf[ulPathlen]= 0x0;
// 				}
// 			}
// 		}
// 		f_closedir(&dir);
// 	}
// 	else
// 	{
// 		fmsh_print("directory [%s] not exist!\r\n",path);
// 		return FR_NO_PATH;
// 	}
//     return rc;
// }

// /*删除path指定的空目录及其子目录下,确保目录下没有文件,否则会删除失败*/
// FRESULT rm_all_empty_dir(TCHAR* path)
// {
//     FRESULT rc;	 /* Result code */
// 	DIR dir;
// 	static FILINFO fno;
// 	UINT i;
// 	TCHAR* pfname_buf = path_buf;
	
// 	strcpy(pfname_buf,path);
	
// 	rc = f_opendir (&dir,path);
// 	if(FR_OK == rc)
// 	{
// 		for (;;) 
// 		{
// 			rc = f_readdir(&dir, &fno); /* Read a directory item */
// 			if (rc == FR_OK)
// 			{
// 				if(fno.fname[0] == 0)
// 				{
// 					f_closedir(&dir);

// 					rc = f_unlink(pfname_buf);
// 					if (rc != FR_OK) 
// 					{
// 					  fmsh_print("remove %s err[%d]!\r\n",pfname_buf,rc);
// 					}
// 					else
// 					{
// 					  fmsh_print("remove %s OK!\r\n",pfname_buf);
// 	                  //path_buf[ulPathlen]= 0x0;
// 					}
// 					return rc;
// 				}
// 				else
// 				{
// 					if (fno.fattrib & AM_DIR) 
// 					{	/* It is a directory */
// 						i = strlen(pfname_buf);
// 						sprintf(&pfname_buf[i], "/%s", fno.fname);
// 						rc = rm_all_empty_dir(pfname_buf);  /* Enter sub directory */
// 						if (rc != FR_OK) 
// 						  break;
// 						pfname_buf[i] = 0;
// 					} 
// 					else 
// 					{	/* It is a file,skip*/
// 					   fmsh_print("directory [%s] not empty!\r\n",fno.fname);
// 					   return FR_DENIED;
					
// 					}
// 				}
// 			}
// 			else
// 			{
// 				break;  /* Break on error or end of dir */
// 			}
// 		}
		
// 		f_closedir(&dir);
// 	}
// 	else
// 	{
// 		fmsh_print("directory [%s] not exist!\r\n",path);
// 		return FR_NO_PATH;
// 	}
//     return rc;
// }


// /*遍历显示path指定的目录所有文件的信息*/
// void show_all_file_info_of_dir(TCHAR* path)
// {
// 	scan_files(path);
// 	return;
// }

// /*遍历显示path指定的partition所有目录及子目录*/
// void show_all_dir_of_partition(TCHAR* path)
// {
// 	scan_dirs(path);
// 	return;
// }


// /*删除path指定的目录、子目录下的所有文件,还有目录和子目录*/
// void remove_all_dirs(TCHAR* path)
// {
// 	if(FR_OK == rm_all_files_in_dir(path))
// 	{
// 		rm_all_empty_dir(path);
// 	}

// 	return;
// }

// /*删除path指定的某个目录或者文件,如果目录非空则会删除失败*/
// void remove_one_dir_or_file(TCHAR* path)
// {
//     FRESULT rc;	 /* Result code */
// 	rc = f_unlink(path);
// 	if (rc != FR_OK) 
// 	{
// 	  fmsh_print("remove %s err[%d]!\r\n",path,rc);
// 	}
// 	else
// 	{
// 	  fmsh_print("remove %s OK!\r\n",path);
// 	}

// 	return;
// }


// /*显示指定逻辑分区的容量信息及剩余容量信息*/
// FRESULT show_partition_usage(u32 ulPhyDriveNo,u32 ulPartitionNum)
// {
// 	FRESULT Res = FR_OK;
// 	TCHAR *Path[] = {"0:","1:","2:","3:","4:","5:","6:","7:"};/*Logical drive number */
// 	u32 i;
// 	DWORD fre_clust, fre_sect, tot_sect;
// 	FATFS *fs;

// 	for(i=0;i < ulPartitionNum;i++)
// 	{	
// 		/* Get total sectors and free sectors */
// 		Res = f_getfree(Path[i+4*ulPhyDriveNo], &fre_clust, &fs);
// 		if (Res)
// 		{
// 		  fmsh_print("f_getfree err[%d]!\r\n",Res);
// 		  continue;
// 		}
// 		tot_sect = (fs->n_fatent - 2) * fs->csize;
// 		fre_sect = fre_clust * fs->csize;
// 		/*如果sector size不是512字节时,使用(tot_sect*fs->ssize)/ 1024, (fre_sect*fs->ssize) / 1024);*/
// 		fmsh_print("partition [%d] :%10lu KiB total space.%10lu KiB available.\r\n", i,tot_sect/2, fre_sect/2);/*sector size = 512 bytes*/
// 	}
// 	return Res;
// }

// /*通过IAR jlink上传主机上的bin文件到sdmmc中指定的目录*/
// u32 upload_bin_to_sdmmc(char* host_file,char* dst_path)
// {
//     FILE *fptr = NULL;
// 	size_t rdsize;
// 	long fileLen;
// 	char *pbuf;
	
//     FIL fileinst;
//     FIL *fp = &fileinst;
// 	FRESULT rc;	 /* Result code */
// 	u32 ulbw;
	
// 	fptr = fopen(host_file,"rb");
// 	if(NULL != fptr)
// 	{
// 	    fseek(fptr,0,SEEK_END);
// 		fileLen = ftell(fptr);
// 		fseek(fptr,0,SEEK_SET);
// 		if(-1 != fileLen)
// 		{
// 			pbuf = malloc(fileLen);
// 			rdsize = fread(pbuf,1,fileLen,fptr);
// 			if(rdsize == fileLen)
// 			{
// 				rc = f_open(fp, dst_path, FA_CREATE_ALWAYS|FA_WRITE);/*追加写入方式打开*/
// 				if (rc) 
// 				{
// 				  fmsh_print("Unable to create file %s: %d\r\n", dst_path, rc);
// 				  fclose(fptr);
// 				  free(pbuf);
// 				  return FMSH_FAILURE;
// 				}	
				
// 				rc= f_write(fp,(void*)pbuf, fileLen, &ulbw);
// 				if(rc || (fileLen != ulbw))
// 				{
// 					fmsh_print("update bin %s failed.\r\n",host_file);
// 					fclose(fptr);
// 				    free(pbuf);
// 					f_close(fp);
// 					return FMSH_FAILURE;
// 				}
// 			}
// 			else
// 			{
// 				fmsh_print("read bin %s failed.\r\n",host_file);
// 				fclose(fptr);
// 				free(pbuf);
// 				return FMSH_FAILURE;
// 			}
// 		}
// 		else
// 		{
// 			fmsh_print("get bin %s length failed.\r\n",host_file);
// 			fclose(fptr);
// 			return FMSH_FAILURE;
// 		}
// 	}
// 	else
// 	{
// 		fmsh_print("open bin %s failed.\r\n",host_file);
// 	    return FMSH_FAILURE;		
// 	}
	
// 	fclose(fptr);
// 	free(pbuf);
// 	f_close(fp);
// 	fmsh_print("update bin %s OK!\r\n",host_file);
// 	return FMSH_SUCCESS;
// }


// u32 sdmmc_wr_rd_test(u32 ulPhyDriveNo,u32 ulPartitionNum)
// {
//     FIL fileinst;
//     FIL *fp = &fileinst;
//     FRESULT rc;	 /* Result code */
// 	//u32 ulret = FMSH_SUCCESS;
//     char *pwbuf = NULL;
//     char *pwbuf_AlignStart;
// 	char *pwbuf_AlignEnd;
//     char *prbuf = NULL;
//     char *prbuf_AlignStart;
//     char *prbuf_AlignEnd;
//     u32 ulbw,ulbr;
//     FSIZE_t fileLen;
// 	TCHAR *Path[] = {"0:","1:","2:","3:","4:","5:","6:","7:"};/*Logical drive number */
//     char filename[32]={0};
//     u32 i,j,k;
//     u64 Pretime = 0;
//     u64 Curtime = 0;
//     u64 timeUsed = 0;
// 	FSIZE_t  fp_offset;

// 	DWORD fre_clust, fre_sect;
// 	FATFS *fs;
// 	TCHAR *subdir[FF_VOLUMES] = {"/subdir0","/subdir1","/subdir2","/subdir3","/subdir4","/subdir5","/subdir6","/subdir7"};/*子目录名称 */
// 	FILINFO finfo;

// 	if(CONFIG_VOLUMES_NUM < ulPartitionNum)
// 	{
// 		return FMSH_FAILURE;  
// 	}

// 	pwbuf = malloc(FWRITE_READ_BUFFER_SIZE_MAX + 2*CONFIG_SYS_CACHELINE_SIZE);
// 	if(NULL == pwbuf)
// 	{
// 		fmsh_print("pwbuf malloc err\r\n");
// 		return FMSH_FAILURE;
// 	}
// 	/*由于使用了dcache,使用的buffer起始地址以cacheline size对齐,大小也需要以cacheline size对齐*/
// 	pwbuf_AlignStart = (char *)(((u32)pwbuf + CONFIG_SYS_CACHELINE_SIZE) & (~((u32)CONFIG_SYS_CACHELINE_SIZE - 1)));
// 	pwbuf_AlignEnd = (char *)(((u32)pwbuf_AlignStart +FWRITE_READ_BUFFER_SIZE_MAX+ CONFIG_SYS_CACHELINE_SIZE) & (~((u32)CONFIG_SYS_CACHELINE_SIZE - 1)));

// 	prbuf = malloc(FWRITE_READ_BUFFER_SIZE_MAX + 2*CONFIG_SYS_CACHELINE_SIZE);
// 	if(NULL == prbuf)
// 	{
// 		fmsh_print("prbuf malloc err\r\n");
// 		free(pwbuf);
// 		return FMSH_FAILURE;
// 	}
// 	/*由于使用了dcache,使用的buffer起始地址以cacheline size对齐,大小也需要以cacheline size对齐*/
// 	prbuf_AlignStart = (char *)(((u32)prbuf + CONFIG_SYS_CACHELINE_SIZE) & (~((u32)CONFIG_SYS_CACHELINE_SIZE - 1)));
// 	prbuf_AlignEnd = (char *)(((u32)prbuf_AlignStart +FWRITE_READ_BUFFER_SIZE_MAX+ CONFIG_SYS_CACHELINE_SIZE) & (~((u32)CONFIG_SYS_CACHELINE_SIZE - 1)));

// 	fmsh_print("sdmmc%d FAT32 baremetal test start.....\r\n",ulPhyDriveNo);
// 	for(i=0;i < 3;i++)/*连续测试多次,测试追加写入功能*/
// 	{	 
// 		fmsh_print("%d round test in progress.....\r\n",i+1);
// 		for(k = 0;k < ulPartitionNum;k++)/*多个分区*/
// 		{
// 		  /*假定sdmmc0和sdmmc1均有4个分区*/
// 		  f_chdrive(Path[k+4*ulPhyDriveNo]);/*Change Current Drive*/
// 		  strcpy(m_dir_buffer,subdir[k+4*ulPhyDriveNo]);
		  
// 		  if(FR_OK != f_stat(m_dir_buffer, &finfo))
// 		  {
// 			  rc = f_mkdir(m_dir_buffer);
// 			  if (rc)
// 			  {
// 				  free(pwbuf);
// 				  free(prbuf);
// 				  return FMSH_FAILURE;
// 			  }
// 		  }
// 		  //scan_files(subdir[k]);

// 		  if(FR_OK != f_chdir(m_dir_buffer))
// 		  {
// 			  free(pwbuf);
// 			  free(prbuf);
// 			  return FMSH_FAILURE;
// 		  }
		  
// 		  for(j=0;j < 100;j++)/*生成100个文件*/
// 		  {
// 			  /* Get volume information and free clusters of drive */
// 			  rc = f_getfree(Path[k+4*ulPhyDriveNo], &fre_clust, &fs);
// 			  if (rc)
// 			  {
// 				  free(pwbuf);
// 				  free(prbuf);
// 				  return FMSH_FAILURE;
// 			  }
			  
// 			  /* Get free sectors */
// 			  fre_sect = fre_clust * fs->csize;
// 			  /*如果sector size不是512字节时,使用fs->ssize*/
// 			  if(fre_sect < (FWRITE_READ_BUFFER_SIZE_MAX/512))/*sector size = 512 bytes */
// 			  {
// 				fmsh_print("partition[%d]:left space not enough to write:%10lu KiB available.\r\n",k,fre_sect/2);
// 				 break;
// 			  } 		  

// 			sprintf(filename, "test%d.bin",j);
// 			rc = f_open(fp, filename, FA_OPEN_APPEND|FA_READ|FA_WRITE);/*追加写入方式打开*/
// 			if (rc) 
// 			{
// 			  fmsh_print("Unable to open file %s: %d\r\n", filename, rc);
// 			  free(pwbuf);
// 			  free(prbuf);
// 			  return FMSH_FAILURE;
// 			}	
			
// 			memset(pwbuf_AlignStart,0x5a+j+i+k,FWRITE_READ_BUFFER_SIZE_MAX);
// 	#if PSOC_CACHE_ENABLE
// 			flush_dcache_range((u32)pwbuf_AlignStart,(u32)pwbuf_AlignEnd);
// 	#endif
			
// 			Pretime = get_current_time();		  
// 			rc= f_write(fp,(void*)pwbuf_AlignStart, FWRITE_READ_BUFFER_SIZE_MAX, &ulbw);
// 			if(rc || (FWRITE_READ_BUFFER_SIZE_MAX != ulbw))
// 			{
// 				fmsh_print("Write File To SD EMMC Card Failed[%d].\r\n",rc);
// 				f_close(fp);
// 				free(pwbuf);
// 				free(prbuf);
// 				return FMSH_FAILURE;
// 			}			 
// 			//f_sync(fp);/*flush cached data into file*/
				
// 			fileLen = f_size(fp);

// 			Curtime = get_current_time();
// 			timeUsed = (Curtime - Pretime)/GTC_CLK_FREQ/1000;
// 			fmsh_print("FAT32 partition[%d]: write file[%d]--size[0x%x],Use time: %lldms,speed:%fKiB/s\r\n",k,j,fileLen,timeUsed,(double)(FWRITE_READ_BUFFER_SIZE_MAX)/timeUsed/1.024);

// 			fp_offset = f_tell(fp);
// 			f_close(fp);/*关闭当前文件*/
			
// 			rc = f_open(fp, filename, FA_READ);/*只读方式打开*/
// 			if (rc) 
// 			{
// 			  fmsh_print("Unable to open file %s: %d\r\n", filename, rc);
// 			  free(pwbuf);
// 			  free(prbuf);
// 			  return FMSH_FAILURE;
// 			} 

// 			/*回读校验*/
// 			fp_offset = fp_offset - FWRITE_READ_BUFFER_SIZE_MAX;
// 			rc = f_lseek(fp,fp_offset);/*将文件指针设置到上次写入的起始位置,进行回读校验*/
// 			if(rc)
// 			{
// 			  fmsh_print("f_lseek err Failed[%d],fp_offset:%d\r\n",rc,fp_offset);
// 				f_close(fp);
// 				free(pwbuf);
// 				free(prbuf);
// 				return FMSH_FAILURE;
// 			}		
// 			rc = f_read(fp,prbuf_AlignStart,ulbw,&ulbr);
// 			if(rc || (ulbr != ulbw))
// 			{
// 				fmsh_print("read FAT32 partition[%d] file[%d] err\r\n",k,j);
// 			}
// 	#if PSOC_CACHE_ENABLE
// 			flush_dcache_range((u32)prbuf_AlignStart,(u32)prbuf_AlignEnd);
//     #endif
// 			if(0 != memcmp(prbuf_AlignStart,pwbuf_AlignStart,FWRITE_READ_BUFFER_SIZE_MAX))
// 			{
// 				fmsh_print("FAT32 partition[%d] file[%d] readback check err\r\n",k,j);
// 				free(pwbuf);
// 				free(prbuf);
// 				f_close(fp);
// 				return FMSH_FAILURE;				
// 			}
// 			else
// 			{
// 				fmsh_print("FAT32 partition[%d] file[%d]--size[0x%x] readback check OK!\r\n",k,j,fileLen);
// 			}
			
// 			rc= f_close(fp);/*关闭当前文件*/
// 			if(rc)
// 			{
// 				free(pwbuf);
// 				free(prbuf);
// 				return FMSH_FAILURE;
// 			}
// 		  }
// 		}
// 		fmsh_print("%d round test finish.....\r\n",i+1);
// 	}	
// 	fmsh_print("sdmmc%d FAT32 baremetal demo works good!!!\r\n",ulPhyDriveNo);
// 	free(pwbuf);
// 	free(prbuf);
	
// 	return FMSH_SUCCESS;

// }

#ifdef XPAR_UARTNS550_0_BASEADDR
/*****************************************************************************/
/*
*
* Uart16550 setup routine, need to set baudrate to 9600 and data bits to 8
*
* @param	None
*
* @return	None
*
* @note		None.
*
******************************************************************************/
static void Uart550_Setup(void)
{

	XUartNs550_SetBaud(XPAR_UARTNS550_0_BASEADDR,
			XPAR_XUARTNS550_CLOCK_HZ, 9600);

	XUartNs550_SetLineControlReg(XPAR_UARTNS550_0_BASEADDR,
			XUN_LCR_8_DATA_BITS);
}
#endif

/*****************************************************************************/
/*
*
* This function checks data buffer after the DMA transfer is finished.
*
* We use the static tx/rx buffers.
*
* @param	Length is the length to check
* @param	StartValue is the starting value of the first byte
*
* @return
*		- XST_SUCCESS if validation is successful
*		- XST_FAILURE if validation is failure.
*
* @note		None.
*
******************************************************************************/
// static int CheckData(int Length, u8 StartValue)
// {
// 	u8 *RxPacket;
// 	int Index = 0;
// 	u8 Value;

// 	RxPacket = (u8 *) RX_BUFFER_BASE;
// 	Value = StartValue;

// 	/* Invalidate the DestBuffer before receiving the data, in case the
// 	 * Data Cache is enabled
// 	 */
// 	invalidate_dcache_range((UINTPTR)RxPacket, (UINTPTR)RxPacket + Length);
	
// 	for(Index = 0; Index < Length; Index++) {
// 		// xil_printf("Data%d is: %x/%x\r\n",Index, RxPacket[Index], Value);
// 		if (RxPacket[Index] != Value) {
// 			xil_printf("Data error %d: %x/%x\r\n",
// 			    Index, RxPacket[Index], Value);

// 			return XST_FAILURE;
// 		}
// 		Value = (Value + 1) & 0xFF;
// 	}

// 	return XST_SUCCESS;
// }

/*****************************************************************************/
/*
*
* This is the DMA TX Interrupt handler function.
*
* It gets the interrupt status from the hardware, acknowledges it, and if any
* error happens, it resets the hardware. Otherwise, if a completion interrupt
* is present, then sets the TxDone.flag
*
* @param	Callback is a pointer to TX channel of the DMA engine.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void TxIntrHandler(void *Callback)
{

	u32 IrqStatus;
	int TimeOut;
	XAxiDma *AxiDmaInst = (XAxiDma *)Callback;

	/* Read pending interrupts */
	IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DMA_TO_DEVICE);

	/* Acknowledge pending interrupts */

	XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DMA_TO_DEVICE);

	/*
	 * If no interrupt is asserted, we do not do anything
	 */
	if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) {

		return;
	}

	/*
	 * If error interrupt is asserted, raise error flag, reset the
	 * hardware to recover from the error, and return with no further
	 * processing.
	 */
	if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) {

		Error = 1;

		/*
		 * Reset should never fail for transmit channel
		 */
		XAxiDma_Reset(AxiDmaInst);

		TimeOut = RESET_TIMEOUT_COUNTER;

		while (TimeOut) {
			if (XAxiDma_ResetIsDone(AxiDmaInst)) {
				break;
			}

			TimeOut -= 1;
		}

		return;
	}

	/*
	 * If Completion interrupt is asserted, then set the TxDone flag
	 */
	if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) {

		TxDone = 1;
	}
	// xil_printf(" Tx intr:txDone is %d\r\n",TxDone);
}

/*****************************************************************************/
/*
*
* This is the DMA RX interrupt handler function
*
* It gets the interrupt status from the hardware, acknowledges it, and if any
* error happens, it resets the hardware. Otherwise, if a completion interrupt
* is present, then it sets the RxDone flag.
*
* @param	Callback is a pointer to RX channel of the DMA engine.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void RxIntrHandler(void *Callback)
{
	u32 IrqStatus;
	int TimeOut;
	XAxiDma *AxiDmaInst = (XAxiDma *)Callback;

	/* Read pending interrupts */
	IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DEVICE_TO_DMA);

	/* Acknowledge pending interrupts */
	XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DEVICE_TO_DMA);

	/*
	 * If no interrupt is asserted, we do not do anything
	 */
	if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) {
		return;
	}

	/*
	 * If error interrupt is asserted, raise error flag, reset the
	 * hardware to recover from the error, and return with no further
	 * processing.
	 */
	if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) {

		Error = 1;

		/* Reset could fail and hang
		 * NEED a way to handle this or do not call it??
		 */
		XAxiDma_Reset(AxiDmaInst);

		TimeOut = RESET_TIMEOUT_COUNTER;

		while (TimeOut) {
			if(XAxiDma_ResetIsDone(AxiDmaInst)) {
				break;
			}

			TimeOut -= 1;
		}

		return;
	}

	/*
	 * If completion interrupt is asserted, then set RxDone flag
	 */
	if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) {

		RxDone = 1;
	}
	// xil_printf(" rx intr:RxDone is %d\r\n",RxDone);
}

/*****************************************************************************/
/*
*
* This function setups the interrupt system so interrupts can occur for the
* DMA, it assumes INTC component exists in the hardware system.
*
* @param	IntcInstancePtr is a pointer to the instance of the INTC.
* @param	AxiDmaPtr is a pointer to the instance of the DMA engine
* @param	TxIntrId is the TX channel Interrupt ID.
* @param	RxIntrId is the RX channel Interrupt ID.
*
* @return
*		- XST_SUCCESS if successful,
*		- XST_FAILURE.if not succesful
*
* @note		None.
*
******************************************************************************/
static int SetupIntrSystem(INTC * IntcInstancePtr,
			   XAxiDma * AxiDmaPtr, u16 TxIntrId, u16 RxIntrId)
{
	u32 Status;
	
	Status =  FGicPs_SetupInterruptSystem(IntcInstancePtr);
    if(Status!=GIC_SUCCESS)
	{
		return GIC_FAILURE ;
	}

	/* The trigger type is not set in the peripheral test. */
	FGicPs_SetPriorityTriggerType(IntcInstancePtr, TxIntrId, 0xA0, 0x3);
	FGicPs_SetPriorityTriggerType(IntcInstancePtr, RxIntrId, 0xA0, 0x3);
	
	
	Status = FGicPs_Connect(IntcInstancePtr,TxIntrId,
	      (FMSH_InterruptHandler)TxIntrHandler, AxiDmaPtr);
	if (Status != GIC_SUCCESS) {
		return GIC_FAILURE;
	}      

	Status = FGicPs_Connect(IntcInstancePtr,RxIntrId,
	      (FMSH_InterruptHandler)RxIntrHandler, AxiDmaPtr);
	if (Status != GIC_SUCCESS) {
		return GIC_FAILURE;
	}      

	FMSH_ExceptionRegisterHandler(FMSH_EXCEPTION_ID_IRQ_INT,
          (FMSH_ExceptionHandler)FGicPs_InterruptHandler_IRQ,
                IntcInstancePtr);  

	FGicPs_Enable(IntcInstancePtr, TxIntrId);
	FGicPs_Enable(IntcInstancePtr, RxIntrId);

	return XST_SUCCESS;
}

/*****************************************************************************/
/**
*
* This function disables the interrupts for DMA engine.
*
* @param	IntcInstancePtr is the pointer to the INTC component instance
* @param	TxIntrId is interrupt ID associated w/ DMA TX channel
* @param	RxIntrId is interrupt ID associated w/ DMA RX channel
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void DisableIntrSystem(INTC * IntcInstancePtr,
					u16 TxIntrId, u16 RxIntrId)
{
	FGicPs_Disconnect(IntcInstancePtr, TxIntrId);
	FGicPs_Disconnect(IntcInstancePtr, RxIntrId);
}

/*****************************************************************************/
/**
*
* This function Transmission for dma
*
* @param	AxiDmaIns is the pointer to the AXIDMA component instance
* @param	wBuffer is Send buffer
* @param	length is send buffer length
*
* @return	成功返回XST_SUCCESS.失败返回XST_FAILURE
*
* @note		None.
*
******************************************************************************/
int pixel_dma_send(XAxiDma* AxiDmaIns,u16 *wBuffer, unsigned int length)
{
	int Status;
	u16 *TxBufferPtr;
	if((AxiDmaIns == NULL)||(wBuffer == NULL))
	{
		xil_printf("send Pointer err\r\n");
		return XST_FAILURE;
	}

	if (AxiDmaIns == &AxiDma)
		TxBufferPtr = (u16 *)TX_BUFFER_BASE ;
	else
	{
		xil_printf("para err\r\n");
		return XST_FAILURE;
	}

	memset(TxBufferPtr,0,length);
	memcpy(TxBufferPtr,wBuffer,length);
	// for(int Index = 0; Index < length; Index ++) {
	// 	TxBufferPtr[Index] = wBuffer[Index];
	// }

	flush_dcache_range((UINTPTR)TxBufferPtr, (UINTPTR)TxBufferPtr+MAX_PKT_LEN);

	Status = XAxiDma_SimpleTransfer(AxiDmaIns,(UINTPTR) TxBufferPtr,
			length, XAXIDMA_DMA_TO_DEVICE);
//	xil_printf("status is %d",Status);
	if (Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}
	// xil_printf("\r\npixel_dma_send txdone is %d\r\n",TxDone);
	// TxDone = 0;
    return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function Transmission for dma
*
* @param	AxiDmaIns is the pointer to the AXIDMA component instance
* @param	rBuffer is recv buffer
*
* @return	length is rev buffer length
*
* @note		None.
*
******************************************************************************/
unsigned int pixel_dma_recv(XAxiDma* AxiDmaIns,u16 *rBuffer)
{
	int Status;
	unsigned int Length = 0 ;
	u16 *RxBufferPtr;
	
	while ( !RxDone && !Error) {
				/* NOP */
		}
	if (Error) 
	{
		/* Compiler complain that it may not be support!! */
		if(!RxDone)
			xil_printf("Failed test receive not done\r\n");
		else
			xil_printf("Failed test receive done\r\n");

	}
	Length = XAxiDma_ReadReg(AxiDmaIns->RegBase,0x58);
	if((AxiDmaIns == NULL)||(rBuffer == NULL))
	{
		xil_printf("recv Pointer err\r\n");
		return XST_FAILURE;
	}
	
	if (AxiDmaIns == &AxiDma)
		RxBufferPtr = (u16 *)RX_BUFFER_BASE ;
	else
	{
		xil_printf("pixel_dma_recv input para err\r\n");
		return XST_FAILURE;
	}

	
	// for(int Index = 0; Index < 32; Index++) 
	// {
	// 	xil_printf("Data : %x\r\n", RxBufferPtr[Index]);
	// }
	// Length =MAX_PKT_LEN;
	invalidate_dcache_range((UINTPTR)RxBufferPtr, (UINTPTR)RxBufferPtr + MAX_PKT_LEN);
	Status = XAxiDma_SimpleTransfer(AxiDmaIns,(UINTPTR) RxBufferPtr,
				MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);

	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	
	memset(rBuffer,0,Length);
	memcpy(rBuffer,RxBufferPtr,Length);
	// xil_printf("pixel_dma_recv:");
	// for(int Index = 0; Index < 32; Index++) 
	// {
	// 	xil_printf("0x%x ", rBuffer[Index]);
	// }
	
	// invalidate_dcache_range((UINTPTR)RxBufferPtr,MAX_PKT_LEN);
		/* Invalidate the DestBuffer before receiving the data, in case the
	 * Data Cache is enabled
	 */

	// for(int i = 0; i < Length; i++)
	// 	{
	// 		rBuffer[i] = RxBufferPtr[i];
	// 	}
	// memset(RxBufferPtr,0,Length);
	// memcpy(RxBufferPtr,rBuffer,Length);
	// flush_dcache_range((UINTPTR)RxBufferPtr, (UINTPTR)RxBufferPtr + MAX_PKT_LEN);
	// xil_printf("\r\npixel_dma_recv rxdone is %d\r\n",RxDone);
	RxDone = 0;

    return Length;
}
/*****************************************************************************/
/**
*
* This function for dma init
*
* @param	None.
*
* @return	成功返回XST_SUCCESS失败返回XST_FAILURE.
*
* @note		None.
*
******************************************************************************/
int pixel_dma_init(void)
{
	// xil_printf("\r\n--- 0Entering dma init() --- \r\n");
    int 			Status;
	// u16 			*TxBufferPtr;
	u16 			*RxBufferPtr;
	XAxiDma_Config 	*Config;
	// TxBufferPtr = (u16 *)TX_BUFFER_BASE ;
	RxBufferPtr = (u16 *)RX_BUFFER_BASE;
	// u8 *RxBufferPtr= (u8 *)RX_BUFFER_BASE;
	memset(RxBufferPtr,0,MAX_PKT_LEN);
	// xil_printf("\r\n--- Entering dma init() --- \r\n");
	Config = XAxiDma_LookupConfig(DMA_DEV_ID);
	if (!Config) {
		xil_printf("No config found for %d\r\n", DMA_DEV_ID);

		return XST_FAILURE;
	}
	// xil_printf("success config found for %d\r\n", DMA_DEV_ID);
	/* Initialize DMA engine */
	Status = XAxiDma_CfgInitialize(&AxiDma, Config);

	if (Status != XST_SUCCESS) {
		xil_printf("Initialization failed %d\r\n", Status);
		return XST_FAILURE;
	}
	// xil_printf("XAxiDma Initialization succeed %d\r\n", Status);
	if(XAxiDma_HasSg(&AxiDma)){
		xil_printf("Device configured as SG mode \r\n");
		return XST_FAILURE;
	}
	// xil_printf("Device configured as simple mode\r\n");
	/* Set up Interrupt system  */
	Status = SetupIntrSystem(&IntcInstance, &AxiDma, TX_INTR_ID, RX_INTR_ID);
	if (Status != XST_SUCCESS) {
		xil_printf("Failed intr setup\r\n");
		return XST_FAILURE;
	}
	// xil_printf("success intr setup\r\n");

	/* Disable all interrupts before setup */

	XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
						XAXIDMA_DMA_TO_DEVICE);

	XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
				XAXIDMA_DEVICE_TO_DMA);

	/* Enable all interrupts */
	XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
							XAXIDMA_DMA_TO_DEVICE);


	XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
							XAXIDMA_DEVICE_TO_DMA);

	/* Initialize flags before start transfer test  */
	TxDone = 0;
	RxDone = 0;
	Error = 0;

	Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) RxBufferPtr,
				MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/* Flush the SrcBuffer before the DMA transfer, in case the Data Cache
	 * is enabled
	 */
	// flush_dcache_range((UINTPTR)TxBufferPtr, (UINTPTR)TxBufferPtr + MAX_PKT_LEN);
	// invalidate_dcache_range((UINTPTR)RxBufferPtr, (UINTPTR)RxBufferPtr + MAX_PKT_LEN);
	// unsigned int Length = XAxiDma_ReadReg(AxiDma.RegBase,0x58);
	// xil_printf("init Length = %x\n\r", Length);
	// xil_printf("NOinit:read from addr: \r\n");
	// u16 			wBuffer[640] 			= {0};
	// for(int i=0;i<20;i++)
	// {	
		 
	// 	for(int j=0;j<32;j++)
	// 	{
	// 		wBuffer[j+i*32] = FMSH_ReadData16(RX_BUFFER_BASE,(j+i*32)*2);
	// 		xil_printf("0x%x ",wBuffer[j+i*32]);
	// 	}
	// 	xil_printf("\r\n");
	// }
	// xil_printf("pixel_dma_init successful\r\n");
    return XST_SUCCESS;
}


int main()
{
	u32 		ulret 					= FMSH_SUCCESS;
    u64 		Pretime 				= 0;
    u64 		Curtime 				= 0;
    u64 		timeUsed 				= 0;
	DWORD 		plist1[] 				= {100, 0, 0, 0}; /* 25% for 4 partitions each */
	FIL 		fileinst;
    FIL 		*fp 					= &fileinst;
    FRESULT 	rc;	 							/* Result code */
	// FSIZE_t 	fileLen;
	char 		filename[32]={0};
    u16 		*pwbuf 					= NULL;
    u16 		*pwbuf_AlignStart;
	u16 		*pwbuf_AlignEnd;
	u32 		ulbw;//,ulbr;
	u16 		*rBuffer;
	u16 		*rbuf_AlignStart;
	int			status;
	int 		Length = 0;
	// int 		i = 0;
	int 		pixel_cnt = 0;
    global_timer_enable();
	/* it need to test for cache operation!
	 * Our application use the a7_ahbram which is 128KB ocm.
	 * include text, bss, rodat, vector, mmu table
	 * please refer to the a7_ahbram.icf in the hello.out/output directory.
	 */
	invalidate_icache_all();
	icache_enable();

	flush_dcache_all();
	dcache_enable();

    init_platform();

	FMSH_WriteReg(FPS_SLCR_BASEADDR, 0x008, 0xDF0D767B);
	FMSH_WriteReg(FPS_SLCR_BASEADDR, 0x838, 0xf);        
	FMSH_WriteReg(FPS_SLCR_BASEADDR, 0x004, 0xDF0D767B);

	delay_ms(50);
	FMSH_WriteReg(0xe0029000, 0x490, 0x1);    //re-enable hp0

	xil_printf("\r\n--- Entering main() --- \r\n");
	rBuffer = malloc(FWRITE_READ_BUFFER_SIZE_MAX + 2*CONFIG_SYS_CACHELINE_SIZE);
	if(NULL == rBuffer)
	{
		fmsh_print("rBuffer malloc err\r\n");
		return FMSH_FAILURE;
	}
	rbuf_AlignStart = (u16 *)(((u32)rBuffer + CONFIG_SYS_CACHELINE_SIZE) & (~((u32)CONFIG_SYS_CACHELINE_SIZE - 1)));
	// rbuf_AlignEnd = (u16 *)(((u32)rbuf_AlignStart +FWRITE_READ_BUFFER_SIZE_MAX+ CONFIG_SYS_CACHELINE_SIZE) & (~((u32)CONFIG_SYS_CACHELINE_SIZE - 1)));
	pwbuf = malloc(FWRITE_READ_BUFFER_SIZE_MAX + 2*CONFIG_SYS_CACHELINE_SIZE);
	if(NULL == pwbuf)
	{
		fmsh_print("pwbuf malloc err\r\n");
		return FMSH_FAILURE;
	}
	/*由于使用了dcache,使用的buffer起始地址以cacheline size对齐,大小也需要以cacheline size对齐*/
	pwbuf_AlignStart = (u16 *)(((u32)pwbuf + CONFIG_SYS_CACHELINE_SIZE) & (~((u32)CONFIG_SYS_CACHELINE_SIZE - 1)));
	pwbuf_AlignEnd = (u16 *)(((u32)pwbuf_AlignStart +FWRITE_READ_BUFFER_SIZE_MAX+ CONFIG_SYS_CACHELINE_SIZE) & (~((u32)CONFIG_SYS_CACHELINE_SIZE - 1)));

	// /* 和PL做交互,通知PS状态ok */
	// xil_printf("Start notifying PL\r\n");
	FGpioPs_T 			* gpios = &g_gpios;
	FGpioPs_Config 		*gpio_cfgPpr;
	status = pixel_dma_init();
	if( status!= XST_SUCCESS)
	{
		xil_printf("pixel_dma_init failed\r\n");
	}
	else
	{
		xil_printf("pixel_dma_init successful\r\n");
	}
	
  /*******************************************************************************************/
#if MANUAL_FORCE_FDISK_EN

#ifdef SDMMCPS_0_DEVICE_ID
    /* 将MANUAL_FORCE_FDISK_EN配置为1,删除已有的分区,变成裸盘,正常流程配置为0,不走该流程*/
	fdisk_physicaldrive(SDMMCPS_0_DEVICE_ID);
#endif

#ifdef SDMMCPS_1_DEVICE_ID
	/* 将MANUAL_FORCE_FDISK_EN配置为1,删除已有的分区,变成裸盘,正常流程配置为0,不走该流程*/
	fdisk_physicaldrive(SDMMCPS_1_DEVICE_ID);
#endif
    return FMSH_SUCCESS;
#endif

/*SDMMCPS_0_DEVICE_ID,在BD中使能了sdmmc0,就会在fmsh_ps_parameters.h定义SDMMCPS_0_DEVICE_ID为0*/
#ifdef SDMMCPS_0_DEVICE_ID
    Pretime = get_current_time();
    ulret = fmsh_SdEmmcInitPartFAT32(SDMMCPS_0_DEVICE_ID,1,plist1);
    if (ulret) 
    {
      fmsh_print("fmsh_SdEmmcInitPartFAT32 sdmmc0 err\r\n");
      return FMSH_FAILURE;
    }
	fmsh_print("fmsh_SdEmmcInitPartFAT32 sdmmc0 success\r\n");
	Curtime = get_current_time();
	timeUsed = (Curtime - Pretime)/GTC_CLK_FREQ/1000;
	fmsh_print("sdmmc0 format FAT32 time Used:%lldms\r\n",timeUsed);
#endif

/*SDMMCPS_1_DEVICE_ID,在BD中使能了sdmmc1,就会在fmsh_ps_parameters.h定义SDMMCPS_1_DEVICE_ID为1*/
#ifdef SDMMCPS_1_DEVICE_ID
    Pretime = get_current_time();
    ulret = fmsh_SdEmmcInitPartFAT32(SDMMCPS_1_DEVICE_ID,4,plist2);
    if (ulret) 
    {
      fmsh_print("fmsh_SdEmmcInitPartFAT32 sdmmc0 err\r\n");
      return FMSH_FAILURE;
    }
	
	Curtime = get_current_time();
	timeUsed = (Curtime - Pretime)/GTC_CLK_FREQ/1000;
	fmsh_print("sdmmc0 format FAT32 time Used:%lldms\r\n",timeUsed);
#endif


#ifdef SDMMCPS_1_DEVICE_ID
	if(FMSH_SUCCESS != sdmmc_wr_rd_test(SDMMCPS_1_DEVICE_ID,4))
	{
		fmsh_print("sdmmc%d wr_rd_test err\r\n",SDMMCPS_1_DEVICE_ID);
	}
#endif

	//upload_bin_to_sdmmc("D:\\BOOT.bin","0:/BOOT.bin");
	// fmsh_print("SD test start.....\r\n");
	/* 和pl交互 */
	gpio_cfgPpr = FGpioPs_LookupConfig(FPAR_GPIOPS_2_DEVICE_ID);
	// xil_printf("FGpioPs_LookupConfig successful\r\n");
	FGpioPs_init(gpios,gpio_cfgPpr);
	// xil_printf("FGpioPs_init successful\r\n");
	FGpioPs_setDirection(gpios,0xf);
	// xil_printf("FGpioPs_setDirection successful\r\n");
	FGpioPs_writeData(gpios,0);
	delay_ms(1000);
	FGpioPs_writeData(gpios,FMSH_BIT0);
	delay_ms(1000);
	FGpioPs_writeData(gpios,0);
	xil_printf("start test\r\n");
	Pretime = get_current_time();
	while(1)
	{
		
		if (RxDone)
		{
			Length = pixel_dma_recv(&AxiDma,rbuf_AlignStart);
			if (Error) 
			{
				fmsh_print("An error occurred during reception");
				goto Exit;
			}
			FGpioPs_writeData(gpios,FMSH_BIT0);
			pixel_cnt++;
                        fmsh_print("pixel cnt is %d",pixel_cnt);
			memset(pwbuf_AlignStart,0x5A,FWRITE_READ_BUFFER_SIZE_MAX);
			memcpy(pwbuf_AlignStart,rbuf_AlignStart,Length);
	// 		xil_printf("\r\n");
			// xil_printf("NO%d:length DMA is 0x%x,first data is 0x%x 0x%x\r\n",pixel_cnt,Length,rbuf_AlignStart[0],pwbuf_AlignStart[0]);
			FGpioPs_writeData(gpios,0);
#ifdef SD_SAVE
			sprintf(filename, "TestFrame%d.bin",pixel_cnt);
			rc = f_open(fp, filename, FA_OPEN_APPEND|FA_READ|FA_WRITE);/*追加写入方式打开*/
			if (rc) 
			{
				fmsh_print("Unable to open file %s: %d\r\n", filename, rc);
				free(pwbuf);
				//free(prbuf);
				return FMSH_FAILURE;
			}
			// fmsh_print("Success to open file %s\r\n", filename);
			// memset(pwbuf_AlignStart,0x5a,FWRITE_READ_BUFFER_SIZE_MAX);
			// rBuffer[1280] 			= {0};
			// memcpy(pwbuf_AlignStart,rBuffer,FWRITE_READ_BUFFER_SIZE_MAX);
			#if PSOC_CACHE_ENABLE
					flush_dcache_range((u32)pwbuf_AlignStart,(u32)pwbuf_AlignEnd);
			#endif
			// memcpy(pwbuf_AlignStart,rBuffer,FWRITE_READ_BUFFER_SIZE_MAX);
			// Pretime = get_current_time();		  
			rc= f_write(fp,(void*)pwbuf_AlignStart, FWRITE_READ_BUFFER_SIZE_MAX, &ulbw);
			if(rc || (FWRITE_READ_BUFFER_SIZE_MAX != ulbw))
			{
				fmsh_print("Write File To SD EMMC Card Failed[%d].\r\n",rc);
				f_close(fp);
				free(pwbuf);
				// free(prbuf);
				return FMSH_FAILURE;
			}		
			// fileLen = f_size(fp);	
			// fmsh_print("SD: write size[0x%x],Use time: %lldms,speed:%fKiB/s\r\n",fileLen,timeUsed,(double)(FWRITE_READ_BUFFER_SIZE_MAX)/timeUsed/1.024); 
			rc= f_close(fp);/*关闭当前文件*/
			if(rc)
			{
				fmsh_print("Unable to close file\r\n");
				free(pwbuf);
				// free(prbuf);
				return FMSH_FAILURE;
			}
#endif
			if((pixel_cnt%100) == 0)
			{
				Curtime = get_current_time();
				timeUsed = (Curtime - Pretime)/GTC_CLK_FREQ/1000;
				fmsh_print("Succeed save %d frame,time used %dms\r\n",pixel_cnt,timeUsed);
			}

			// free(pwbuf);
			// free(prbuf);
		}
	}
Exit:
	DisableIntrSystem(&IntcInstance, TX_INTR_ID, RX_INTR_ID);
	free(pwbuf);
	free(rBuffer);
    return 0;
}
相关推荐
阳排5 天前
ZYNQ-7020嵌入式系统学习笔记(1)——使用ARM核配置UART发送Helloworld
笔记·学习·fpga开发·zynq
hi9410 天前
PYNQ 框架 - 中断(INTR)驱动
嵌入式硬件·fpga开发·zynq·pynq
li星野17 天前
PL端:LED闪烁
fpga开发·zynq
会点灯的大力水手25 天前
3-ZYNQ 折腾记录 -PS_PL AXI Interfaces
xilinx·zynq
冷凝雨1 个月前
【复旦微FM33 MCU 外设开发指南】外设篇1——硬件除法器
arm·1024程序员节·复旦微·fm33·fm33lc0
XiaoChaoZhiNeng1 个月前
基于Zynq SDIO WiFi移植三(支持2.4/5G)
5g·fpga·zynq·ap·sdio
XiaoChaoZhiNeng2 个月前
基于Zynq SDIO WiFi移植一(支持2.4/5G)
5g·fpga·zynq
辣个蓝人QEX2 个月前
【FPGA开发】Modelsim如何给信号分组
fpga开发·modelsim·zynq
li星野2 个月前
ZYNQ:点亮LED灯
fpga开发·zynq·7010
XiaoChaoZhiNeng2 个月前
基于Zynq SDIO WiFi移植二(支持2.4/5G)
5g·fpga·zynq·sdio