Skip to content

Issue in wire library for I2C Slave on SAMD51 Thing Plus #56

@JordanMajd

Description

@JordanMajd

Issue

Using the Thing Plus as an I2C slave:

  • Hangs up the i2c bus and itself whenever an i2c operation occurs.
  • Does not show up on the bus at registered address.
  • Does not invoke onRequest or onReceive callbacks.

This issue also affects Adafruit SAMD51 boards, an issue tracking a fix for their Wire lib and variants is in the ArduinoCore-samd repo.

Reproduction

Sample Program:

#include <Wire.h>

void setup() {
  Serial.begin(115200);
  Wire.begin(0x08);
  Wire.onRequest(requestHandler);
  Serial.println("Setup complete");
}

void loop() {
  Serial.println(millis());
  delay(100);
}

void requestHandler() {
  Serial.println("Req: responding 6 bytes");
  Wire.write("bytess");
}

Upon running i2cdetect the device stops printing timestamps in the loop. i2cdetect is sluggish, and shows no available addresses, not even other devices on the bus:

$ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --   

i2cget is unable to read values from the board:

$ i2cget -y 1 8
Error: Read failed

Explanation

Thing Plus' Wire lib was written for a SAMD21, which has a single Sercom interrupt for I2C slave operations. Whereas, the SAMD51 uses 4 Sercom Interrupts when being used as an I2C slave.

Workaround

Near the top of the repro sketch sketch declare each of the 4 SERCOM3 interrupt handlers:

void SERCOM3_0_Handler() { Wire.onService(); }
void SERCOM3_1_Handler() { Wire.onService(); }
void SERCOM3_2_Handler() { Wire.onService(); }
void SERCOM3_3_Handler() { Wire.onService(); }

Now both i2cdetect and i2cget are nominal:

$ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- 08 -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- 1a -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --  
$ i2cget -y 1 8
0x62

Fix

Update Wire.h to support 4 sercom interrupt handlers for a wire interface in addition to declaring the handlers in the Thing Plus variant.h.

I'm submitting a PR to Adafruit and can also submit one here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions