arduino / arduino/ArduinoCore-samd

I2C handling out-of-order on PA08/PA09/SERCOM_ALT.

Open
#398 8 comments 1 reaction 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.