sosandroid / FRAM_MB85RC_I2C

Arduino library for I2C FRAM - Fujitsu MB85RC & Cypress FM24, CY15B
Other
56 stars 21 forks source link

Addressing problems #2

Closed porcao closed 7 years ago

porcao commented 7 years ago

I'm doing some tests using MB85RC16. I have managed to make the examples work perfectly. But if I include a new recording at another address he always writes at the beginning where the previous recording was made. This seeming it uses not the last address, and always use the same address for any recording I do. I tried now record two numbers in two memory locations. But every recording is made and read from the same address. If we try to read one byte, for example, a completely different place it always returns me first byte that is written at the beginning of the memory. Ex.: fram.readByte (0x50, & readValue); Tks

porcao commented 7 years ago

Example:

include < Wire.h >

include < math.h >

include < FRAM_MB85RC_I2C.h >

uint16_t writeaddress = 0x10; uint16_t testaddress = 0x50; uint16_t testaddress2 = 0x70;

//Creating object for FRAM chip FRAM_MB85RC_I2C fram;

void setup() { uint8_t readvalue = 0xFF;

Serial.begin(115200); Serial.println("Starting..."); while (!Serial) ; Wire.begin();

fram.begin(); byte result;

result = fram.readByte(writeaddress, &readvalue); if (result == 0) Serial.println("Read Done"); if (result != 0) Serial.println("Read failed"); Serial.print("Leitura:"); Serial.println(readvalue, DEC);

result = fram.writeByte(writeaddress, 77); if (result == 0) Serial.println("Write Done"); if (result != 0) Serial.println("Write failed");

result = fram.writeByte(testaddress, 44); if (result == 0) Serial.println("Write Done"); if (result != 0) Serial.println("Write failed");

result = fram.readByte(writeaddress, &readvalue); if (result == 0) Serial.println("Read Done"); if (result != 0) Serial.println("Read failed"); Serial.print("Leitura:"); Serial.println(readvalue, DEC);

result = fram.readByte(testaddress2, &readvalue); if (result == 0) Serial.println("Read Done"); if (result != 0) Serial.println("Read failed"); Serial.print("Leitura:"); Serial.println(readvalue, DEC); }

void loop() { // nothing to do }

sosandroid commented 7 years ago

Hi, Thanks for sharing your issue. However, this is not an issue. The source of this behavior comes from the device itself.

I designed the lib for devices with 3 bits salve address and 16 bits memory address.

MB85RC16 has no slave adresses and 11 bits memory addresses. The 3 upper bits of the memory address are used as the "salve address" to match the I2C protocol. The lib is not compatible with this device.

To address this device, this lib has to be modified widely. I do not have the time nor testing devices to do it right now (not even in the coming months) but if you want to try, I can help you a bit.

To better understand the difference between the lib behavior and what the device expects, please have a look on page 8 of datasheets for MB85RC256V and MB85RC16.

http://edevice.fujitsu.com/fj/DATASHEET/e-ds/MB85RC256V-DS501-00017-5v1-E.pdf http://edevice.fujitsu.com/fj/DATASHEET/e-ds/MB85RC16-DS501-00001-11v0-E.pdf

sosandroid commented 7 years ago

To make it easier, the things to modify are :

This should be enougth

porcao commented 7 years ago

My friend! Thank you very much! I managed to work perfectly. Congratulations for the great work! And again: thank you!

sosandroid commented 7 years ago

Fell free to share your code in order to improve the whole lib. This can be usefull to others :)

porcao commented 7 years ago

In fact I rushed a little. Apparently still have a problem. I need to set up a new code to perform further tests. But I ended up not changing your lib and made this way:

  Wire.beginTransmission(0x50);
  Wire.write(writeaddress);
  if ( Wire.endTransmission() > 0) Serial.print("Erro da Fram");
  Wire.requestFrom(0x50, 1);
  Serial.print("Leitura 1:"); Serial.println(Wire.read(), DEC);

  Wire.beginTransmission(0x50);
  Wire.write(writeaddress);
  Wire.write(77);
  if ( Wire.endTransmission() > 0) Serial.print("Erro da Fram");
sosandroid commented 7 years ago

By the way, can you share the device IDs sent to serial when you have the SERiAL_DEBUG enabled ?

