复旦微用AXIDMA接收原始图像

参考SD卡移植博客,,移植SD卡相应代码
AXIDMA部分Demo下的bsp包整个pl搬到相应位置,添加相应文件

在这里插入图片描述


#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;
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/242482.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法中的最优化方法课程复习

算法中的最优化方法课程复习 单模函数、拟凸函数、凸函数证明证明一个线性函数与一个凸函数的和也是凸的 梯度线性规划标准形式以及如何标准化标准形式常见标准化方法线性化技巧 单纯形法二次规划无约束优化Nelder-Mead线搜索FR共轭梯度法例题 优化算法的选择、停止准则算法选择…

echarts 没画出来图形,dom报错宽高未识别

当echarts 刷新时&#xff0c;画不出图形 控制台 报错 应当是你画布&#xff0c;父级使用了flex布局&#xff0c;找成了画布的宽高失效 解决方法&#xff1a;画布class上加上一句 flex-shrink: 0;

算法笔记—链表、队列和栈

链表、队列和栈 1. 链表1.1 单链表反转1.2 双链表反转1.3 合并两个有序链表1.4 链表相加1.5 划分链表 2. 队列和栈2.1 循环队列2.2 栈实现队列2.3 队列实现栈2.4 最小栈2.2 双端队列 1. 链表 1.1 单链表反转 力扣 反转链表 // 反转单链表public ListNode reverseList(ListNod…

三、Shell 环境

一、Linux 系统分类 在 Linux 中&#xff0c;常见的 Shell 有以下几种&#xff1a; Bourne Shell&#xff08;sh&#xff09;&#xff1a;最早的 Shell&#xff0c;由 Stephen Bourne 开发。它是大多数其他 Shell 的基础。Bourne Again Shell&#xff08;bash&#xff09;&am…

螺旋矩阵算法(leetcode第59题)

题目描述&#xff1a; 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。示例 1&#xff1a;输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]] 示例 2&#xff1a;输入&#…

SQL Server 远程连接服务器数据库

本文解决sql server的远程连接问题。需要开启防火墙&#xff0c;开启端口&#xff0c;并处理权限不足的报错: 【use 某数据库】The server principal "[server]" is not able to access the database "[database]" under the current security context. 【…

[C/C++]——内存管理

学习C/C的内存管理 前言&#xff1a;一、C/C的内存分布二、C语言中动态内存管理方式三、C中动态内存管理方式3.1、new/delete操作符3.1.2、new/delete操作内置类型3.1.3、new/delete操作自定义类型 3.2、认识operator new和operator delete函数3.3、了解new和delete的实现原理3…

json.loads和eval 速度对比

json.loads和eval 速度对比 代码1结果图代码2参考地址 代码1 import json import time import pandas as pddata_sets pd.read_pickle("val_token_id.pandas_pickle") data_sets[str(i) for i in data_sets] starttime.time() [json.loads(i) for i in data_sets] …

FlieZilla服务器配置与数据访问、传输

概述 手机apk当初服务器&#xff0c;PC端访问手机端的数据&#xff0c;再没有数据线的情况下&#xff0c;非常方便。希望各位同仁搞起来&#xff0c;在此做个笔录。 安装包下载链接&#xff1a;https://download.csdn.net/download/qq_36075612/88577274 一、下载安装包&…

2023-12-08 队列与栈

栈与队列一 232. 用栈实现队列 思路&#xff1a;对于使用栈实现队列的话&#xff0c;必须使用两个共同来维护使得每次都能先进先出&#xff01; class MyQueue:def __init__(self):# 需要建立两个list来维护出栈以及进栈self.stack_in []self.stack_out []def push(self, x…

“ABCD“[(int)qrand() % 4]作用

ABCD[(int)qrand() % 4] 作用 具体来说&#xff1a; qrand() 是一个函数&#xff0c;通常在C中用于生成一个随机整数。% 4 会取 qrand() 生成的随机数除以4的余数。因为4只有四个不同的余数&#xff08;0, 1, 2, 3&#xff09;&#xff0c;所以这实际上会生成一个0到3之间的随…

1.4 Postman的安装

hello大家好&#xff0c;本小节我们来安装一下Postman&#xff0c;好为我们后续的测试工作做准备。 首先&#xff0c;打开Postman的官网Postman API Platform 然后根据同学们自己电脑的操作系统来下载对应的Postman安装包。我这里拿windows来举例。我们点击windows的图标 会跳…

STM32G030C8T6:使用外部晶振配置LED灯闪烁

本专栏记录STM32开发各个功能的详细过程&#xff0c;方便自己后续查看&#xff0c;当然也供正在入门STM32单片机的兄弟们参考&#xff1b; 本小节的目标是&#xff0c;使用STM32G030C8T6单片机&#xff0c;通过STM32CubeMX软件&#xff0c;配置并使用外部8MHz晶振&#xff0c;实…

孩子还是有一颗网安梦——Bandit通关教程:Level 10 → Level 11

&#x1f575;️‍♂️ 专栏《解密游戏-Bandit》 &#x1f310; 游戏官网&#xff1a; Bandit游戏 &#x1f3ae; 游戏简介&#xff1a; Bandit游戏专为网络安全初学者设计&#xff0c;通过一系列级别挑战玩家&#xff0c;从Level0开始&#xff0c;逐步学习基础命令行和安全概念…

3、ollvm移植

github: https://github.com/obfuscator-llvm/obfuscator/tree/llvm-4.0 先复制 include Obfuscation: /home/nowind/llvm/ollvm/obfuscator/include/llvm/Transforms/Obfuscation /home/nowind/llvm/llvm-project-9.0.1/llvm/include/llvm/Transforms/Obfuscation lib Ob…

13.字符串长度【2023.12.5】

1.问题描述 获取字符串长度是编程过程中常用的操作之一。编写一个程序&#xff0c;输入一个字符串&#xff0c;然后输出字符串的长度。 2.解决思路 输入一个字符串。程序将输入的字符串的长度输出。使用内置函数len()获取字符串的长度 3.代码实现 strinput("请输入一…

C语言实现简易版扫雷游戏

由于前面所讲知识点有限&#xff0c;无法实现扫雷游戏的全部功能&#xff0c;本期为各位呈现的是相对简单且易于编写的扫雷游戏。 第一步 设计游戏可玩多次的循环框架 这里在之前猜数字游戏时使用的循环框架一致&#xff0c;但是上次讲解不够深入&#xff0c;这里补充一下。这…

minio可用性磁盘/节点故障恢复的研究

做poc真的很累。年初的报告拿出来按topic拿出来分享一下。 目的 通过模拟各类条件下的minio集群状态&#xff0c;确认minio是否符合官方“N/2硬盘在线&#xff0c;数据可读取&#xff1b;N/21硬盘在线&#xff0c;数据可读写”的描述。 同时通过停止minio集群中节点的服务停止…

青少年CTF-Crypto(Morse code/ASCII和凯撒)

FLAG&#xff1a;你这一生到底想干嘛 专研方向: Web安全 &#xff0c;Md5碰撞 每日emo&#xff1a;不要因为别人都交卷了&#xff0c;就乱选答案 文章目录 1.Morse code2、ASCII和凯撒的约定 1.Morse code 题目提示摩尔斯电码&#xff0c;这个是给的附件 直接用摩尔斯解密&am…
最新文章