Linux MTD测试程序

来源:互联网 发布:mac chrome广告终结者 编辑:程序博客网 时间:2024/06/05 07:42


/** 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;elseprintf("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 regionsregion_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+1printf("\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;}/* [] */


0 0