Arduino作为编程器读写BIOS、bootloader、uboot或者breed
生活随笔
收集整理的這篇文章主要介紹了
Arduino作为编程器读写BIOS、bootloader、uboot或者breed
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
極路由1S(HC5661A)刷breed刷錯了,身邊沒有編程器寫flash芯片(型號25Q128CS),因此就萌生了使用Arduino作為編程器的想法
參考了ZLBG這篇文章寫得很不錯
都是標準ISP協議,其他flash可以參考讀寫
電路圖請參考ZLBG的博客文章,我貼一下Arduino接線
Arduino代碼如下:
/*communication with W25Q80BV (1 MBYTE SPI FLASH) using Arduino Pro Mini 3.3V/8MHzReference: http://www.instructables.com/id/How-to-Design-with-Discrete-SPI-Flash-Memory/?ALLSTEPSReference2: http://www.cnblogs.com/zlbg/p/4246721.html */// the SPI bus uses pins 10 (SS), 11 (MOSI), 12 (MISO), and 13 (SCK)/** * 使用Arduino作為編程器將uboot寫入flash(EEPROM) * 注意uboot不要超過芯片存儲容量 * 理論上支持所有EEPROM * * 測試機型:極路由1S(HC5661A),刷入breed */#include <SPI.h>#define READ_JEDEC_ID 0x9F #define READ_STATUS_1 0x05 #define READ_DATA 0x03 #define WRITE_ENABLE 0x06 #define PAGE_PROGRAM 0x02 #define CHIP_ERASE 0xC7// uboot最后四個字節,用于判斷寫入已經結束 // 我們可以使用winhex打開uboot文件查看最后四個字節 static char END_CHARS[4] = {0x3B, 0x54, 0x05, 0x10};void setup() {SPI.begin();SPI.setDataMode(SPI_MODE0);SPI.setBitOrder(MSBFIRST);Serial.begin(115200);ReadID(); // 擦除flashEraseChip();Serial.println("inited"); }// 檢測是否寫入完成,當最后四個字節和結束字節一樣的時候寫入結束 bool isEnd(char check[4]) {if (check[0] == END_CHARS[0] && check[1] == END_CHARS[1] && check[2] == END_CHARS[2] && check[3] == END_CHARS[3]){return true;}return false; }char buffer[64]; // 串口一次最多64字節 char page[256]; // eeprom每頁有256字節 int currentPos = 0; // 當前頁當前位置 int currentPage = 0; // 當前頁數 bool writed = false; // 寫入完成標記 bool start = false; // 開始寫入標記 bool printed = false; // 寫入完成之后打印完成標記 void loop() {if(!writed && Serial.available() > 0) { // 如果寫入未完成我們繼續讀取串口if(!start) {start = true;Serial.println("start write");}int size = Serial.readBytes(buffer, 64);if(size >= 0) {if(size == 64) {if(currentPos + size == 256) { // 當讀取恰好滿一頁時候我們寫入flash一頁for(int i=0; i<64; i++) {page[currentPos + i] = buffer[i];}WritePage(currentPage, page, 256);memset(page, 0, 256*sizeof(byte));currentPos = 0;currentPage++;// 這個時候要判斷是不是末尾,是的話我們完成寫入操作char check[4] = {page[252], page[253], page[254], page[255]};if(isEnd(check)) {Serial.println("WRITE FINISH!!!");writed = true;}} else {for(int i=0; i<64; i++) {page[currentPos + i] = buffer[i];}currentPos += 64;}} else { // 如果讀取不足一頁證明已經到文件末尾了,這個時候數據要全部寫入flashfor(int i=0; i<size; i++) {page[currentPos + i] = buffer[i];}WritePage(currentPage, page, currentPos + size);memset(page, 0, 256*sizeof(byte));currentPos = 0;currentPage++;// 完成寫入操作Serial.println("WRITE FINISH!!!");writed = true;}// 每次讀完串口緩沖都要清零memset(buffer, 0, 64*sizeof(byte));}}// 寫完而且未打印時候我們把flash里面數據按頁讀出來// 我們可以復制黏貼串口調試助手里面的16進制數據到winhex// 然后保存到一個文檔和原uboot作對比看看寫入是否正確if(writed && !printed) {for(int i=0; i<currentPage; i++) {ReadPage(i, page, 256);for(int i = 0; i < 256; i++){Serial.print(char(page[i]));}memset(page, 0, 256*sizeof(byte));delay(20);}printed = true;} }void CheckBusy() {digitalWrite(SS, HIGH);digitalWrite(SS, LOW);SPI.transfer(READ_STATUS_1);while(SPI.transfer(0) & 0x01); digitalWrite(SS, HIGH); }void ReadID() {digitalWrite(SS, HIGH);digitalWrite(SS, LOW);SPI.transfer(READ_JEDEC_ID);byte manuID = SPI.transfer(0);byte memoType = SPI.transfer(0);byte capa = SPI.transfer(0);digitalWrite(SS, HIGH);Serial.print("Manufacturer ID: "); Serial.println(manuID, HEX);Serial.print("Memory Type: "); Serial.println(memoType, HEX);Serial.print("Capacity : "); Serial.println(capa, HEX);CheckBusy(); }void ReadPage(word pageNumber, char pageBuffer[], int length) {// pageNumber: 16-bit datadigitalWrite(SS, HIGH);digitalWrite(SS, LOW);SPI.transfer(READ_DATA);SPI.transfer((pageNumber >> 8) & 0xFF);SPI.transfer(pageNumber & 0xFF);SPI.transfer(0);for(int i = 0; i < length; i++){pageBuffer[i] = SPI.transfer(0);}digitalWrite(SS, HIGH);CheckBusy(); }void WritePage(word pageNumber, char pageBuffer[], int length) {digitalWrite(SS, HIGH);digitalWrite(SS, LOW); SPI.transfer(WRITE_ENABLE);digitalWrite(SS, HIGH);digitalWrite(SS, LOW); SPI.transfer(PAGE_PROGRAM);SPI.transfer((pageNumber >> 8) & 0xFF);SPI.transfer(pageNumber & 0xFF);SPI.transfer(0);for(int i = 0; i < length; i++){SPI.transfer(byte(pageBuffer[i]));}digitalWrite(SS, HIGH);CheckBusy(); }void EraseChip() {digitalWrite(SS, HIGH);digitalWrite(SS, LOW); SPI.transfer(WRITE_ENABLE);digitalWrite(SS, HIGH);digitalWrite(SS, LOW); SPI.transfer(CHIP_ERASE);digitalWrite(SS, HIGH);CheckBusy(); }接線完成之后打開串口調試助手sscom32,當串口顯示begin時候選擇breed文件發送到Arduino,Arduino會寫到flash,寫完之后會讀取flash剛剛寫入的數據到串口調試助手,這樣子我們可以對比寫入是否正確。注意:寫入之前建議備份flash,自己寫read保存吧我就不寫了
另外需要寫入對應起始地址的話也需要自行修改
可惜最后還是沒有救活,我焊工太差了電路板掛了
總結
以上是生活随笔為你收集整理的Arduino作为编程器读写BIOS、bootloader、uboot或者breed的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 保理业务举例说明
- 下一篇: atomic and exclusive