网络故障(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
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);
*b2 = SPI.transfer(0xFF);
*b3 = SPI.transfer(0xFF);
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);
}
}

串行端口将数据转发到SPI 每次读取一个字节,但读取速度要慢256个字节,然后通过spi写入闪存,然后通过指定文件大小来确定闪存是否结束。少于一页的剩余数据为0xFF。由于某些BootLoader文件的末尾为0xFF,因此您可以指定文件大小以提前结束写入过程,从而节省时间。可以通过winhex查看要写入的二进制文件。 写入页面后,请阅读此页面并检查写入的数据。如果出现错误,程序将返回并停止运行。 由于是从串行端口逐字节读取的,因此串行端口的波特率不应太大,否则会丢失数据。 9600bps更合适。调试时,您可以将FILE_SIZE更改为256,并删除打印页面数据上的注释。 如果没有问题,请使用通过sscom发送文件的功能。擦除芯片几秒钟后,单击发送文件,串行端口将输出当前写入页面的序列号。 #define FILE_SIZE 524288
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));
_write_page(currentPage, page);
delay(10);
byte page_temp[256];
_read_page(currentPage, 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));
_write_page(currentPage, page);
delay(10);
byte page_temp[256];
_read_page(currentPage, 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
当今,越来越多的业务应用运行于网络架构之上,保障网络的持续、高效、安全的运行,成为网络管理者面临的巨大挑战。 |