当前位置:萝卜系统 > 网络技术教程 > 详细页面

小米路由器如何向spi中写入文件,BootLoader莫得了

小米路由器如何向spi中写入文件,BootLoader莫得了

更新时间:2023-08-22 文章作者:未知 信息来源:网络 阅读次数:

网络故障(network failure)是指由于硬件的问题、软件的漏洞、病毒的侵入等引起网络无法提供正常服务或降低服务质量的状态。

它是做什么用的?

手边有两个路由器,一个是小米r3gv2(砖状,没有BootLoader),另一个是Phicomm K3(砖状,nand闪存中的BootLoader也不可用)。对于小米路由器,请焊接spi闪存,然后,只需使用编程器将其闪烁即可。对于PHICOMM K3,SPI闪光垫也保留在PCB上。您可以更改SPI引导,然后将CFE(一种BootLoader)闪存到nand闪存中。

不幸的是,由于这种流行病,程序员并没有被运送出去,所以我想了很久,最后想到我可以使用具有SPI功能的可编程设备来制作程序员。至于如何将文件写入spi,是不是sscom?您可以直接通过串行端口发送文件,然后在Arduino中创建一个串行端口以接收SPI写入。

SPI闪存

有许多SPI闪存,GD或Winbond品牌,其中大多数是8PIN,可以在路由器和机顶盒中随处可见。小米路由器使用128Mbit(16M)。以winbond为例,命名为W25QXX,图片如下:

在这里插入图片描述

不同品牌的此类芯片在引脚定义和读取命令方面几乎兼容。在Arduino Mega 2560中,默认情况下SPI引脚为50、51、52和53。

在这里插入图片描述

SPI读写

spi闪存的基本特征之一是必须在写入之前将其擦除。被擦除的位置是0xFF。在编写SPI Flash的过程中,我们主要使用的是读取ID(检查程序是否正确),芯片擦除,页面编程(写入数据)和数据读取(数据验证)三个命令。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

程序功能功能

#include 
#define WB_WRITE_ENABLE       0x06
#define WB_WRITE_DISABLE      0x04
#define WB_CHIP_ERASE         0xc7
#define WB_READ_STATUS_REG_1  0x05
#define WB_READ_DATA          0x03
#define WB_PAGE_PROGRAM       0x02
#define WB_JEDEC_ID           0x9f
//打印256字节的数据(16x16)
void print_page_bytes(byte* page_buffer) {
    char buf[10];
    for (int i = 0; i  16; ++i) {
        for (int j = 0; j  16; ++j) {
            sprintf(buf, "x", page_buffer[i * 16 + j]);
            Serial.print(buf);
        }
        Serial.println();
    }
}
void get_jedec_id(void) {
    Serial.println("command: get_jedec_id");
    byte b1, b2, b3;
    _get_jedec_id(&b1, &b2, &b3);
    char buf[128];
    sprintf(buf, "Manufacturer ID: xh\nMemory Type ID: xh\nCapacity ID: xh",
        b1, b2, b3);
    Serial.println(buf);
    Serial.println("Ready");
}
void chip_erase(void) {
    Serial.println("command: chip_erase");
    _chip_erase();
    Serial.println("Ready");
}
void read_page(unsigned int page_number) {
    char buf[80];
    sprintf(buf, "command: read_page(xh)", page_number);
    Serial.println(buf);
    byte page_buffer[256];
    _read_page(page_number, page_buffer);
    print_page_bytes(page_buffer);
    Serial.println("Ready");
}
void read_all_pages(void) {
    Serial.println("command: read_all_pages");
    byte page_buffer[256];
    for (int i = 0; i  4096; ++i) {
        _read_page(i, page_buffer);
        print_page_bytes(page_buffer);
    }
    Serial.println("Ready");
}
void _get_jedec_id(byte* b1, byte* b2, byte* b3) {
    digitalWrite(SS, LOW);
    SPI.transfer(WB_JEDEC_ID);
    *b1 = SPI.transfer(0xFF); // manufacturer id
    *b2 = SPI.transfer(0xFF); // memory type
    *b3 = SPI.transfer(0xFF); // capacity
    digitalWrite(SS, HIGH);
}
void _chip_erase(void) {
    digitalWrite(SS, LOW);
    SPI.transfer(WB_WRITE_ENABLE);
    digitalWrite(SS, HIGH);
    delay(10);
    digitalWrite(SS, LOW);
    SPI.transfer(WB_CHIP_ERASE);
    digitalWrite(SS, HIGH);
    delay(10);
    digitalWrite(SS, LOW);
    SPI.transfer(WB_WRITE_DISABLE);
    digitalWrite(SS, HIGH);
    not_busy();
}
void _read_page(word page_number, byte* page_buffer) {
    digitalWrite(SS, LOW);
    SPI.transfer(WB_READ_DATA);
    SPI.transfer((page_number >> 8) & 0xFF);
    SPI.transfer((page_number >> 0) & 0xFF);
    SPI.transfer(0);
    for (int i = 0; i  256; ++i) {
        page_buffer[i] = SPI.transfer(0xFF);
    }
    digitalWrite(SS, HIGH);
    not_busy();
}
void _write_page(word page_number, byte* page_buffer) {
    digitalWrite(SS, LOW);
    SPI.transfer(WB_WRITE_ENABLE);
    digitalWrite(SS, HIGH);
    delay(10);
    digitalWrite(SS, LOW);
    SPI.transfer(WB_PAGE_PROGRAM);
    SPI.transfer((page_number >> 8) & 0xFF);
    SPI.transfer((page_number >> 0) & 0xFF);
    SPI.transfer(0);
    for (int i = 0; i  256; ++i) {
        SPI.transfer(page_buffer[i]);
    }
    digitalWrite(SS, HIGH);
    
    digitalWrite(SS, LOW);
    SPI.transfer(WB_WRITE_DISABLE);
    digitalWrite(SS, HIGH);
    not_busy();
    
}
uint8_t read_status(void)
{
    digitalWrite(SS, LOW);
    SPI.transfer(WB_READ_STATUS_REG_1);
    uint8_t data = SPI.transfer(0xFF);
    digitalWrite(SS, HIGH);
    return data;
}
void not_busy(void) {
    while (read_status() & 0x01)
    {
        delay(1);
    }
}

