树莓派spi读写取w25q64芯片

手头有个MTK7628的路由器,我要用修改openwrt系统,为了保留原本的系统环境,不得不绞尽脑汁想出
此对策,将w25q64中的系统镜像提取出来。工欲善其事必先利其器,以下便是镜像提取工具制作的详细过程。
原料:
树莓派3B+,sd卡,w25q64芯片。

准备:

开启树莓派spi功能:

执行:sudo raspi-config

选择 Advanced Options   -> SPI -> yes  启动 SPI 内核驱动
 运行 lsmod 命令,可以看到 spi 模块“spi_bcm2835”已启动
树莓派spi读写取w25q64芯片_第1张图片
/dev 路径下面,我们可以发现两个 spi 设备
树莓派spi读写取w25q64芯片_第2张图片
树莓派与w25q64芯片的链接方法

树莓派spi读写取w25q64芯片_第3张图片


上图的网络标号括号内对应树莓派排针的引脚序号。

接下来直接贴代码

#include   
#include   
#include   
#include   
#include   
#include   
#include   
#include   
#include   
  
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))  
#define RX_TX_MAX 1024
 
static void pabort(const char *s)  
{  
    perror(s);  
    abort();  
}  
  
static const char *device = "/dev/spidev0.0";  
static uint8_t mode;  
static uint8_t bits = 8;  
static uint32_t speed = 1000000;  
static uint16_t delay; 
static char* file_name;
static uint32_t number_byte=0;
static uint8_t read_write_flg=0;	//0-read 1-write

int spi_fd;

  
static void read_date(int addr,char *buff,int size)  
{  
    int ret,i;  
    uint8_t rx[RX_TX_MAX];
    uint8_t tx[RX_TX_MAX] = {  
        0x03, 0x00, 0x00, 0x00,0x00,
     
    };  
    
    tx[1]=(addr&0xFF0000)>>16;
    tx[2]=(addr&0xFF00)>>8;
    tx[3]=addr&0xFF;
    
    struct spi_ioc_transfer tr = {  
        .tx_buf = (unsigned long)tx,  
        .rx_buf = (unsigned long)rx,  
        .len = size+4,  
        .delay_usecs = delay,  
        .speed_hz = speed,  
        .bits_per_word = bits,  
    };  
  
    ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);  
    if (ret < 1)  
        pabort("can't send spi message");  
        
    for(i=0;i>16;
    
    write_en(spi_fd);
   	while(read_reg1(spi_fd)&0x01==0x01);
   	
    struct spi_ioc_transfer tr = {  
        .tx_buf = (unsigned long)tx,  
        .rx_buf = (unsigned long)rx,  
        .len = 4,  
        .delay_usecs = delay,  
        .speed_hz = speed,  
        .bits_per_word = bits,  
    }; 
    
     ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);  
    if (ret < 1)  
        pabort("can't send spi message"); 
        
     while(read_reg1(spi_fd)&0x01==0x01);     
} 


static void write_data_page(int addr,char *tx_buff,int size)  
{  
    int ret,i;  
    uint8_t rx[256+4]; 
    char tx[256+4];
    tx[0] =0x02; 
    tx[1]=(addr&0xFF0000)>>16;
    tx[2]=(addr&0xFF00)>>8;
    tx[3]=addr&0xFF;
    
    write_en(spi_fd);
    for(i=0;i<256;i++)
    {
    	tx[4+i]=tx_buff[i];
    }
    
    struct spi_ioc_transfer tr = {  
        .tx_buf = (unsigned long)tx,  
        .rx_buf = (unsigned long)rx,  
        .len = size+4,  
        .delay_usecs = delay,  
        .speed_hz = speed,  
        .bits_per_word = bits,  
    };  
  
    ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);  
    if (ret < 1)  
        pabort("can't send spi message");  
        
    while(read_reg1(spi_fd)&0x01==0x01);
}   
  

  
  
static void print_usage(const char *prog)  
{  
    printf("Usage: %s [-DsbdlHOLC3]\n", prog);  
    puts("  -D --device   device to use (default /dev/spidev1.1)\n"  
         "  -s --speed    max speed (Hz)\n"  
         "  -d --delay    delay (usec)\n"  
         "  -b --bpw      bits per word \n"  
         "  -r --read     read img \n" 
         "  -w --writ     write img \n" 
         "  -n --number   Number of bytes read or written \n" 
         "  -l --loop     loopback\n"  
         "  -H --cpha     clock phase\n"  
         "  -O --cpol     clock polarity\n"  
         "  -L --lsb      least significant bit first\n"  
         "  -C --cs-high  chip select active high\n"  
         "  -3 --3wire    SI/SO signals shared\n");  
    exit(1);  
}  
  
