Hey guys,
I have really serious problem on which I work for a couple of days now.
I get some strange behaviour on the I2C bus of my Arduino, the components I use are the following:
- Arduino Leonardo (ATMega 32u4)
- NFC Module V1.1 from elecfreaks (PN532 Chip)
Here are the Links to the datasheets of these 2 components
Arduino Leonardo Site
PN532 Chip Datasheet
I use the I2C Library from dsscuircits.com because I need to send / read more than 32 bytes over the I2C bus.
I made some slight modifications, which do not really effect the core functions, for example I splitted the send and read methods into 3 methods to have a seperate start, actual read/write and stop.
But I tested everything with the official read and write methods from this library and had the same problems, so that can't be the source of it.
At start everything works properly, I can read NFC Tags and send Peer Data with no problems.
The LLCP, SNEP and NDEF Protocols work properly.
Reading and Sending on the I2C Bus too.
Everything works well, repeatedly.
BUT
There is this one thing that happens, which I can reproduce repeatedly with a specific smartphone and it sometimes happens just out of nothing.
The following logic analyzer images (with a DigiView DV3400) shows you the different situations:
This is a close up of some I2C Bus activity, as you can see everything is fine
Here is a closer close up to see the end of a frame
And another close up of the start of a "healthy" frame
Also in a bigger overview, you can see that everything is working properly
For "debugging" purposes, I printed some TWI registers before the read/write processes, here is the typical output while reading:
(The big gaps between the clock (SCL) cycles are because of the print output while reading. It does not effect the error, it still happens when I remove them.)
.
...
READ | TWCR:C4 TWSR:50 TWINT:7 TWDR:0
READ | TWCR:84 TWSR:40 TWINT:7 TWDR:49
READ | TWCR:C4 TWSR:50 TWINT:7 TWDR:0
READ | TWCR:84 TWSR:40 TWINT:7 TWDR:49
READ | TWCR:C4 TWSR:50 TWINT:7 TWDR:0
READ | TWCR:84 TWSR:40 TWINT:7 TWDR:49
READ | TWCR:C4 TWSR:50 TWINT:7 TWDR:0
READ | TWCR:84 TWSR:40 TWINT:7 TWDR:49
READ | TWCR:C4 TWSR:50 TWINT:7 TWDR:0
...
.
Now when the error happens (just after some time or putting the specific smartphone to the NFC Module) it looks like this:
This is the moment when it breaks. This always happens in a read frame.
And another time
And another time...
Additional Info:
Some time ago, after that happened, the I2C bus was freezing at all and I needed a hard reset on the Arduino. After using the timeOut method from the I2C library, the I2C bus did not keep frozen anymore, but it also did not get back into the normal workflow, as seen in the following picture:
This is how the workflow looks like after the problem occured. The lower image shows one of the impulses of the upper image. It looks like this for read and write.
Here in a bigger timeframe:
The output of some TWI registers change like this:
.
..
READ | TWCR:C4 TWSR:50 TWINT:7 TWDR:0
READ | TWCR:84 TWSR:40 TWINT:7 TWDR:49
READ | TWCR:C4 TWSR:50 TWINT:7 TWDR:0
READ | TWCR:84 TWSR:40 TWINT:7 TWDR:49
READ | TWCR:C4 TWSR:50 TWINT:7 TWDR:0
READ | TWCR:4 TWSR:F8 TWINT:7 TWDR:49
READ | TWCR:44 TWSR:F8 TWINT:7 TWDR:93
READ | TWCR:44 TWSR:F8 TWINT:7 TWDR:27
READ | TWCR:44 TWSR:F8 TWINT:7 TWDR:4F
READ | TWCR:44 TWSR:F8 TWINT:7 TWDR:9F
..
.
I can reset everything and make it work again, by just removing the VCC from the NFC module and reattaching it. Sometimes I have to do this multiple times, but in the most cases it works after the first time. I can see that it works again by the serial output that prints the TWI Registers.
All the jobs are also done well again after resetting it like this.
The usual routine in the error cycle is that
TWSR remains F8
TWDR changes but not with the correct values
TWCR switches between 4, 44 and 4C
The most common TWCR values in binary here:
the bad ones / the good ones
| 0x4c - | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 |
|---|---|---|---|---|---|---|---|---|
| 0x44 - | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 |
| 0x04 - | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
| 0xC4 - | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 |
| 0x84 - | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
| Bit# | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
according to the ATMega Datasheet which I linked here, this is the short form of the different bits:
Bit 7 - TWINT - TWI Interrupt Flag:
is set by hardware when TWI finished the current job
Bit 6 - TWEA - TWI Enable Ackowledge Bit:
if set to one, ACK pulse is generated
Bit 5 - TWSTA - TWI START Condition Bit:
if one, checks if bus is enabled and generates start condition
Bit 4 - TWSTO - TWI STOP Condition Bit:
same as 5 but for stop
(I think, at least for now, that this is the problem)
Bit 3 - TWWC - TWI Write Collision Flag:
".. is set when attempging to write to the TWI Data Register.."
Bit 2 - TWEN - TWI Enable Bit:
somehow the on/off switch for the I2C
Bit 1 - Res - Reserved Bit
always zero
Bit 0 - TWIE - TWI Interrupt Enable
when this is 1, the TWI interrupt request will be activated as long as TWINT is high
The I2C library I use has a lockUp() method which is called when something wents wrong.
It is also called when my problem happens, so I tried to do some things inside this method, like writing TWDR when Bit 3 is set, because it says in the datasheet that then it is cleared.
Tried to set the TWI Enable Bit to 0 and back 1 in the hope that it resets somehow, but nothing worked.
I have to admit, that I didn't keep protocoling all my tries scientifically. I tested around with a lot of settings but nothing worked, so if you have any suggestions that you think I might already tested them, just let me try them again.
For now I somehow think I can just reset the I2C bus, clear it or unfreeze it somehow, but I did not manage to do so yet.
The Sourcecode is following in the next post because else this one becomes to long.
CONTINUING NEXT POST...