|
楼主 |
发表于 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();
}
|
|