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ファイルをテストしました