设为首页收藏本站

极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 494|回复: 6

刷写AMI BIOS成功

  [复制链接]
发表于 2017-1-7 15:08:50 | 显示全部楼层 |阅读模式
       最近休息,升级老电脑,换4核CPU,刷自己修改后的bios,结果刷出了一点小故障,主板默认写保护,用了N多种方法,花了几天时间,虽然搞好了,但是,还是想自己打造一个编程器,以后想刷就刷。
       查看主板bios芯片型号为25Q80P,上网查芯片资料发现与arduino的ISP编程接口功能相近,用arduino再配上相应的程序应该能做到;于是再次上网搜索看有没有制作成功的例子,找到了两遍博文,提供了方法,但都没有提到最后是否成功。其中一位博客离成功一步之遥,结果板子烧了。
       查看硬件配置,应该是5V直接3.3V,电流大,arduino板子承受不了,给烧了。
       于是我在信号间串联1个电阻,本来准备用510欧的电阻,但手头没有,找了4个1K的,用孔孔板焊好后,与arduino连接,成功的将文件写入spi_flash芯片。先上图:
      
       1_7_3.GIF 1_7_2.GIF 1_7_1.GIF
回复

使用道具 举报

 楼主| 发表于 2017-1-7 15:44:21 | 显示全部楼层
下面是arduinoe原代码:
/*************** arduino SPI_flash编程器(烧录器)*******************
    communication with W25Q80BV (1 MBYTE SPI FLASH) using Arduino Pro Mini 3.3V/8MHz
    Reference: http://www.instructables.com/id/How-to-Design-with-Discrete-SPI-Flash-Memory/?ALLSTEPS
    Reference2: http://www.cnblogs.com/zlbg/p/4246721.html
    wuernuer:http://blog.csdn.net/wuernuer/article/details/50759523
*/

// arduino(与spi_falsh连接) pins 10 (CS), 11 (MOSI), 12 (MISO),  13 (SCK)

/*
* 使用Arduino作为编程器将bios写入spi_flash
* 注意bios文件不要超过芯片存储容量
* 理论上支持所有spi_flash(EEPROM)
* 测试电脑:七彩虹C.G41H D3 V23主板,L5420至强四核CPU(771硬改),2*2G DDR3 1333内存
*           官方1003_bios,文件大小1M
*/

#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

// bios最后四个字节,用于判断写入已经结束
// 我们可以使用winhex打开bios文件查看最后四个字节
static char END_CHARS[4] = {0x3B, 0x54, 0x05, 0x10};

void setup()
{
    SPI.begin();
    SPI.setDataMode(SPI_MODE0);
    SPI.setBitOrder(MSBFIRST);
    Serial.begin(115200);

    ReadID();
      
    EraseChip();    // 擦除flash
    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];             // 每页有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 {        // 如果读取不足一页证明已经到文件末尾了,这个时候数据要全部写入flash
                for(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
    // 然后保存到一个文档和原bios作对比看看写入是否正确
    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 data
    digitalWrite(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();
}
回复 支持 反对

使用道具 举报

发表于 2017-1-7 17:13:25 | 显示全部楼层
整一个编程器啊。很强,想楼主学习。电脑上的软件和arduino的通信的具体协议资料是否也可以提供?
回复 支持 反对

使用道具 举报

发表于 2017-1-7 20:05:28 | 显示全部楼层
20年前就用WINFLASH刷BIOS了,大多可刷,楼主可以试试。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-1-7 20:21:15 | 显示全部楼层
catnull 发表于 2017-1-7 17:13
整一个编程器啊。很强,想楼主学习。电脑上的软件和arduino的通信的具体协议资料是否也可以提供?

刚试过,arduino IDE 1.0.5_r2就行,只要有SPI.h库文件就好,串口发送用的是sscom,网上很多。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-1-7 22:33:40 | 显示全部楼层
msold5 发表于 2017-1-7 20:05
20年前就用WINFLASH刷BIOS了,大多可刷,楼主可以试试。

我这是arduino组成的硬件编程器,与windows下的winflash刷新升级软件不是一个概念
回复 支持 反对

使用道具 举报

发表于 2017-1-12 08:50:01 | 显示全部楼层
hbyczcp 发表于 2017-1-7 20:21
刚试过,arduino IDE 1.0.5_r2就行,只要有SPI.h库文件就好,串口发送用的是sscom,网上很多。

这个就是一个定制能力非常强悍的编程器了。理论上,只有flash芯片手册可以搞到,读写控制器的协议可以知道,那么就能进行编程。感谢楼主的无私分享。
回复 支持 反对

使用道具 举报

高级模式  
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊 ( 浙ICP备09023225号  

GMT+8, 2017-4-27 05:26 , Processed in 0.099313 second(s), 12 queries , File On.

Powered by Discuz! X3.3 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表