用mini2440烧写spiflash『中』
发布时间:2020-12-15 06:13:16 所属栏目:百科 来源:网络整理
导读:上部分主要是说了下调试方法。 另外修改了下spidev.c中的 //static unsigned bufsiz = 4096;static unsigned bufsiz = 4*1024*1024; 下面贴上烧写/读取程序。 程序的致命弱点是速度太慢,主要是因为每次ret = ioctl(Fd_dev,SPI_IOC_MESSAGE(2),Spi_tr);调用
上部分主要是说了下调试方法。 另外修改了下spidev.c中的 //static unsigned bufsiz = 4096; static unsigned bufsiz = 4*1024*1024; 下面贴上烧写/读取程序。 程序的致命弱点是速度太慢,主要是因为每次ret = ioctl(Fd_dev,SPI_IOC_MESSAGE(2),Spi_tr);调用都要花费20ms, 希望高手可以提出解决方法。 /* * SPI program chip(using spidev driver) * * Copyright (c) 2007 MontaVista Software,Inc. * Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com> * Copyright (c) 2012 fengchen <fengchen_rs@qq.com> * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * Cross-compile with cross-gcc -I/path/to/cross-kernel/include */ #include <stdint.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <getopt.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <linux/types.h> #include <linux/spi/spidev.h> /*********spi conf******************/ #define SPI_BITS_PER_WORD 8 #define SPI_SPEED 25000000 #define SPI_MODE 0 #define SPI_DEVICE "/dev/spidev0.0" #define ONCE_READ_MAX_BYTES 3*1024*1024 /*********device******************/ #define MX25L32 //#define MX25L64 //#define W25Q80 /*******************pagesize*******************/ #define SIZE_1M_PAGE_NUM 256*16 //(256sectors)*(16pages/sector) #ifdef W25Q80 //#define CHIP_ID 0x13 #define SPI_FLASH_25_X_XX #define PAGE_NUM SIZE_1M_PAGE_NUM #define TIME_ERASECHIP 2*1000*1000 #define TIME_PAGEPROGRAM 700 #endif #ifdef MX25L32 //#define CHIP_ID 0x15 #define SPI_FLASH_25_X_XX #define PAGE_NUM SIZE_1M_PAGE_NUM*4 #define TIME_ERASECHIP 25*1000*1000 #define TIME_PAGEPROGRAM 1400 #endif #ifdef MX25L64 //#define CHIP_ID 0x16 #define SPI_FLASH_25_X_XX #define PAGE_NUM SIZE_1M_PAGE_NUM*8 #define TIME_ERASECHIP 50*1000*1000 #define TIME_PAGEPROGRAM 1400 #endif /*************** cmd type ************/ struct cmd_type { char* cmd_name; uint8_t cmd; uint8_t num_addr; uint8_t *p_cmd_addr; uint8_t num_dummy; uint8_t mode_data_rw; //r:0,w:1 uint32_t num_data; uint8_t *p_rw_data; uint32_t delay_usecs; }; #ifdef SPI_FLASH_25_X_XX #define PAGE_SIZE 256 //256bytes/page #define CHIP_SIZE PAGE_SIZE*PAGE_NUM #define NUM_ADDR 3 struct cmd_type cmd_readdeviceid = { .cmd_name = "cmd_readdeviceid",.cmd = 0xAB,.num_addr = 0,.p_cmd_addr = NULL,.num_dummy = 3,.mode_data_rw = 0,.num_data = 1,.delay_usecs = 0,}; struct cmd_type cmd_chiperase = { .cmd_name = "cmd_chiperase",.cmd = 0x60,.num_dummy = 0,.num_data = 0,.p_rw_data = NULL,.delay_usecs = TIME_ERASECHIP,// }; struct cmd_type cmd_writeenable = { .cmd_name = "cmd_writeenable",.cmd = 0x06,}; struct cmd_type cmd_readstatus = { .cmd_name = "cmd_readstatus",.cmd = 0x05,}; struct cmd_type cmd_fastread = { .cmd_name = "cmd_fastread",.cmd = 0x0B,.num_addr = NUM_ADDR,.num_dummy = 1,.num_data = CHIP_SIZE,}; struct cmd_type cmd_pageprogram = { .cmd_name = "cmd_pageprogram",.cmd = 0x02,.mode_data_rw = 1,.num_data = PAGE_SIZE,.delay_usecs = 0/4,//transmit need too long time }; #endif int Fd_dev;//spi device struct spi_ioc_transfer Spi_tr[2]={ { .cs_change = 0,//not change(??) .bits_per_word = SPI_BITS_PER_WORD,.rx_buf = (unsigned long)NULL,},{ .cs_change = 0,//change(??) .bits_per_word = SPI_BITS_PER_WORD,}; struct timeval tv; void prt_time(uint8_t num) { gettimeofday(&tv,NULL); printf("[%d,time is %ld]n",num,tv.tv_usec); } uint8_t transmit(struct cmd_type *p_cmd) { int ret; uint32_t i; uint8_t *a_tr_buf; struct spi_ioc_transfer *p_spi_tr; /*send cmd+addr+dummy */ prt_time(0); p_spi_tr = Spi_tr; p_spi_tr->len = 1+(p_cmd->num_addr)+(p_cmd->num_dummy); a_tr_buf = (uint8_t *)malloc(p_spi_tr->len); p_spi_tr->tx_buf = (unsigned long)a_tr_buf; p_spi_tr->rx_buf = (unsigned long)NULL; a_tr_buf[0] = p_cmd->cmd; prt_time(1); for(i=0;i<(p_cmd->num_addr);i++){ a_tr_buf[1+i] = (p_cmd->p_cmd_addr)[(p_cmd->num_addr-1)-i];//large addr first } for(i=0;i<(p_cmd->num_dummy);i++){ a_tr_buf[1+(p_cmd->num_addr)+i] = 0xFF; } /*send/receive data*/ prt_time(2); p_spi_tr ++; p_spi_tr->len = p_cmd->num_data; p_spi_tr->delay_usecs = p_cmd->delay_usecs; if(p_cmd->num_data){ if(p_cmd->mode_data_rw){ //write p_spi_tr->tx_buf = (unsigned long)(p_cmd->p_rw_data); p_spi_tr->rx_buf = (unsigned long)NULL; } else{//read p_spi_tr->tx_buf = (unsigned long)NULL; p_spi_tr->rx_buf = (unsigned long)(p_cmd->p_rw_data); } } /*spi operation*/ prt_time(3); ret = ioctl(Fd_dev,Spi_tr); prt_time(4); if (ret < 1){ printf("n[Return = %d. Can't read/write chip !]n",ret); goto ERROR; } free(a_tr_buf); prt_time(5); return 0; ERROR: free(a_tr_buf); return 1; } uint8_t spi_conf(char *device) { int ret = 0; uint8_t mode = SPI_MODE,bits_per_word = SPI_BITS_PER_WORD; uint32_t max_speed_hz = SPI_SPEED; ret += ioctl(Fd_dev,SPI_IOC_WR_MODE,&mode); ret += ioctl(Fd_dev,SPI_IOC_RD_MODE,SPI_IOC_WR_BITS_PER_WORD,&bits_per_word); ret += ioctl(Fd_dev,SPI_IOC_RD_BITS_PER_WORD,SPI_IOC_WR_MAX_SPEED_HZ,&max_speed_hz); ret += ioctl(Fd_dev,SPI_IOC_RD_MAX_SPEED_HZ,&max_speed_hz); if(ret||(mode!=SPI_MODE)||(bits_per_word!=SPI_BITS_PER_WORD)||(max_speed_hz!=SPI_SPEED)){ printf("SPI mode configure ERROR : mode=%d!n",mode); return 1; } return 0; } uint8_t read_status() { uint8_t status=0x88; int ret; cmd_readstatus.p_rw_data = &status; ret = transmit(&cmd_readstatus); if(ret){ puts("Read status ERROR!"); } return status; } uint8_t write_enable() { int ret; ret = transmit(&cmd_writeenable); if(ret){ puts("Set WEL bit ERROR: 0!"); return 1; } return 0; } uint8_t verity_id(char * filename) { uint8_t id=0x1d; int ret; struct stat file_status; ret = stat(filename,&file_status); if(ret < 0){ puts("nRead file status ERROR!"); return 1; } printf("nFile size is %ldBytes(%.2fMBytes).n",file_status.st_size,(float)file_status.st_size/1024/1024); if(file_status.st_size > CHIP_SIZE){ puts("Error : File size is bigger than Chip size!"); return 1; } if((read_status())&0x01){ puts("Device is busy!"); return 1; } cmd_readdeviceid.p_rw_data = &id; ret = transmit(&cmd_readdeviceid); if(ret){ puts("Get ID Failure!"); return 1; } printf("The chip ID is 0x%x.nContinue ? (y/n)",id); if(getchar()=='y'){ puts("Wait several minute..."); } else{ puts("Exit.n"); return 1; } return 0; } uint8_t erase_chip() { int ret; uint32_t sleep_time; uint32_t i = 0; ret = write_enable(); if(ret){ puts("Erase disable!"); return 1; } ret = transmit(&cmd_chiperase); if(ret){ puts("Erase chip ERROR 1 !"); return 1; } else{ if((read_status())&0x01){ printf("Erasing..."); } else{ //not working puts("Erase chip ERROR 2 !"); return 1; } } sleep_time = cmd_chiperase.delay_usecs/100; while((read_status())&0x01){ usleep(sleep_time); } puts("nErase Done.");//spi_ioc_transfer-delay_usecs return 0; } uint8_t write_page(uint32_t num_page,uint8_t *p_buf_w) { int ret; uint32_t j; uint32_t sleep_time; uint8_t p_addr[NUM_ADDR]; for(j=0;j<NUM_ADDR;j++){ p_addr[j] = (uint8_t)((num_page*PAGE_SIZE)>>(8*j)); } cmd_pageprogram.p_cmd_addr = p_addr; cmd_pageprogram.p_rw_data = p_buf_w; ret = write_enable(); if(ret){ puts("nWrite disable!n"); goto ERROR; } ret = transmit(&cmd_pageprogram); if(ret){ printf("nWrite Failure! Page : %d!n",num_page); goto ERROR; } sleep_time = cmd_pageprogram.delay_usecs/100; while((read_status())&0x01){ usleep(sleep_time); } return 0; ERROR: return 1; } uint8_t write_chip(char * filename) { uint8_t *p_buf_w; int i; int ret; int fd_file; int size_w,num; fd_file = open(filename,O_RDONLY); if (fd_file < 0){ printf("Can't open file : %sn",filename); return 1; } p_buf_w = (uint8_t*)malloc(CHIP_SIZE); size_w = read(fd_file,p_buf_w,CHIP_SIZE); if(size_w<0){ puts("Read file ERROR!"); return 1; } memset(p_buf_w+size_w,0xff,PAGE_SIZE-size_w%PAGE_SIZE); printf("Writing... ---%%."); num=size_w; for(i=0;num>0;i++) { prt_time(10); ret = write_page(i,p_buf_w+PAGE_SIZE*i); if(ret){ printf("nWrite page %d ERROR!n",i); goto ERROR; } printf("bbbbb%03d%%.",(i*PAGE_SIZE*100)/size_w); num -= PAGE_SIZE; } printf("bbbbb100%%.nWrite Done.n",size_w); close(fd_file); free(p_buf_w); return 0; ERROR: close(fd_file); free(p_buf_w); return 1; } uint8_t read_chip(uint8_t *p_buf_r,uint32_t size_r) { uint8_t p_addr[NUM_ADDR]; int ret; uint32_t i,j; int n; uint32_t addr; addr = 0; for(n = size_r,i = 0;n > 0;n -= ONCE_READ_MAX_BYTES,i++){ addr += ONCE_READ_MAX_BYTES*i; for(j=0;j<NUM_ADDR;j++){ p_addr[j] = (uint8_t)(addr>>j*8); } cmd_fastread.p_cmd_addr = p_addr; p_buf_r += ONCE_READ_MAX_BYTES*i; cmd_fastread.p_rw_data = p_buf_r; if(n<ONCE_READ_MAX_BYTES){ cmd_fastread.num_data = n; } else{ cmd_fastread.num_data = ONCE_READ_MAX_BYTES; } ret = transmit(&cmd_fastread); if(ret){ puts("nRead CHIP Failure!"); goto ERROR; } } return 0; ERROR: return 1; } uint8_t verity_chip(char * filename) { uint8_t *p_buf_r,*p_buf_file; int ret; uint32_t i; int fd_file; int size_r,num; fd_file = open(filename,filename); return 1; } p_buf_file = (uint8_t *)malloc(CHIP_SIZE); size_r = read(fd_file,p_buf_file,CHIP_SIZE); if(size_r<0){ puts("Read file ERROR!"); return 1; } p_buf_r = (uint8_t *)malloc(CHIP_SIZE); ret = read_chip(p_buf_r,size_r); if(ret){ goto ERROR; } puts("Veritying..."); /* for(i=0;i<size_r;i++) { if(p_buf_file[i]!=p_buf_r[i]){ //not match printf("nByte num %d Error! p_buf_file[%d]=%2x,p_buf_r[%d]=%2x.n",i,p_buf_file[i],p_buf_r[i]); goto ERROR; } printf("bbbbb%3d%%.",i/(size_r/100)); } */ ret = memcmp(p_buf_file,p_buf_r,size_r); if(ret){ puts("Verity ERROR!"); goto ERROR; } else{ puts("Verity Done."); } close(fd_file); free(p_buf_file); free(p_buf_r); return 0; ERROR: close(fd_file); free(p_buf_file); free(p_buf_r); return 1; } void check_exit(int ret) { if(ret){ close(Fd_dev); exit(0); } } int main(int argc,char *argv[]) { int ret; char *filename = argv[1];//"/home/fengchen/nfs.dir/spi_flash/MX25L80_firmware"; Fd_dev = open(SPI_DEVICE,O_RDWR); if (Fd_dev < 0){ puts("Can't open device."); return 1; } ret = spi_conf(SPI_DEVICE); check_exit(ret); ret = verity_id(filename); check_exit(ret); ret = erase_chip(); check_exit(ret); ret = write_chip(filename); check_exit(ret); ret = verity_chip(filename); check_exit(ret); close(Fd_dev); puts("Succeed !"); //ok return 0; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |