
Hi! Today I tried to set up an I2C eeprom for my project, using the driver in xpcc. I got the communication working after a while (I think the default address it uses, 0xA0 is wrong, as that's an 8 bit address, so the correct would be 0x50), but something doesn't work, I think probably on the read side, but I'm not sure. If I store a uint16_t and then read it back (either via the templated or the buffer-length way), the high byte (which is the second one in memory) is always 0xFF. If I lie, and for length I pass 3, the uint16_t will contain the correct value. I suspect there might be a small error in the low level implementation of the I2C transaction that causes this, but I don't know nearly enough to actually verify it. Can somebody take a look at this, or tell me if I'm completely wrong? :D Regards, Antal

Hi,
Today I tried to set up an I2C eeprom for my project, using the driver in xpcc. I got the communication working after a while (I think the default address it uses, 0xA0 is wrong, as that's an 8 bit address, so the correct would be 0x50), but something doesn't work, I think probably on the read side, but I'm not sure.
Yes, the address is definitely wrong, if should be 0x50.
If I store a uint16_t and then read it back (either via the templated or the buffer-length way), the high byte (which is the second one in memory) is always 0xFF. If I lie, and for length I pass 3, the uint16_t will contain the correct value. I suspect there might be a small error in the low level implementation of the I2C transaction that causes this, but I don't know nearly enough to actually verify it. Can somebody take a look at this, or tell me if I'm completely wrong? :D
I've looked through the implementation, and there was nothing that caught my eye as obviously wrong. Which specific I2C EEPROM chip do you use? The driver is kept generic, but was modelled after the 24FC1025. Acknowledge polling or page write is not implemented! You can debug the SoftwareI2C driver by adapting these lines: https://github.com/roboterclubaachen/xpcc/blob/develop/src/xpcc/architecture... This will give you a reasonable debug output over serial. If that fails, I recommend looking at the physical bus with a logic analyzer. Hope that helps a little, Niklas

Hi,
Which specific I2C EEPROM chip do you use?
I'm using a 24FC128, specifically chosen because the driver mentioned this family.
You can debug the SoftwareI2C driver by adapting these lines: https://github.com/roboterclubaachen/xpcc/blob/develop/src/xpcc/architecture... This will give you a reasonable debug output over serial.
Sadly, I don't have a serial output connected to a PC, but I mostly got used to it by now. I use the LCD for basic debugging, will see what I can figure out using that.
If that fails, I recommend looking at the physical bus with a logic analyzer.
I'm not sure I can get my hands on one, but if the problem persists I'll try. Antal

Hi there,
Which specific I2C EEPROM chip do you use?
I'm using a 24FC128, specifically chosen because the driver mentioned this family.
I wanted to verify the Eeprom driver myself, so I set up a simple test project using the 24FC1025 in 8pin DIP. Since this needed a breadboard, I used an RCA specific STM32F407 breakout, therefore this is not an xpcc example. But the code is pretty board independent anyway: https://gist.github.com/salkinium/da0db79a2808fa4f48ca0ac608de57a8 The example writes 32kB of data using 128B page writes using the driver. I modified the driver to allow addressing the upper 64kB using the A16 bank bit in the control byte (or address byte). https://github.com/roboterclubaachen/xpcc/commit/c424fd1f8e0adb3e4ffd3cc9ab0... I had significant electrical trouble in getting the EEPROM chip to work, and saw random write failures just like you. Then I had a closer look at the datasheet, and I wired up pin A2 to low, instead of high, assuming it was an address pin. The datasheet is pretty clear on this: Non-Configurable Chip Select. This pin must be hard wired to logical 1 state (VCC). Device will not operate with this pin left floating or held to logical 0 (VSS). After doing so, the Eeprom worked just fine. Cheers, Niklas

I had significant electrical trouble in getting the EEPROM chip to work, and saw random write failures just like you. Then I had a closer look at the datasheet, and I wired up pin A2 to low, instead of high, assuming it was an address pin. The datasheet is pretty clear on this:
Non-Configurable Chip Select. This pin must be hard wired to logical 1 state (VCC). Device will not operate with this pin left floating or held to logical 0 (VSS).
After doing so, the Eeprom worked just fine.
Yes, I've seen that, but for the 24FC128 that pin IS actually an address pin, so this probably isn't the problem. Could you try writing and reading in chunks of 2 bytes? I just want to make sure that it's not a problem with only this length. Regards, Antal

Hi,
Could you try writing and reading in chunks of 2 bytes? I just want to make sure that it's not a problem with only this length.
I've updated the gist with writes and reads of 2 bytes, which works fine for me. Ok, maybe another poke in the dark: There is this thing where page write (= writes > 1B) have to be aligned to the page size (128B for my chip): If a Page Write command attempts to write across a physical page boundary, the result is that the data wraps around to the beginning of the current page (overwriting data previously stored there), instead of being written to the next page as might be expected. Maybe that could explain why you would get 0xFF as the second byte? Cheers, Niklas

Hi,
Ok, maybe another poke in the dark: There is this thing where page write (= writes > 1B) have to be aligned to the page size (128B for my chip): […] Maybe that could explain why you would get 0xFF as the second byte?
Just as a follow-up on this, I just tried this, and it does indeed return 0xFF for the second byte. So writing 2B to address 127 on a fresh chip (ie. all memory to 0xFF), will result in this behavior. My test code then produces this: {2D, CF} != {2D, FF} {46, 29} != {46, FF} {04, B4} != {04, FF} {78, D8} != {78, FF} Is that what you are seeing? Niklas

Hi,
Ok, maybe another poke in the dark: There is this thing where page write (= writes > 1B) have to be aligned to the page size (128B for my chip): […] Maybe that could explain why you would get 0xFF as the second byte?
Just as a follow-up on this, I just tried this, and it does indeed return 0xFF for the second byte. So writing 2B to address 127 on a fresh chip (ie. all memory to 0xFF), will result in this behavior. My test code then produces this:
{2D, CF} != {2D, FF} {46, 29} != {46, FF} {04, B4} != {04, FF} {78, D8} != {78, FF}
Is that what you are seeing?
It has nothing to do with this, I'm not even close to the page boundaries. I'm trying to write and read the first ~4 bytes. I've tried a million things now without much success. One thing I do which I know I shouldn't is using RF_CALL_BLOCKING everywhere. Could this be the cause?

Hi,
Is that what you are seeing?
It has nothing to do with this, I'm not even close to the page boundaries. I'm trying to write and read the first ~4 bytes. I've tried a million things now without much success. One thing I do which I know I shouldn't is using RF_CALL_BLOCKING everywhere. Could this be the cause?
No, I don't think so. The failure that you describe is so specific, I don't think the RF_CALL_BLOCKING mechanism, which is extremely generic, could have any effect on this. If there were something wrong with that macro, I would expect the entire transfer to fail, not just one byte. RF_CALL_BLOCKING is a while(1) loop that polls the resumable function _in place_. So no other task will run during that call (except interrupts of course): https://github.com/roboterclubaachen/xpcc/blob/develop/src/xpcc/processing/r... Note that hardware I2C is interrupt driven, so it will definitely execute during that macro. SoftwareI2cMaster executes completely within the `start` method of I2cMaster, which is called inside the macro (somewhere in the driver) and therefore also executes during that macro. Using RF_CALL_BLOCKING is fine _both_ inside and outside of a Protothread. But particularly for I2C, which is quite slow compared to the CPU speed, you can use time during the transfer to switch to other protothreads and do other things. Hence the recommendation to call your resumable functions using PT_CALL from inside a Protothread, because it makes it a lot easier to add more tasks in the future and make them execute in parallel. Cheers, Niklas

Hi, I've updated xpcc to include the eeprom fix, and there were still problems, but FINALLY I've got it working. What I'm doing in my code is that I have a "version" constant, which I change when the data structure to be saved changes, so invalid values don't get read. When I read the data structure, first I check this version, and if it matches the compiled-in version then I read the real data. On writing the data I just unconditionally write first the version then the data. The problem was that the second write (which should write the actual data) didn't work, because the first one didn't finish yet. If you read "7.0 ACKNOWLEDGE POLLING" of the data sheet (http://ww1.microchip.com/downloads/en/DeviceDoc/21191s.pdf) it describes a way to poll for readiness of the device. So this doesn't work: RF_CALL_BLOCKING(eeprom.write(0, SETTINGS_VERSION)); RF_CALL_BLOCKING(eeprom.write(sizeof(SETTINGS_VERSION), data)); But this does: RF_CALL_BLOCKING(eeprom.write(0, SETTINGS_VERSION)); while (!RF_CALL_BLOCKING(eeprom.write(0, nullptr, 0))) {} RF_CALL_BLOCKING(eeprom.write(sizeof(SETTINGS_VERSION), data)); This really seems like a hack, so maybe this check should be incorporated into the driver (I might give a shot at implementing it if this is the way to go). I should have probably read the data sheet way earlier. At least I learned something :) Regards, Antal 2016-05-10 22:56 GMT+02:00 Niklas Hauser <niklas.hauser@rwth-aachen.de>:
Hi,
Is that what you are seeing?
It has nothing to do with this, I'm not even close to the page boundaries. I'm trying to write and read the first ~4 bytes. I've tried a million things now without much success. One thing I do which I know I shouldn't is using RF_CALL_BLOCKING everywhere. Could this be the cause?
No, I don't think so. The failure that you describe is so specific, I don't think the RF_CALL_BLOCKING mechanism, which is extremely generic, could have any effect on this. If there were something wrong with that macro, I would expect the entire transfer to fail, not just one byte.
RF_CALL_BLOCKING is a while(1) loop that polls the resumable function _in place_. So no other task will run during that call (except interrupts of course): https://github.com/roboterclubaachen/xpcc/blob/develop/src/xpcc/processing/r...
Note that hardware I2C is interrupt driven, so it will definitely execute during that macro. SoftwareI2cMaster executes completely within the `start` method of I2cMaster, which is called inside the macro (somewhere in the driver) and therefore also executes during that macro.
Using RF_CALL_BLOCKING is fine _both_ inside and outside of a Protothread. But particularly for I2C, which is quite slow compared to the CPU speed, you can use time during the transfer to switch to other protothreads and do other things. Hence the recommendation to call your resumable functions using PT_CALL from inside a Protothread, because it makes it a lot easier to add more tasks in the future and make them execute in parallel.
Cheers, Niklas
_______________________________________________ xpcc-dev mailing list xpcc-dev@lists.rwth-aachen.de http://mailman.rwth-aachen.de/mailman/listinfo/xpcc-dev
participants (2)
-
Niklas Hauser
-
Szabó Antal