static void parse_opts(int argc, char *argv[])  
{  
    while (1) {  
        static const struct option lopts[] = {  
            { "device",  1, 0, 'D' },  
            { "speed",   1, 0, 's' },  
            { "delay",   1, 0, 'd' },  
            { "bpw",     1, 0, 'b' },
            { "read",    1, 0, 'r' }, 
            { "write",   1, 0, 'w' },  
            { "number",  1, 0, 'n' }, 
            { "loop",    0, 0, 'l' },  
            { "cpha",    0, 0, 'H' },  
            { "cpol",    0, 0, 'O' },  
            { "lsb",     0, 0, 'L' },  
            { "cs-high", 0, 0, 'C' },  
            { "3wire",   0, 0, '3' },  
            { "no-cs",   0, 0, 'N' },  
            { "ready",   0, 0, 'R' }, 
            
            { NULL, 0, 0, 0 },  
        };  
        int c;  
  
        c = getopt_long(argc, argv, "D:s:d:b:r:w:n:lHOLC3NR", lopts, NULL);  
  
        if (c == -1)  
            break;  
  
        switch (c) {  
        case 'D':  
            device = optarg;  
            break;  
        case 's':  
            speed = atoi(optarg);  
            break;  
        case 'd':  
            delay = atoi(optarg);  
            break;  
        case 'b':  
            bits = atoi(optarg);  
            break;  
        case 'r':
        		read_write_flg =1;  
            file_name =optarg;  
            printf("file %s\n",file_name);
            break; 
        case 'w':
        		read_write_flg =2;   
            file_name = optarg;   
            break; 
        case 'n':  
            number_byte = atoi(optarg);  
            break; 
        case 'l':  
            mode |= SPI_LOOP;  
            break;  
        case 'H':  
            mode |= SPI_CPHA;  
            break;  
        case 'O':  
            mode |= SPI_CPOL;  
            break;  
        case 'L':  
            mode |= SPI_LSB_FIRST;  
            break;  
        case 'C':  
            mode |= SPI_CS_HIGH;  
            break;  
        case '3':  
            mode |= SPI_3WIRE;  
            break;  
        case 'N':  
            mode |= SPI_NO_CS;  
            break;  
        case 'R':  
            mode |= SPI_READY;  
            break;  
        default:  
            print_usage(argv[0]);  
            break;  
        }  
    }  
} 


void write_img()
{
	FILE *file = fopen(file_name,"rb");
	if(file==0)
	{
		printf("open error for \"%s\"", file_name); 
		return;
	}
    
   	//擦除块
   	int i;
   	printf("Eraseing...\n"); 
        for (i = 0; i < (number_byte/64/1024); i++) { 
    		BlockErase64k(i*64*1024);
    		printf("Block Erase for %d block %dkB-%dkB\n\33[1A", i,i*64,(i+1)*64); 
        }
        printf("\nErase finish!\n"); 
    
        printf("writing...\n");
        //给芯片编程
  	char buff_data[256];
   	for (i = 0; i < (number_byte/256); i++) {  
   		 
        fread(&buff_data,1,256,file);      
        write_data_page(i*256,buff_data,256); 
        if(i%256==0)   
		    	printf("%dkB\n\33[1A", i*256/1024); 
    } 
		 
    fclose(file);
    write_dis();
    
    printf("\nwrite finish!\n");
}

void read_img()
{
    	FILE *file = fopen(file_name,"wb");
	if(file==0)
	{
	    printf("open error for \"%s\"", file_name); 
	    return;
	}
	printf("reading...\n"); 
        char buff_data[256];
  	int i;
   	for (i = 0; i < (number_byte)/256; i++) {  
        read_date(i*256,buff_data,256);
        fwrite(&buff_data,1,256,file);
		   	if(i%256==0)   
		    	printf("%dkB\n\33[1A", i*256/1024); 	
	    	
    } 
    fclose(file);
    write_dis();
    printf("\nread finish!\n");
}  
  
int main(int argc, char *argv[])  
{  
    int ret = 0;  
     
    int i;
    char aa[256]; 
  
    parse_opts(argc, argv);  
  
    spi_fd = open(device, O_RDWR);  
    if (spi_fd < 0)  
        pabort("can't open device");  
  
    /* 
     * spi mode 
     */  
    ret = ioctl(spi_fd, SPI_IOC_WR_MODE, &mode);  
    if (ret == -1)  
        pabort("can't set spi mode");  
  
    ret = ioctl(spi_fd, SPI_IOC_RD_MODE, &mode);  
    if (ret == -1)  
        pabort("can't get spi mode");  
  
    /* 
     * bits per word 
     */  
    ret = ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &bits);  
    if (ret == -1)  
        pabort("can't set bits per word");  
  
    ret = ioctl(spi_fd, SPI_IOC_RD_BITS_PER_WORD, &bits);  
    if (ret == -1)  
        pabort("can't get bits per word");  
  
    /* 
     * max speed hz 
     */  
    ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);  
    if (ret == -1)  
        pabort("can't set max speed hz");  
  
    ret = ioctl(spi_fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);  
    if (ret == -1)  
        pabort("can't get max speed hz");  
  
    printf("spi mode: %d\n", mode);  
    printf("bits per word: %d\n", bits);  
    printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);  
       
    read_id();
    
    //write
    if(read_write_flg==1)
    {
    		read_img();
    }
    else if(read_write_flg==2)
    {
    		write_img();		
    }
    return ret;  
}

编译执行:gcc spi-w25q64.c -o spi-w25q64

编译生成:spi-w25q64

应用使用方法:

   1. 读取数据:sudo ./spi-w25q64 -r w25q64.img -n 8388608

       -r 跟的参数是将读取的数据保存成w25q64.img文件 

        -n 跟的参数是要读多少字节

树莓派spi读写取w25q64芯片_第4张图片

上图“40 17”  是读到的芯片id。

  2.芯片编程:sudo ./spi-w25q64 -w w25q64.img -n 8388608

    

       -r 跟的参数是将w25q64.img文件 中的数据写入芯片中。

        -n 跟的参数是要读多少字节。


树莓派spi读写取w25q64芯片_第5张图片

 
  

可下载源码:https://download.csdn.net/download/xiaopanpanpanpan/10337072

你可能感兴趣的:(spi,flash,树莓派3)