sparkfun / Arduino_Boards

Board definitions for SparkFun-manufactured AVR, ARM, and ESP-based Arduino boards.
263 stars 125 forks source link

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

Closed JordanMajd closed 4 years ago

JordanMajd commented 4 years ago

Issue

Using the Thing Plus as an I2C slave:

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.

AndyEngland521 commented 4 years ago

added in v1.7.2, thanks!