arduino / arduino/ArduinoCore-samd
I2C handling out-of-order on PA08/PA09/SERCOM_ALT.
- Dominant language
- C
- Stars
- 502
- Forks
- 740
- PR merge metrics
- No merged PRs in 30d
Description
I've got a custom board using a SAMD21E18. In variant.h:
```c++
/* External I2C */
#define PIN_WIRE1_SDA (3u)
#define PIN_WIRE1_SCL (4u)
#define PERIPH_WIRE1 sercom2
#define WIRE1_IT_HANDLER SERCOM2_Handler
static const uint8_t SDA1 = PIN_WIRE1_SDA;
static const uint8_t SCL1 = PIN_WIRE1_SCL;
```
Pin 3 is PA08, pin r is PA09.
This i2c works in my sketch using Wire1. The issue I'm running into is using this in slave mode.
``` c++
Wire1.begin(SLAVE_ADDR);
Wire1.onRequest(requestEvent);
Wire1.onReceive(receiveEvent);
```
The software is configured such that the slave behaves like a common register-access I2C device - the master writes an address (1 byte), then sets up a read to get the data from that address.
Whenever my master (raspberry pi, as it happens) sends the 1-byte address payload, then subsequently tries to read the data back, the read operation (requestEvent) gets handled BEFORE the write operation (receive event), so that the address byte isn't properly set first. I've verified this by setting up time-stamping in those two functions - the `requestEvent` stores `micros()` when it happened, as does the `receiveEvent`, and next loop through the sketch they're printed out for comparison. I've also set a breakpoint on Wire.cpp:214 to capture the first I2C event that ever happens, and it's the request that gets handled rather than the receive.
For what it's worth, the Raspberry Pi is running the I2C bus at 50kHz, which seems slow. Perhaps that's somehow relevant?
To provide further evidence I'm not insane, the workaround is relatively simple - in the master code, any time I want to do a "read," I issue it twice - once to set the address (discard the returned data, since we know it's from a bogus address), and again to get the actual data desired, after a 1ms delay just for safety's sake.
Is there any sane reason the handler callbacks would be happening out-of-order from what's happening on the wire?
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with variant.h and Wire.cpp around line 214, then trace how Wire1's SERCOM2 interrupt dispatches requestEvent and receiveEvent for the reported SAMD21E18 PA08/PA09 setup. Reproduce the Raspberry Pi transaction at 50kHz and verify that callback order matches the I2C wire sequence without requiring the duplicate read workaround.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- embedded-iot
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100