欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

Arduino作为编程器读写BIOS、bootloader、uboot或者breed

发布时间:2023/12/16 编程问答 44 豆豆
生活随笔 收集整理的这篇文章主要介绍了 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的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。