极路由1s flash_flash怎么编程复制元件_编程器刷路由器flash

串行端口将数据转发到SPI

每次读取一个字节,但读取速度要慢256个字节,然后通过spi写入闪存,然后通过指定文件大小来确定闪存是否结束。少于一页的剩余数据为0xFF。由于某些BootLoader文件的末尾为0xFF,因此您可以指定文件大小以提前结束写入过程,从而节省时间。可以通过winhex查看要写入的二进制文件。

写入页面后,请阅读此页面并检查写入的数据。如果出现错误,程序将返回并停止运行。

由于是从串行端口逐字节读取的,因此串行端口的波特率不应太大,否则会丢失数据。 9600bps更合适。调试时,您可以将FILE_SIZE更改为256,并删除打印页面数据上的注释。

如果没有问题,请使用通过sscom发送文件的功能。擦除芯片几秒钟后,单击发送文件,串行端口将输出当前写入页面的序列号。

#define FILE_SIZE 524288 //512KB
void setup()
{
    SPI.begin();
    SPI.setDataMode(0);
    SPI.setBitOrder(MSBFIRST);
    digitalWrite(SS, HIGH);
    Serial.begin(9600);
    Serial.println("Ready");
    init_printf();
    not_busy();
    get_jedec_id();
    chip_erase();
    while (Serial.read() > 0);
}
void loop()
{
    if (!writed && Serial.available() > 0) 
    {
        bytes++;
        page[currentPos] = Serial.read();
        currentPos++;
        if (currentPos == 256) 
        {
            Serial.println("Receive Page:" + String(currentPage));
            //print_page_bytes(page);
            _write_page(currentPage, page);
            delay(10);
            byte page_temp[256];
            _read_page(currentPage, page_temp);
            //Serial.println("Read Page:" + String(currentPage));
            //print_page_bytes(page_temp);
            for (int k = 0; k  256; k++)
            {
                if (page_temp[k] != page[k])
                {
                    Serial.println("Error!");
                    return;
                }
            }
            if (bytes >= FILE_SIZE)
            {
                writed = true;
                Serial.println("WRITE FINISH!!!");
            }
            memset(page, 0xFF, 256 * sizeof(byte));
            currentPos = 0;
            currentPage++;
        }
        else if (bytes >= FILE_SIZE)
        {
            Serial.println("Receive Page:" + String(currentPage));
            //print_page_bytes(page);
            _write_page(currentPage, page);
            delay(10);
            byte page_temp[256];
            _read_page(currentPage, page_temp);
            //Serial.println("Read Page:" + String(currentPage));
            //print_page_bytes(page_temp);
            for (int k = 0; k  256; k++)
            {
                if (page_temp[k] != page[k])
                {
                    Serial.println("Error!");
                    return;
                }
            }
            writed = true;
            Serial.println("WRITE FINISH!!!");
        }
    }
    if (writed)
    {
        Serial.read();
    }
}

如果遇到不正确的写入数据,随机错误,重复错误或很多0x00,则问题的80%是电压。我使用3. 3V,操作GD Flash没问题。编写Winbond Flash。它不能被写入,并且阅读混乱。然后,在擦除闪存之后,切断芯片的电源,并且写入就可以了。


本文来自本站,转载请注明本文网址:
http://www.pc-fly.com/a/tongxingongju/article-372886-1.html


当今,越来越多的业务应用运行于网络架构之上,保障网络的持续、高效、安全的运行,成为网络管理者面临的巨大挑战。

温馨提示:喜欢本站的话,请收藏一下本站!

本类教程下载

系统下载排行

网站地图xml | 网站地图html