Transferir dados de uma memória flash para outra memória flash

Olá, bom dia.

Estou trabalhando em um projeto onde eu preciso clonar uma memória flash utilizando o Arduino. O grande problema está no fato de as duas memórias possuírem paginações diferentes. A memória que eu preciso copiar os dados é uma Wibond 25Q32FCIG1522 e a memória para a qual eu preciso transferir esses dados é a MxIc Mx25L3206E. Como a paginação das duas memórias é diferente, em primeira instância eu tratei de fazer o código varrendo as memórias bit a bit. Ao abrir o Monitor Serial eu consigo ver que a leitura está funcionando, mas a escrita na segunda memória não funciona. A seguir estou enviando o código que estou utilizando para ler e escrever. 


#include <SPI.h>
// SS: pin 10
// MOSI: pin 11
// MISO: pin 12
// SCK: pin 13

#define SS 10
#define MOSI 11
#define MISO 12
#define SCK 13
#define SS2 9

// WinBond flash commands
#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

/*
* These global variables enable assembly of the user serial
* input command.
*/
boolean g_command_ready(false);
String g_command;

/*
* print_page_bytes() is a simple helperf function that formats 256
* bytes of data into an easier to read grid.
*/

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, "%02x", page_buffer[i * 16 + j]);
Serial.print(buf);
}
Serial.println();
}
}

/*
================================================================================
User Interface Routines
The functions below map to user commands. They wrap the low-level calls with
print/debug statements for readability.
================================================================================
*/

/*
* The JEDEC ID is fairly generic, I use this function to verify the setup
* is working properly.
*/
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: %02xh\nMemory Type: %02xh\nCapacity: %02xh",
b1, b2, b3);
Serial.println(buf);
Serial.println("Ready");
}

//void chip_erase(void) {
// Serial.println("command: chip_erase");
// _chip_erase();
// Serial.println("Ready");
//}

byte bufferMemoria[256];
void read_page(unsigned int page_number) {
char buf[80];
sprintf(buf, "command: read_page(%04xh)", page_number);
Serial.println(buf);
//byte page_buffer[256];
_read_page(page_number,bufferMemoria);
print_page_bytes(bufferMemoria);
Serial.println("Ready");
}

void read_all_pages(void) {
Serial.println("command: read_all_pages");
byte page_buffer[256];
for (int i = 0; i < 4194304; ++i) {
//for (int i = 0; i < 4096; ++i) {
_read_page(i, page_buffer);
print_page_bytes(page_buffer);
}
Serial.println("Ready");
}

void write_byte(word page, byte offset, byte databyte) {
char buf[80];
sprintf(buf, "command: write_byte(%04xh, %04xh, %02xh)", page, offset, databyte);
Serial.println(buf);
byte page_data[256];
_read_page(page, page_data);
page_data[offset] = databyte;
_write_page(page, page_data);
Serial.println("Ready");
}

/*
================================================================================
Low-Level Device Routines
The functions below perform the lowest-level interactions with the flash device.
They match the timing diagrams of the datahsheet. They are called by wrapper
functions which provide a little more feedback to the user. I made them stand-
alone functions so they can be re-used. Each function corresponds to a flash
instruction opcode.
================================================================================
*/

/*
* See the timing diagram in section 9.2.35 of the
* data sheet, "Read JEDEC ID (9Fh)".
*/
void _get_jedec_id(byte *b1, byte *b2, byte *b3) {
digitalWrite(SS, HIGH);
digitalWrite(SS, LOW);
SPI.transfer(WB_JEDEC_ID);
*b1 = SPI.transfer(0); // manufacturer id
*b2 = SPI.transfer(0); // memory type
*b3 = SPI.transfer(0); // capacity
digitalWrite(SS, HIGH);
not_busy();
}

/*
* See the timing diagram in section 9.2.26 of the
* data sheet, "Chip Erase (C7h / 06h)". (Note:
* either opcode works.)
*/
void _chip_erase(void) {
digitalWrite(SS, HIGH);
digitalWrite(SS, LOW);
SPI.transfer(WB_WRITE_ENABLE);
digitalWrite(SS, HIGH);
digitalWrite(SS, LOW);
SPI.transfer(WB_CHIP_ERASE);
digitalWrite(SS, HIGH);
/* See notes on rev 2
digitalWrite(SS, LOW);
SPI.transfer(WB_WRITE_DISABLE);
digitalWrite(SS, HIGH);
*/
not_busy();
}

/*
* See the timing diagram in section 9.2.10 of the
* data sheet, "Read Data (03h)".
*/
void _read_page(word page_number, byte *page_buffer) {
digitalWrite(SS, HIGH);
digitalWrite(SS, LOW);
SPI.transfer(WB_READ_DATA);
// Construct the 24-bit address from the 16-bit page
// number and 0x00, since we will read 256 bytes (one
// page).
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(0);
}
digitalWrite(SS, HIGH);
not_busy();
}

/*
* See the timing diagram in section 9.2.21 of the
* data sheet, "Page Program (02h)".
*/
void _write_page(word page_number, byte *page_buffer) {
digitalWrite(SS2, HIGH);
digitalWrite(SS2, LOW);
SPI.transfer(WB_WRITE_ENABLE);
digitalWrite(SS2, HIGH);
digitalWrite(SS2, 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(SS2, HIGH);
/* See notes on rev 2
digitalWrite(SS, LOW);
SPI.transfer(WB_WRITE_DISABLE);
digitalWrite(SS, HIGH);
*/
not_busy();
}

/*
* not_busy() polls the status bit of the device until it
* completes the current operation. Most operations finish
* in a few hundred microseconds or less, but chip erase
* may take 500+ms. Finish all operations with this poll.
*
* See section 9.2.8 of the datasheet
*/
void not_busy(void) {
digitalWrite(SS, HIGH);
digitalWrite(SS, LOW);
SPI.transfer(WB_READ_STATUS_REG_1);
while (SPI.transfer(0) & 1) {};
digitalWrite(SS, HIGH);
}

/*
* This handy built-in callback function alerts the UNO
* whenever a serial event occurs. In our case, we check
* for available input data and concatenate a command
* string, setting a boolean used by the loop() routine
* as a dispatch trigger.
*/
void serialEvent() {
char c;
while (Serial.available()) {
c = (char)Serial.read();
if (c == ';') {
g_command_ready = true;
}
else {
g_command += c;
}
}
}

void setup(void) {
SPI.begin();
SPI.beginTransaction(SPISettings(9600, MSBFIRST, SPI_MODE3));
SPI.setDataMode(0);
SPI.setBitOrder(MSBFIRST);
Serial.begin(9600);
Serial.println("");
Serial.println("Ready");
}

/*
* loop() dispatches the commands compiled by the serialEvent
* parser callback. Some commands take multiple arguments, so
* I have to split up the strings with some messy manipulation.
*/
void loop(void) {

for(int i=0; i< 4194304 ; i++){
read_page(i);
_write_page(i,bufferMemoria);
}


// if (g_command_ready) {
// if (g_command == "get_jedec_id") {
// get_jedec_id();
// }
// else if (g_command == "chip_erase") {
// chip_erase();
// }
// else if (g_command == "read_all_pages") {
// read_all_pages();
// }
// // A one-parameter command...
// else if (g_command.startsWith("read_page")) {
// int pos = g_command.indexOf(" ");
// if (pos == -1) {
// Serial.println("Error: Command 'read_page' expects an int operand");
// } else {
// word page = (word)g_command.substring(pos).toInt();
// read_page(page);
// }
// }
// // A three-parameter command..
// else if (g_command.startsWith("write_byte")) {
// word pageno;
// byte offset;
// byte data;
//
// String args[3];
// for (int i = 0; i < 3; ++i) {
// int pos = g_command.indexOf(" ");
// if (pos == -1) {
// Serial.println("Syntax error in write_byte");
// goto done;
// }
// args[i] = g_command.substring(pos + 1);
// g_command = args[i];
// }
// pageno = (word)args[0].toInt();
// offset = (byte)args[1].toInt();
// data = (byte)args[2].toInt();
// write_byte(pageno, offset, data);
// }
// else {
// Serial.print("Invalid command sent: ");
// Serial.println(g_command);
// }
//done:
// g_command = "";
// g_command_ready = false;
// }
}

Como esse procedimento não funcionou, agora eu estou tentando primeiramente apagar uma memória Winbond e transferir para ela os dados de outra memória Winbond que esteja funcionando. Mas acredito que eu esteja fazendo o procedimento da maneira errada pois a memória não está sendo apagada. 

Alguém poderia me ajudar? Obrigada.

Exibições: 219

Responder esta

Respostas a este tópico

Boa tarde MO.
Só ajudo amigos que não colam sketch na área de texto do tópico.
Sou velho e ranzinza.
Se remover o code, e anexar como arquivo, posso reconsiderar minha decisão de não ajudá-lo.
Leia: http://labdegaragem.com/forum/topics/sugest-o-de-como-postar
Rui

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço