After more reading I opted to go for the level shifter breakout board (pack of five off Ebay). It appears to work as advertised.
I first tried the IDE SD library and it reports “…initialization failed…” But, it looks like that won’t work anyway since the chip needs to be formatted.
Without touching the wiring I then made the following attempts:
Tried the SPI demo in the tutorial. This also did not recognize the EEPROM being present so I;
Worked up a small sketch to demo some basic commands, just reading/writing the config. and status registers.
/* This short sketch reads and prints the eeprom product info
two times. First time is via command 0xAB and requires addition
of three dummy bytes in transmission. Second way is via JEDEC
command 0x9F, requiring no additional bytes transmitted.
Next is read and printed the chip's status register
Followed by the configuration register
*/
#include <SPI.h>
#include "PM25LV040_INSTRUCTIONS.h"
#define CS_PIN 10
#ifndef PIN_LED
#define PIN_LED 13
#endif
byte inBuffer[9]; // eeprom data in
void setup() {
Serial.begin(115200);
Serial.println(__FILE__);
pinMode(PIN_LED, OUTPUT);
pinMode(CS_PIN, OUTPUT);
digitalWrite(CS_PIN, HIGH);
SPI.begin();
}
void read_eeprom(unsigned int num_bytes) {
unsigned int addr;
byte resp;
digitalWrite(CS_PIN, LOW);
/* transmit read id command with required 3 dummy bytes */
SPI.transfer(SPI_EEPROM_RDID);
SPI.transfer(0x00);
SPI.transfer(0x00);
SPI.transfer(0x00);
for (addr = 0; addr < num_bytes; addr++) {
resp = SPI.transfer(0xff);
Serial.println(resp, 16); // DISPLAY a column in hex notation
/* success! prints:
0x9d, 1st mfr ID byte;
0x7e, device ID (Pm25LV040);
0x7f, 2nd mfr ID byte as predicted in datasheet.
*/
}
digitalWrite(CS_PIN, HIGH);
}
void read_JEDEC_ID(unsigned int num_bytes) {
unsigned int addr;
digitalWrite(CS_PIN, LOW);
/* transmit read id command - jedec does not require 3 dummy bytes */
SPI.transfer(SPI_EEPROM_JEDEC_ID);
for (addr = 0; addr < num_bytes; addr++) {
inBuffer[addr] = SPI.transfer(0xff);
}
Serial.print("mfr id1 = ");
Serial.println(inBuffer[1], 16);
Serial.print("mfr id2 = ");
Serial.println(inBuffer[0], 16);
Serial.print("device id = ");
Serial.println(inBuffer[2], 16);
digitalWrite(CS_PIN, HIGH);
}
void write_status_reg(unsigned int num_bytes) {
digitalWrite(CS_PIN, LOW);
/* transmit command */
SPI.transfer(SPI_EEPROM_WREN);
digitalWrite(CS_PIN, HIGH);
delay(10);
digitalWrite(CS_PIN, LOW);
SPI.transfer(SPI_EEPROM_WRSR);
SPI.transfer(0);
digitalWrite(CS_PIN, HIGH);
}
void read_Status_Reg() {
byte resp;
digitalWrite(CS_PIN, LOW);
SPI.transfer(SPI_EEPROM_RDSR); // returns one byte
resp = SPI.transfer(0xff);
Serial.println("\nStatus Register");
Serial.print("bit 0 - wip\t");
Serial.println(bitRead(resp, 0));
Serial.print("bit 1 - wel\t");
Serial.println(bitRead(resp, 1));
Serial.print("bit 2 - BP0\t");
Serial.println(bitRead(resp, 2));
Serial.print("bit 3 - BP1 =\t");
Serial.println(bitRead(resp, 3));
Serial.print("bit 4 - BP2 =\t");
Serial.println(bitRead(resp, 4));
Serial.print("bit 5 -\t");
Serial.println(bitRead(resp, 5));
Serial.print("bit 6 -\t");
Serial.println(bitRead(resp, 6));
Serial.print("bit 7 - SWRD\t");
Serial.println(bitRead(resp, 7));
digitalWrite(CS_PIN, HIGH);
}
void loop() {
digitalWrite(PIN_LED, LOW);
if (Serial.read() == 'D') {
digitalWrite(PIN_LED, HIGH);
read_eeprom(3);
read_JEDEC_ID(3);
read_Status_Reg();
write_status_reg(0); // clear write protect bits
read_Status_Reg();
}
}
and associated header file with defines for the EEPROM command set.
/* Pm25LV040 instruction set - for 512k SPI EEPROM
*/
#define SPI_EEPROM_WREN 0x06 // write enable command
#define SPI_EEPROM_WRDI 0x04 // WRITE DISABLE
#define SPI_EEPROM_RDSR 0x05 // read the status register, receive one byte
#define SPI_EEPROM_WRSR 0x01 // write the status register, append one byte
#define SPI_EEPROM_READ 0x03 // read data normal speed, append three byte address,
// receive one byte, repeatable
#define SPI_EEPROM_FAST_READ 0x0B // read data fast mode
#define SPI_EEPROM_RDID 0xab // read mfr and product ID
#define SPI_EEPROM_JEDEC_ID 0x9F // read mfr and product by JEDEC ID command
#define SPI_EEPROM_PAGE_PROG 0x02 // page program data bytes into memory, append
// three byte address, receive up to 256 bytes
#define SPI_EEPROM_RDCR 0xA1 // read the configuration register, receive one byte
#define SPI_EEPROM_WRCR 0xF1 // write the configuration register, append one byte
#define SPI_EEPROM_SECTOR_ERASE 0xD7 // sector erase command, append three byte address
#define SPI_EEPROM_BLOCK_ERASE 0xD8 // block erase, append three byte address
#define SPI_EEPROM_CHIP_ERASE 0xC7 // chip erase
Once that worked it showed that the three Block Protect bits were all set, effectively making the entire memory write protected. I added a function to clear these bits and a subsequent call to the status register function shows success.
9D
7E
7F
mfr id1 = 9D
mfr id2 = 7F
device id = 7E
Status Register
bit 0 - wip 0
bit 1 - wel 0
bit 2 - BP0 0
bit 3 - BP1 = 0
bit 4 - BP2 = 0
bit 5 - 0
bit 6 - 0
bit 7 - SWRD 0
Status Register
bit 0 - wip 1
bit 1 - wel 1
bit 2 - BP0 0
bit 3 - BP1 = 0
bit 4 - BP2 = 0
bit 5 - 0
bit 6 - 0
bit 7 - SWRD 0
Based on my limited knowledge this chip basically follows the ‘standard’ SPI EEPROM conventions as to command set and status register bit placement so I *believe *it’s getting the correct instructions and is returning expected data.
Still the SPIEEPROM tutorial code would not recognize the chip so I loaded this (GitHub - kbondarev/spieeprom: Arduino library which helps to read and write to an EEPROM over SPI) sketch which fills a 256 byte buffer with the for() loop iterator, sends buffer to the chip, then reads back and displays the just-written data. I expect to see the Value numbers matching the Address numbers. It sorta works ( the original data was all 255s ) in that the sketch will read but the data doesn’t match (sample).
Address:|241| - Value:|240|
Address:|242| - Value:|240|
Address:|243| - Value:|242|
Address:|244| - Value:|244|
Address:|245| - Value:|0|
Address:|246| - Value:|0|
Address:|247| - Value:|2|
Address:|248| - Value:|0|
Address:|249| - Value:|0|
Address:|250| - Value:|0|
Address:|251| - Value:|2|
Address:|252| - Value:|4|
Address:|253| - Value:|8|
Address:|254| - Value:|8|
Address:|255| - Value:|10|
Address:|0| - Value:|0|
Address:|1| - Value:|0|
Address:|2| - Value:|0|
Address:|3| - Value:|0|
Address:|4| - Value:|4|
Address:|5| - Value:|0|
Address:|6| - Value:|0|
Address:|7| - Value:|0|
Address:|8| - Value:|0|
Address:|9| - Value:|0|
May be relevant: It’s not random, this same sequence of written values repeats over and over, even after a reset.
My only other experience with SPI was the basic experiments with 74HC SIPO, PISO registers. Any ideas where I should be looking?