Linux MTD测试程序

本文介绍了一个FPGA应用示例程序,包括FPGA设备的打开与关闭、状态检查、配置文件写入、闪存擦除及读取等功能。通过具体的C语言代码实现,展示了如何与FPGA交互并完成配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


/** filename: program.c
* description: demo of program FPGA application
* date: 2015-10-13
* compiler: ARCH=arm CROSS_COMPILE=arm-fsl-linux-gnueabi-  make
*/

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <asm/ioctl.h>
#include <mtd/mtd-user.h>
#include <errno.h>
#include <ctype.h>   /* isprint */



/* gpio index */
#define FPGA_GPIO_NCONFIG   	0      
#define FPGA_GPIO_ROMPATH_SEL   1	
#define FPGA_GPIO_CONF_DONE   	2  	
#define FPGA_GPIO_NSTATUS   	3

/* dev/fpga   ioctl cmd  */
#define FPGA_IOC_SET_GPIO	_IO('F',0)
#define FPGA_IOC_RST_GPIO	_IO('F',1)
#define FPGA_IOC_GET_GPIO	_IO('F',2)


#define BUFFER_SIZE 1048576
#define DEBUG_SIZE  2048

/* buffer */
char buffer[BUFFER_SIZE];
char read_buffer[DEBUG_SIZE];


/* fpga device */
struct fpga {
	int fd;

        int nconfig;
        int rompath_sel;
	int conf_done;
	int nstaus;
};

/* global variable */
struct fpga fpga_dev;


/** flash erase
*/
int region_erase(int Fd, int start, int count, int unlock, int regcount)
{
	int i, j;
	region_info_t * reginfo;

	reginfo = calloc(regcount, sizeof(region_info_t));

	for(i = 0; i < regcount; i++)
	{
		reginfo[i].regionindex = i;
		if(ioctl(Fd,MEMGETREGIONINFO,&(reginfo[i])) != 0)
			return 8;
		else
			printf("Region %d is at %d of %d sector and with sector "
					"size %x\n", i, reginfo[i].offset, reginfo[i].numblocks,
					reginfo[i].erasesize);
	}

	// We have all the information about the chip we need.

	for(i = 0; i < regcount; i++)
	{ //Loop through the regions
		region_info_t * r = &(reginfo[i]);

		if((start >= reginfo[i].offset) &&
				(start < (r->offset + r->numblocks*r->erasesize)))
			break;
	}

	if(i >= regcount)
	{
		printf("Starting offset %x not within chip.\n", start);
		return 8;
	}

	//We are now positioned within region i of the chip, so start erasing
	//count sectors from there.

	for(j = 0; (j < count)&&(i < regcount); j++)
	{
		erase_info_t erase;
		region_info_t * r = &(reginfo[i]);

		erase.start = start;
		erase.length = r->erasesize;

		if(unlock != 0)
		{ //Unlock the sector first.
			if(ioctl(Fd, MEMUNLOCK, &erase) != 0)
			{
				perror("\nMTD Unlock failure");
				close(Fd);
				return 8;
			}
		}
		printf("\rPerforming Flash Erase of length 0x%llx at offset 0x%llx",
				erase.length, erase.start);
		fflush(stdout);
		if(ioctl(Fd, MEMERASE, &erase) != 0)
		{
			perror("\nMTD Erase failure");
			close(Fd);
			return 8;
		}


		start += erase.length;
		if(start >= (r->offset + r->numblocks*r->erasesize))
		{ //We finished region i so move to region i+1
			printf("\nMoving to region %d\n", i+1);
			i++;
		}
	}

	printf(" done\n");

	return 0;
}


int non_region_erase(int Fd, int start, int count, int unlock)
{
    mtd_info_t meminfo;
    if (ioctl(Fd,MEMGETINFO,&meminfo) == 0)
    {
        erase_info_t erase;
        erase.start = start;
        erase.length = meminfo.erasesize;
        for (; count > 0; count--) {
            printf("\rPerforming Flash Erase of length %u at offset 0x%x",
                    erase.length, erase.start);
            fflush(stdout);
            if(unlock != 0)
            {
                //Unlock the sector first.
                printf("\rPerforming Flash unlock at offset 0x%x",erase.start);
                if(ioctl(Fd, MEMUNLOCK, &erase) != 0)
                {
                    perror("\nMTD Unlock failure");
                    close(Fd);
                    return 8;
                }
            }
            if (ioctl(Fd,MEMERASE,&erase) != 0)
            {
                perror("\nMTD Erase failure");
                close(Fd);
                return 8;
            }
            erase.start += meminfo.erasesize;
        }
        printf(" done\n");
    }
    return 0;
}


/** fpga print info
*/
int print_fpga(void)
{
	char str[128];

	sprintf(str,"nconfig:%d\n", fpga_dev.nconfig);
	printf(str);
	sprintf(str,"rompath sel:%d\n", fpga_dev.rompath_sel);
	printf(str);
	sprintf(str,"conf_done:%d\n", fpga_dev.conf_done);
	printf(str);
	sprintf(str,"nstatus:%d\n", fpga_dev.nstaus);
	printf(str);

	return 0;
}


/** after write flash, poll up nconfig single, and wait at least 2us
*/
int fpga_nconfig()
{
	char str[128];
	int ret, param;
        
        /* pull down rompath sel */
	ret = ioctl(fpga_dev.fd, FPGA_IOC_RST_GPIO, FPGA_GPIO_ROMPATH_SEL);
     	if(ret < 0) {
		sprintf(str,"Unable to rst nconfig single, errno=%d\n",errno);
		printf(str);
		return -1;
	}

	sleep(20);

        /* pull down nconfig */
	ret = ioctl(fpga_dev.fd, FPGA_IOC_RST_GPIO, FPGA_GPIO_NCONFIG);
     	if(ret < 0) {
		sprintf(str,"Unable to rst nconfig single, errno=%d\n",errno);
		printf(str);
		return -1;
	}
        
        /* sleep 2us */
	sleep(2);

        /* query nconfig*/
        param = FPGA_GPIO_NCONFIG;
	ret = ioctl(fpga_dev.fd, FPGA_IOC_GET_GPIO, ¶m);
     	if(ret < 0) {
		sprintf(str,"Unable to get  single, errno=%d\n",errno);
		printf(str);
		return -1;
	}
	fpga_dev.nconfig = param;
        printf("================query nconfig:%d\n", fpga_dev.nconfig);

        /* pull up nconfig */
	ret = ioctl(fpga_dev.fd, FPGA_IOC_SET_GPIO, FPGA_GPIO_NCONFIG);
     	if(ret < 0) {
		sprintf(str,"Unable to set nconfig single, errno=%d\n",errno);
		printf(str);
		return -1;
	}

	return 0;
}


/** check status
*/
int fpga_check()
{
	char str[128];
	int ret, param;
        
        param = FPGA_GPIO_NCONFIG;
	ret = ioctl(fpga_dev.fd, FPGA_IOC_GET_GPIO, ¶m);
     	if(ret < 0) {
		sprintf(str,"Unable to get  single, errno=%d\n",errno);
		printf(str);
		return -1;
	}
	fpga_dev.nconfig = param;


        param = FPGA_GPIO_ROMPATH_SEL;
	ret = ioctl(fpga_dev.fd, FPGA_IOC_GET_GPIO, ¶m);
    	if(ret < 0) {
		sprintf(str,"Unable to get rompath sel single, errno=%d\n",errno);
		printf(str);
		return -1;
	}
	fpga_dev.rompath_sel = param;


        /* get  conf done */
        param = FPGA_GPIO_CONF_DONE;
	ret = ioctl(fpga_dev.fd, FPGA_IOC_GET_GPIO, ¶m);
     	if(ret < 0) {
		sprintf(str,"Unable to get conf_done single, errno=%d\n",errno);
		printf(str);
		return -1;
	}
	fpga_dev.conf_done = param;


        /* get nstaus */
        param = FPGA_GPIO_NSTATUS;
	ret = ioctl(fpga_dev.fd, FPGA_IOC_GET_GPIO, ¶m);
    	if(ret < 0) {
		sprintf(str,"Unable to get nstatus single, errno=%d\n",errno);
		printf(str);
		return -1;
	}
	fpga_dev.nstaus = param;
        
        print_fpga();
	return 0;
}


/** open fpga device
*
*/
static int open_device(void)
{
	char str[128];
	int ret;

	fpga_dev.fd = open("/dev/fpga", O_RDWR);
	if (fpga_dev.fd < 0) {
		sprintf(str, "Unable to open file /dev/fpga, errno=%d\n", errno);
		printf(str);
		return -1;
	}
        printf("successful open device /dev/fpga. file handle:%d\n", fpga_dev.fd);

	return 0;
}

static int close_device(void)
{
	close(fpga_dev.fd);

	return 0;
}


/** get file size
*/
unsigned long get_file_size(const char *path)
{
	unsigned long filesize = -1;	
	struct stat statbuff;
	if(stat(path, &statbuff) < 0) {
		return filesize;
	}else{
		filesize = statbuff.st_size;
	}
	return filesize;
}



/* read */
int flash_erase(const char* device)
{
    int fd;
    int bytes_read;
    struct mtd_info_user info;
    int regcount;
    int start;
    int count;
    int unlock;
    int ret;
  
    /*1. open dst mtd device file */
    if ((fd = open(device, O_RDWR)) < 0)
    {
        fprintf(stderr,"Open %s Error:%s\n", device, strerror(errno));
        return -1;
    }
    else
    {
        if(ioctl(fd,MEMGETINFO,&info) == 0)
        {
/*
		printf("info.size=%d\n info.erasesize=%d\ninfo.writesize=%d\n 
		info.oobsize=%d\n",
		info.size,info.erasesize,info.writesize,info.oobsize);
*/  
      }
    }

    /* flash erase */
    start = 0;
    count = info.size/info.erasesize;
    unlock = 0;
    printf("Erase Total %d Units\n", count);

    if (ioctl(fd,MEMGETREGIONCOUNT,&regcount) == 0)
    {
        printf("regcount=%d\n",regcount);
	if(regcount == 0)
	{
		ret = non_region_erase(fd, start, count, unlock);
	}
	else
	{
		ret = region_erase(fd, start, count, unlock, regcount);
	}
    }
            
    printf("erased flash!\n");
    sleep(3);


   /* */
   close(fd);

   return 0;
}


/** write the FPGA config file to Altera ECPS flash device
 */
int program(const char *filename, const char* device)
{
    int ret;
    int from_fd,to_fd;
    int bytes_read,bytes_write;
    int file_count, left_bytes;
    unsigned long file_size, total_bytes;
    char *ptr;
     
    /* check  */
    if(!filename || !*filename || !device || !*device) {
         fprintf(stderr,"Invalidate parameter, application exit\n");
         return -1;
    }
   
    file_size = get_file_size(filename);
    file_count = file_size / BUFFER_SIZE;
    left_bytes = file_size % BUFFER_SIZE;
    printf("file name:%s, file size:%d bytes, file count:%d, left bytes:%d\n",
         filename, file_size, file_count, left_bytes);


    /*1. open source file */
    if((from_fd=open(filename,O_RDONLY))==-1)   /*open file readonly, if error return -1, otherwise return file desc */
    {
        fprintf(stderr,"Open %s Error:%s\n", filename,strerror(errno));
        return -2;
    }
 
    /*2. open dst mtd device file */
    if ((to_fd = open(device, O_RDWR)) < 0)
    {
        fprintf(stderr,"Open %s Error:%s\n", device, strerror(errno));
        close(from_fd);
        return -1;
    }


   /*3. this is classical copy file code */
   int cnt = 0;

   total_bytes = 0;
   while(bytes_read = read(from_fd, buffer, BUFFER_SIZE))
   { 
     /* debug code */
     if(cnt == 0)
     {
        //memset(buffer, 'A', BUFFER_SIZE); 
     }

     if((bytes_read == -1)&&(errno != EINTR)) 
         break;
     else if(bytes_read > 0)
     {
       ptr = buffer;
       while(bytes_write = write(to_fd, ptr, bytes_read))
       {
         if((bytes_write == -1)&&(errno != EINTR))
         {
             printf("flash write error.....\n\n\n ");
             break; 
         }
         else if(bytes_write == bytes_read) 
         {
             total_bytes += bytes_write;
             break;
         }
         else if(bytes_write > 0)
         {
            ptr += bytes_write;
            bytes_read -= bytes_write;

            total_bytes += bytes_write;
         }
       }// end while

       printf("\rWrite %ld bytes\n ", total_bytes);
       
       if(bytes_write == -1)
           break;
     }

      cnt++;
   }// end for


   printf("\n\n\n");
   sleep(5);

   // clean:
   close(from_fd);
   close(to_fd);

   return 0;
}

/* read */
int flash_read(const char* device, int size)
{
    int fd;
    int bytes_read;
  
    /*1. open dst mtd device file */
    if ((fd = open(device, O_RDWR)) < 0)
    {
        fprintf(stderr,"Open %s Error:%s\n", device, strerror(errno));
        return -1;
    }

    /*2. read */
    bytes_read = read(fd, read_buffer, size);
    printf("read %d bytes from device %s\n", bytes_read, device);
    
    int i;
    for(i = 0; i < bytes_read; i++)
    {
        if(isprint(read_buffer[i]))
           printf("%c", read_buffer[i]);
        else 
           printf(".");
        
        if((i + 1) % 16 == 0)
            printf("\n");
    }
    printf("\n\n");

    /* */
    close(fd);
    
    return 0;
}



/** main routine
*/
int main(int argc, char *argv[])
{
    if(3 > argc)
    {
        printf("Usage: ./program filename device\n");
        return -1;
    }
    
    fpga_dev.conf_done = -99;
    fpga_dev.nstaus = -99;


    /* open device */
    open_device();

    /* check */
    fpga_check();

    /* erase flash */
    flash_erase(argv[2]);


    /* program FPGA */
    if(program(argv[1], argv[2]) == 0)
    {
        printf("success program flash!\n");
        sleep(3);

        flash_read(argv[2], DEBUG_SIZE);

        sleep(10);

        /* trigger */
        fpga_nconfig();
    
        /* check singele */
        int i;
        for(i = 0; i < 5; i ++)
        {
             fpga_check();
             if( fpga_dev.conf_done == 1 || fpga_dev.nstaus == 1)
             {
                 printf("success query fpga state.");
                 break;
             }
             sleep(1);
        }
        
         if(i > 5)
           printf("can't query fpga state");


   }else {
        printf("program flash failed!\n");
   }
 

    /* close fpga device */
    close_device();
    
    return 1;
}


/* [] */


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值