
Description
I observed that the I2C SCL clock in fast mode (400kHz) is only running at 357kHz, despite using 2k2 pull-up resistors that provide a relatively fast rise time.
After some investigation it turns out that the SERCOM::InitMasterWire() function (in the file SERCOM.cpp) is using the incorrect formula for the BAUD register.
The current fomula appears to be taken from Section 25 SERCOM - Serial Communication Interface in the SAMD21 datasheet:
BAUD = SystemCoreClock (48MHz) / (2 * baud rate) - 1
...however, the correct formula should be the one from Section 28 SERCOM - Inter-Integrated Circuit:
BAUD = SystemCoreClock (48MHz) / (2 * SCL_Frequency) - 5 - (SystemCoreClock (48MHz) * T(rise) / 2)
...where T(rise) is the time taken for the pull-up resistor to pull the SCL line high, (and will very much depend on the resistor values used).
Using 2k2 pull-up resistors I measured the rise time as 90ns, therefore the BAUD value in this instance should be:
BAUD = 48MHz / (2 * 400000) - 5 - (48MHz * 90ns / 2) = 52.84
Using a BAUD value around 52 or 53 gives a SCL frequency close to 400kHz.