網絡故障(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(檢查程序是否正確),芯片擦除,頁面編程(寫入數據)和數據讀。〝祿炞C)三個命令。 



程序功能功能 #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
當今,越來越多的業務應用運行于網絡架構之上,保障網絡的持續、高效、安全的運行,成為網絡管理者面臨的巨大挑戰。 |