armボード書きflash(2)

31089 ワード

armボード書きflash(2)


imx 6 armボードはspiflashのコードの第1篇のブログのアドレスを书いて下で、ここで主にテストを书いて、私达は私达が书いたデータが正しいかどうか分からないで、前に书いたデータを読んで印刷して、ファイルが数メガバイトの时、密密麻の2级制はどのように见て、ここでいくつかexeを书いて、pdfファイルをテストしてテストします.http://blog.csdn.net/chenqianleo/article/details/73658493
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
/* * write a file to spi_flash */
#define W25_WRITE_ENABLE 0x06
#define W25_WRITE_DISABLE 0x04
#define W25_READ_STATUS_1 0x05
#define W25_READ_STATUS_2 0x35
#define W25_WRITE_STATUS 0x01
#define w25_WRITE_SATTUS_ENABLE 0x50
#define W25_READ_DATA 0x03
#define W25_READ_FAST_DATA 0x0B
#define W25_ERASE_SECTOR 0x20
#define W25_ERASE_BLOCK 0xD8
#define W25_ERASE_CHIP 0xc7
#define W25_PAGE_PROGRAM 0x02
#define W25_CHIP_ID 0x9F
#define RDSR_CNT 1000

#define W25_SR_BUSY 0x01
#define FLASH_MAX_SIZE (8*1024*1024) 
#define ONE_SELECTOR_SIZE (4*1024)
#define WRITE_READ_ONCE_SIZE 256
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

static const char* spi_device = "/dev/spidev2.2";
static unsigned char mode;
static unsigned char bits = 8;
static unsigned int speed = 3000000;
static unsigned short delay;
static unsigned char buf[256] = {0};
static unsigned char rxbuffer[1];   
static unsigned char txbuffer[260];

static int getFileSize(const char* name);
static void dis_array(const char* info , const unsigned char* buf, unsigned int len);
static int w25_write_read(int fd , const char* wbuf,unsigned int wlen,
    const char* rbuf , unsigned int rlen);
static int wait_for_idle(int fd);
static int write_spiflash(int fd ,char* buf, int offset , 
    int address_one, int address_two , int address_three);
static int write_spiflash_finally(int fd ,char* buf, int offset , int num, 
    int address_one, int address_two , int address_three);
static void read_spiflash(int fd, int address_one , int address_two,
    int address_three);
static void read_spiflash_savefile(int fd ,FILE* savefd, 
        int address_one , int address_two , int address_three);
static void write_enable(int fd);
static void selector_erase(int fd,int address_one , int address_two , int address_three);
static void print_chipID(int fd);
static void write_status_register(int fd);
static void read_spiflash_savefile_finally(int fd ,FILE* savefd , int num , 
        int  address_one , int address_two , int address_three);

/* * return file size (bytes) */
static int getFileSize(const char* name){
    FILE * pFile = fopen(name , "rb+");
    if(pFile == NULL){
        printf("cout error
"
); return -1; } fseek(pFile , 0 ,SEEK_END); int length = ftell(pFile); fclose(pFile); return length; } /* * print some useful information * @info equla TAG * @buf print buf @len length */ static void dis_array(const char* info , const unsigned char* buf, unsigned int len){ int i = 0; printf("%s :",info); for(i = 0; i< len ; i++){ printf("%02x " , buf[i]); } printf("
"
); } /* * write and read */ static int w25_write_read(int fd , const char* wbuf,unsigned int wlen, const char* rbuf , unsigned int rlen){ int ret = 0; struct spi_ioc_transfer tr[2] = { { .tx_buf = (unsigned long)wbuf, .rx_buf = 0, .len = wlen, .speed_hz = speed, }, { .tx_buf = 0, .rx_buf = (unsigned long)rbuf, .len = rlen, .speed_hz = speed, }, }; ret = ioctl(fd , SPI_IOC_MESSAGE(2) , tr); return ret; } /* * before every command do judge of status register */ static int wait_for_idle(int fd){ int i = 0 ; unsigned char strg = 0; unsigned char tempcmd = W25_READ_STATUS_1; int ret = 0; for (i=0;isizeof(tempcmd ), &strg, sizeof(strg)); if(ret < 0 ){ printf("get status register value error
"
); goto exit; } if(strg & W25_SR_BUSY){ //printf("wait for idle ...
");
usleep(20); continue; }else{ break; } } if( i == RDSR_CNT){ printf("/dev/spidev2.2 is too busy now -------------------------------
"
); ret = -1; goto exit; } return 0; exit: return ret; } /* * wirte data to spi 256 bytes (a page) */ static int write_spiflash(int fd ,char* buf, int offset , int address_one, int address_two , int address_three){ txbuffer[0] = W25_PAGE_PROGRAM; txbuffer[1] = address_one; txbuffer[2] = address_two; txbuffer[3] = address_three; for(int i = 0 ;i< WRITE_READ_ONCE_SIZE; i++){ txbuffer[i+4] = buf[i+offset]; } //dis_array("Write 256 bytes", txbuffer , sizeof(txbuffer)); wait_for_idle( fd ); write_enable(fd); w25_write_read( fd, txbuffer , sizeof(txbuffer), rxbuffer, 0); printf("write selector %02x%02x%02x ok
"
,address_one,address_two,address_three); } /* * write data to spi less than 256,file finally size is less to 256 */ static int write_spiflash_finally(int fd ,char* buf, int offset , int num, int address_one, int address_two , int address_three){ txbuffer[0] = W25_PAGE_PROGRAM; txbuffer[1] = address_one; txbuffer[2] = address_two; txbuffer[3] = address_three; for(int i=0;i4] = buf[i+offset]; } wait_for_idle( fd ); write_enable(fd); w25_write_read( fd, txbuffer ,(4+num), rxbuffer, 0); printf("write selector %02x%02x%02x ok
"
,address_one,address_two,address_three); } /* * read data from spi 256 print or not */ static void read_spiflash(int fd, int address_one , int address_two, int address_three){ unsigned char tempcmd[4] = {0}; wait_for_idle( fd ); tempcmd[0] = W25_READ_DATA; tempcmd[1] = address_one; tempcmd[2] = address_two; tempcmd[3] = address_three; w25_write_read(fd, tempcmd , 4 , buf , sizeof(buf)); //dis_array("Read 256 bytes", buf , sizeof(buf)); } /* * read data to save a file to test */ static void read_spiflash_savefile(int fd ,FILE* savefd , int address_one , int address_two , int address_three){ unsigned char tempcmd[4] = {0}; wait_for_idle( fd ); tempcmd[0] = W25_READ_DATA; tempcmd[1] = address_one; tempcmd[2] = address_two; tempcmd[3] = address_three; w25_write_read(fd, tempcmd , 4 , buf , sizeof(buf)); fwrite(buf , ARRAY_SIZE(buf) , 1 , savefd ); } /* * read data to save a file to test */ static void read_spiflash_savefile_finally(int fd ,FILE* savefd , int num , int address_one , int address_two , int address_three){ unsigned char tempcmd[4] = {0}; wait_for_idle( fd ); tempcmd[0] = W25_READ_DATA; tempcmd[1] = address_one; tempcmd[2] = address_two; tempcmd[3] = address_three; w25_write_read(fd, tempcmd , 4 , buf , sizeof(buf)); fwrite(buf , num , 1 , savefd ); } /* * write enable , before erase , write should do this */ static void write_enable(int fd){ unsigned char tempcmd = W25_WRITE_ENABLE; write(fd , &tempcmd , sizeof(tempcmd)); } /* * erase 4KB * @parm address_one address A23-A16 * @parm address_two address A15-A8 * @parm address_two address A7-A0 */ static void selector_erase(int fd,int address_one , int address_two , int address_three){ unsigned char tempcmd[4] = {0}; wait_for_idle( fd ); write_enable(fd); tempcmd[0] = W25_ERASE_SECTOR; tempcmd[1] = address_one; tempcmd[2] = address_two; tempcmd[3] = address_three; write( fd, tempcmd ,4); printf("Erase_Sector: %02x%02x%02x selector erase done ..
"
,address_one,address_two,address_three); } /* * print_chip_id */ static void print_chipID(int fd){ unsigned char tempbuf[3] = {0}; unsigned char tempcmd = W25_CHIP_ID; w25_write_read( fd, &tempcmd , sizeof(tempcmd ), tempbuf , 3); dis_array("chip_ID: ManufactureID MemoryTypeID CapacityID ", tempbuf , 3); } /* * write status register , not do will create some no-konwun consequencce , don`t kown */ static void write_status_register(int fd){ unsigned char tempcmd[3] = {0}; wait_for_idle( fd ); write_enable(fd); tempcmd[0] = W25_WRITE_STATUS; tempcmd[1] = 0; tempcmd[2] = 0; write(fd , tempcmd , 3 ); } int main(int argc , char* argv[]){ int ret = 0; int fd; char* fileName ; int erase_selector_number = 0; int write_selector_number = 0; if(argc != 2){ printf("Usage: %s %s
"
,argv[0] , "fileName"); return -1; }else{ fileName = argv[1]; } fd = open(spi_device , O_RDWR); if (fd < 0){ printf("open /dev/spidev error
"
); } /* * spi mode */ ret = ioctl(fd , SPI_IOC_WR_MODE , &mode); if (ret == -1){ printf("set spi mode error
"
); } ret = ioctl(fd , SPI_IOC_RD_MODE , &mode); if (ret == -1){ printf("get spi mode error
"
); } /* * bits per word */ ret = ioctl(fd , SPI_IOC_WR_BITS_PER_WORD , &bits); if (ret == -1){ printf("set bits per word error
"
); } ret = ioctl(fd , SPI_IOC_RD_BITS_PER_WORD , &bits); if (ret == -1){ printf("get bits per word error
"
); } /* * max speed hz */ ret = ioctl(fd , SPI_IOC_WR_MAX_SPEED_HZ , &speed); if (ret == -1){ printf("set max speed error
"
); } ret = ioctl(fd , SPI_IOC_RD_MAX_SPEED_HZ , &speed); if (ret == -1){ printf("get max speed error
"
); } /* * print useful info */ printf("spi mode: %d
"
,mode); printf("spi bits per words : %d
"
, bits); printf("spi max speed : %dhz (%dkHz)
"
,speed , speed/1000); /* * open written file covert to bytes[] */ int length = getFileSize(fileName); //file size must less than 8M if(length > FLASH_MAX_SIZE){ printf("The Flash Max Size is 8*1024*1024,your written file size = %dM
"
,length/1024/1024); return -2; } FILE *filefd; filefd = fopen(fileName , "rw+"); unsigned char filebuf[length]; fread(filebuf , sizeof(char) , length , filefd); fclose(filefd); printf("Written file size = %dKB
"
, length/1024); //dis_array("Written_file_info", filebuf , sizeof(filebuf)); /* * get chip id */ print_chipID(fd); //write status register write_status_register(fd); /* *once erase suitable selector */ erase_selector_number = (length/ONE_SELECTOR_SIZE + 1); printf("Now begin erase foresee size = %d , please waiting...
"
,erase_selector_number); int tempa_erase,tempb_erase,tempc_erase = 0 , seletor_times = 0; for(int i = 0 ; i< erase_selector_number ; i++){ tempa_erase = i / 16; tempb_erase = (i % 16) * 16; selector_erase( fd, tempa_erase , tempb_erase , tempc_erase ); seletor_times++; } printf("Erase subitable selector done , erase_times = %d
"
,seletor_times); /* * now begin write */ write_selector_number = length/WRITE_READ_ONCE_SIZE + 1; int all_selector_write = write_selector_number - 1; int finally_size = length % WRITE_READ_ONCE_SIZE; printf("now begin write , write_selector_number = %d
"
,write_selector_number); int tempa_write,tempb_write,tempc_write = 0,write_times = 0; for(int i=0;i256; tempb_write = i%256; if(i < all_selector_write){ write_spiflash( fd, filebuf ,i*256 , tempa_write, tempb_write, tempc_write); }else{ write_spiflash_finally(fd, filebuf , i*256 , finally_size ,tempa_write, tempb_write, tempc_write); } write_times++; } printf("writed done , write_times = %d
"
,write_times); /* * * now read to test */ FILE* savefd; char* backup = "backup"; char saveName[30]; strcpy(saveName , backup); strcat(saveName, fileName); savefd = fopen(saveName , "ab+"); int tempa_read,tempb_read,tempc_read = 0; for(int i = 0 ;i256; tempb_read = i%256; if(i < all_selector_write){ read_spiflash_savefile( fd, savefd , tempa_read, tempb_read, tempc_read); }else{ read_spiflash_savefile_finally( fd, savefd, finally_size , tempa_read, tempb_read, tempc_read); } } fclose(savefd); close(fd); return ret; exit: printf("error exit........................
"
); return ret; }

テストを経て、上のプログラムは完全に正確にflashにデータを書き込むことができて、exeファイル、pdfファイル、bmpファイルをテストしました