porcao commented 7 years ago

Starting... FRAM_MB85RC_I2C object created I2C device address 0x50 WP pin number 13 Write protect management: false Memory Chip NOT FOUND

I gave up. I set up a program to list me all I2C devices. I obtained a list ranging from 0x50 to 0x57. Are memory banks. Each with 256 bytes. I'll buy another memory module that will be easier. Thank you for your patience and help.

sosandroid commented 7 years ago

Ok,, this is because the the checkDevice method has a lower limit when outputing the results. At the time I wrote the Lib, 4K & 16K devices were not available.

I just added a new example which tries to identify the device for you and get its IDs

porcao commented 7 years ago

The Result: Starting... ....... ....... FRAM Device IDs Manufacturer 0xFFF ProductID 0xFFF Density code 0xF ...... ...... ......

sosandroid commented 7 years ago

Very strange as we do not have the manufacturer ID = 0x00A. I may come from the weird way of mixing device address & memory address of the chip.

I would recommend to switch the memory chip with a 256K. The lib has been heavily tested against this one (MB85RC256V). https://www.adafruit.com/product/1895

If easy with solder station, you can get the chip alone with a DIP to SOIC adapter for cheaper on ebay or equiv.

porcao commented 7 years ago

Thank you. That's what I'll do, I'll use this other memory.

sosandroid commented 7 years ago

Just had a mail from Fujitsu's marketing manager. The 16K devices does not have Device IDs implemented. From there, I'll try to add support for the chip in the LIB.

porcao commented 7 years ago

That good news. Once you're done can do the tests you want. Just send me the test code that I am sending you the results. Want my email to facilitate communication?

sosandroid commented 7 years ago

1.1.0b is ready for testing. A new example has been added to show how to address 16K devices

If you can deeply test the lib against your device It would be appreciated as I do not have one.

porcao commented 7 years ago

I testing the FRAM_MB85RC_I2C_manual_mode_simple_write_read example. Result: _Starting... FRAM_MB85RCI2C object created I2C device address 0x50 WP pin number 13 Write protect management: false Memory Chip NOT FOUND ...... ...... ...... Written value 0xCC Read value 0xCC DensityCode 0xF00

porcao commented 7 years ago

I ran some tests by changing the address where writing and reading are made. This chip is 16Kbits then are 2k bytes. The larger address would be 0x800. I did some tests and above 0x0ff it returns me a wrong value. Do you have any test in particular that I can do for you?

sosandroid commented 7 years ago

1.1.0b1 is available for testing. Bug fixing on the lib + better example for 16K device

The example now test a byte & a word writing at 0x25 and 0x750 memory slots. Let me know about the results

porcao commented 7 years ago

writeaddress2 = 0x0FA ==OK writeaddress2 = 0x0FF ==OK writeaddress2 = 0x100 == NOT OK

_Starting... FRAM_MB85RC_I2C object created I2C device address 0x50 WP pin number 13 Write protect management: false Memory Chip initialized FRAM Device IDs Manufacturer 0xF00 ProductID 0xF00 Density code 0xF00 Density 16K Device properties set ...... ...... ...... ...... ...... ...... i2c_addr 0x50 i2c_addr 0x50 Written value 0xCC Read value 0xCC Write Byte test : OK .... .... i2c_addr 0x50 i2caddr 0x50 Written value 0xBEEF Read value 0x1 Write word test : NOT OK .... .... Manufacturer 0xF00 DensityCode 0xF00 Density 16

sosandroid commented 7 years ago

OK, there was an issue with I2CAddressAdapt() to know about the address translation. The issue seems coming from there ... Another test is welcome to find out the write issue

sosandroid commented 7 years ago

Library modified to find out more :)

porcao commented 7 years ago

:(

Starting... FRAM_MB85RC_I2C object created I2C device address 0x50 WP pin number 13 Write protect management: false Memory Chip initialized FRAM Device IDs Manufacturer 0xF00 ProductID 0xF00 Density code 0xF00 Density 16K Device properties set ...... ...... ...... ...... ...... ...... Writing at location 0x25 Calculated addr 0x50 Calculated addr 0x50 Written value 0xCC Read value 0xCC Write Byte test : OK .... .... Writing at location 0x750 Calculated addr 0x57 Calculated addr 0x57 Written value 0xBEEF Read value 0x5051 Write word test : NOT OK .... .... Manufacturer 0xF00 DensityCode 0xF00 Density 16

porcao commented 7 years ago

This works!!!

`#include

define disk1 0x50 //Address of 24LC256 eeprom chip

void setup(void) { Serial.begin(115200); Wire.begin();

unsigned int address = 0x7FF;

writeEEPROM(disk1, address, 56); Serial.print(readEEPROM(disk1, address), DEC); }

void loop(){}

void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data ) { Wire.beginTransmission(deviceaddress); Wire.write((int)(eeaddress >> 8)); // MSB Wire.write((int)(eeaddress & 0xFF)); // LSB Wire.write(data); Wire.endTransmission(); }

byte readEEPROM(int deviceaddress, unsigned int eeaddress ) { byte rdata = 0xFF;

Wire.beginTransmission(deviceaddress); Wire.write((int)(eeaddress >> 8)); // MSB Wire.write((int)(eeaddress & 0xFF)); // LSB Wire.endTransmission();

Wire.requestFrom(deviceaddress,1);

if (Wire.available()) rdata = Wire.read();

return rdata; }`

sosandroid commented 7 years ago

The working example let me thing your have a 64K device. The working process is not compliant with 16K device's datasheet. Can you change the chipDensity to 64 and run the test ? If this works, you have a 64K devivce ...

Despite the KO test at 0x750 memory slot, here below the detailed explanation for a 16K device :

write address 0x25 =>  0b 000 00100101
write address 0x750 => 0b 111 01010000

According to 16K device's datasheet, the I2C protocol is used the following way :
7 bits device address + R/W bit. Device address is 1010xxx where xxx are the 3 MSB of the memory slot (out of 11 bits)
After that device address, the 8 LSB of the memory slot are send to the bus.

To read or write at 0x025 memory slot, the IC2 device address is 0b 1010 000 x. Which means 0x050
To read or write at 0x750 memory slot, the IC2 device address is 0b 1010 111 x. Which means 0x057

The second bit send is
    To read or write at 0x025 memory slot, (0b 000 00100101 & 0x000 11111111) => 0b 000 00100101 => 0x025
    To read or write at 0x750 memory slot, (0b 111 01010000 & 0x000 11111111) => 0b 000 01010000 => 0x010

The process (0x025 memory slot)
    wire.beginTranmission(0x50);
    Wire.write(0x25);
    ...

The process (0x750 memory slot)
    wire.beginTranmission(0x57);
    Wire.write(0x10);
    ...
porcao commented 7 years ago

Weird. I bought this chip:https://pt.aliexpress.com/item/Free-shipping-MB85RC16-RC16-SOIC8-Memory-FRAM-16-K-Bit-I2C/32455962214.html?spm=2114.13010608.0.0.3SluQB

Look my board: http://www.rlracing.com.br/chip.jpg

porcao commented 7 years ago

I ran a program to list all i2c devices. Response got the numbers from 0x50 to 0x57.

sosandroid commented 7 years ago

I agree this is weird. But if the program for 24LC256 works, this means the memory mapping is not the one of the MB85RC16.

Can you just change one line in the "Manual Mode" example ?

uint16_t chipDensity = 16; changed to uint16_t chipDensity = 64;.

Modifying this wil change the way the memory adressing is done by the library. This will be exactly the same as the 24LC256 example you gave 2 days ago. Let me know if this works or not :)

porcao commented 7 years ago

It worked! But I still do not understand why. Because the chip is 16 not 64. Can you imagine an address test to check the limits and make sure it's 64 but sold as 16?

Starting... FRAM_MB85RC_I2C object created I2C device address 0x50 WP pin number 13 Write protect management: false Memory Chip initialized FRAM Device IDs Manufacturer 0xF00 ProductID 0xF00 Density code 0xF00 Density 64K Device properties set ...... ...... ...... ...... ...... ...... Writing at location 0x25 Calculated addr 0x50 Calculated addr 0x50 Written value 0xCC Read value 0xCC Write Byte test : OK .... .... Writing at location 0x750 Calculated addr 0x50 Calculated addr 0x50 Written value 0xBEEF Read value 0xBEEF Write word test : OK .... .... Manufacturer 0xF00 DensityCode 0xF00 Density 64

sosandroid commented 7 years ago

Ok, that sounds better and I'm not falling dummy. Thanks for that.

To fully test either this is a 64K or higher chip or not, you just have to run the reworked example. I added a calculation of the second test address according to the chip density. The second test address will be (chipDensity * 128) - 80 For a 64K chip, you will hit the address 1FB0

porcao commented 7 years ago

It worked. But now I've been thinking about something. Could it be that by using a very high memory value it did not go back to the beginning? And overwritten something that might be in the beginning?

Starting... FRAM_MB85RC_I2C object created I2C device address 0x50 WP pin number 13 Write protect management: false Memory Chip initialized FRAM Device IDs Manufacturer 0xF00 ProductID 0xF00 Density code 0xF00 Density 64K Device properties set ...... ...... ...... ...... ...... ...... Writing at location 0x25 Calculated addr 0x50 Calculated addr 0x50 Written value 0xCC Read value 0xCC Write Byte test : OK .... .... Writing at location 0x1FB0 Calculated addr 0x50 Calculated addr 0x50 Written value 0xBEEF Read value 0xBEEF Write word test : OK .... .... Manufacturer 0xF00 DensityCode 0xF00 Density 64

sosandroid commented 7 years ago

The standard behavior of the chips, according to Datasheet, is last memory slot +1 = first memory slot. You can of course overwrite the 0x780 slot of a 16K device. To be sure, you should modify the example to add a read at that location to be sure you're not looping through the memory map.

If you're not looping, just test some other densities that do not support the Device IDs as mentionned in the readme tables.

One thing is clear now : you do not have a MB85RC16 chip but something else. After checking the MB85RC16 datasheet, the chip marking is different from what you have. RC16 E11050 300

sosandroid commented 7 years ago

Closed

dsk1990 commented 7 years ago

With MB85RC16 I have exactly same problem as porcao. And replace MB85RC16 with FM24C16B , I got the same result! Maybe there is some unknown bug with this lib about r/w address. thank you~

porcao commented 7 years ago

I buy 20 MB85RC16 from USA. Same errors. I stopped my tests and for my use this code work fine:

void writeEEPROM(uint16_t eeaddress, byte data ) { Wire.beginTransmission(0x50 + (eeaddress >> 8)); Wire.write(eeaddress & 0xFF); // LSB Wire.write(data); Wire.endTransmission(); }

byte readEEPROM(uint16_t eeaddress ) { byte rdata = 0x0; Wire.beginTransmission(0x50 + (eeaddress >> 8)); Wire.write(eeaddress & 0xFF); // LSB Wire.endTransmission(); Wire.requestFrom(0x50 + (eeaddress >> 8), 1); if (Wire.available()) rdata = Wire.read(); return rdata; }

sosandroid commented 7 years ago

A fix has been provided by @Palatis. A few weeks ago. @dsk1990, Which version did you test ?

dsk1990 commented 7 years ago

i test 4k and 16k fram; latest version; following results:

if define chipDensity = 4 or 16; when wr addr <= 255; => Calculated address = 0x50; Write word test : OK

if define chipDensity = 4 or 16; when wr addr > 255; => Calculated address != 0x50; Write word test : NOT OK

if define chipDensity = 64 or 256; => always Calculated address = 0x50; Write word test : OK

may difference is in function FRAM_MB85RC_I2C::I2CAddressAdapt

dsk1990 commented 7 years ago

aha, i got it~~

following graph show when read at address 0x1b0 1 Id2 addr should be 51 but it is 50 .

the mistake is in FRAM_MB85RC_I2C::readArray : Wire.requestFrom(i2c_addr, (uint8_t)items);

Changed to:

switch(density) {
            case 4:
                chipaddress = (i2c_addr | ((framAddr >> 8) & 0x1));
                break;
            case 16:
                chipaddress = (i2c_addr | ((framAddr >> 8) & 0x7));
                break;
            default:
                chipaddress = i2c_addr;
                break;
        }

Wire.requestFrom(chipaddress, (uint8_t)items);

enjoy it, thank you~~ @porcao @sosandroid