Go Down

Topic: Repurposing Arduino Zero RX Light (SERCOM5) pin to I2C (Read 672 times) previous topic - next topic

masoandro

Hello,
I am using an Arduino 0 core on my SAMD21 with Atmel Studio. I have an I2C device hooked up to pins PB02 (Arduino Zero pin 19) and PB03 (Arduino Zero pin 25).  As a side note, this exact same device functions without issue on the regular wire (sercom3, 20, 21).
The first thing I did was disable the RX light pin by commenting out sections using PIN_LED_RXL.


I then tried the typical:

Code: [Select]


TwoWire myWire(&sercom5, 19, 25 ); //create an I2C on SERCOM5, PA16, PA17
void setup(){
//...

    myWire.begin(); //pressure sensor 1

    pinPeripheral(19, PIO_SERCOM_ALT); //change functionality of PIO, SDA1

    pinPeripheral(25, PIO_SERCOM_ALT); //SCL1
//...
}


Then I try to read 4 from the I2C component:

Code: [Select]
unsigned int recv[4] = {0};
myWire.requestFrom(INTERFACE_ADDR,4,1); //get 4 bytes of data
while(myWire.available()){
  recv[i++] = myWire.read();
}


And the result is always 0. I do not get a response and it tells me that the slave device sends a NACK - the INTFLAG.MB (master on bus interrupt enable) bit has been set and there is no data in the data register.
Curiously enough, when I set the pinPeripherals of the pins to PIO_SERCOM_ALT, the PINCFG register of PB02 (pin 19) does not get set properly - input enable (INEN) is still set and drive strength (DRVSTR) is not driven high, although the MUX enable (PMUXEN) is set. I know that pinPeripheral() does not set DRVSTR or INEN but it leads me to think that there is something else going on with this pin or the other that may affect its ability to act as an I2C elsewhere during the enabling of the chip. 
The PMUX register is set properly and indicates MUX setting 3, which is correct for SERCOM5 PAD[0] and PAD[1] according to the datasheet - it is MUX Function D (pg 34).
The initialization of the Sercom registers looks fine. For good measure I did change variant.h to include the Sercom5 interrupt for I2C:

Code: [Select]
#define WIRE_INTERFACES_COUNT 2


#define PIN_WIRE_SDA         (20u)
#define PIN_WIRE_SCL         (21u)
#define PERIPH_WIRE          sercom3
#define WIRE_IT_HANDLER      SERCOM3_Handler


static const uint8_t SDA = PIN_WIRE_SDA;
static const uint8_t SCL = PIN_WIRE_SCL;


#define PIN_WIRE1_SDA (19u)
#define PIN_WIRE1_SCL (25u)
#define PERIPH_WIRE1 sercom5
#define WIRE1_IT_HANDLER SERCOM5_Handler


static const uint8_t SDA1 = PIN_WIRE1_SDA;
static const uint8_t SCL1 = PIN_WIRE1_SCL;

Still faced with the same issue - the device does not get return data when calling requestFrom().
If anyone has any insight about the way I'm trying to use these pins and how to get the I2C to work on PB02 and PB03 for Sercom5 I would very much appreciate any help.
Thank you!

MartinL

Hi masoandro,

Not all of the SAMD21's SERCOM pins support I2C. Unfortunately, I2C isn't supported on port pins PB02 and PB03, (see SAMD21 datasheet table 7.2.3 SERCOM I2C Pins, Table 7-5. SERCOM Pins Supporting I2C).

Port pins that support I2C on the SAMD21G are: PA08, PA09, PA12, PA13, PA16, PA17, PA22 and PA23.

masoandro

Ah, good point. Other sercom functions only it seems!

MartinL

Unfortunately, Microchip removed the I2C column from their 7.1 PORT Function Multiplexing table in the latest SAMD21 datasheet, so now it's not as obvious which pins support this functionality.

westfw

Did you ever figure out exactly what "sercom doesn't support i2c" means?

I'd expect a sercom to be a sercom, which leaves ... something electrical?

MartinL

Quote
Did you ever figure out exactly what "sercom doesn't support i2c" means?

I'd expect a sercom to be a sercom, which leaves ... something electrical?
Good point, no I haven't. The datasheet doesn't say either, although as you mention I guess it's most likely something electrical. Perhaps only these pins support I2C open-drain outputs?

westfw

I believe some of the Adafruit SAMD51 boards have "does not support I2C" Sercoms connected to the "Arduino R3" I2C pins, and it seems to work at least some (most?) of the time.  Presumably things are a lot less stressful for the typical "one or two modern CMOS I2C devices in close proximity" than they are for an old-style i2C bus with "many" "clients."

MartinL

Hi westfw,

Quote
I believe some of the Adafruit SAMD51 boards have "does not support I2C" Sercoms connected to the "Arduino R3" I2C pins, and it seems to work at least some (most?) of the time.  Presumably things are a lot less stressful for the typical "one or two modern CMOS I2C devices in close proximity" than they are for an old-style i2C bus with "many" "clients."
Wow, you have an incredible attention to detail. After following up on your eagle eyed observation, I can see what you mean. Adafruit are using PB02 and PB03 for SDA and SCL respectively on their Metro M4, even though they're not listed as SERCOM I2C pins...???

So perhaps it is possible for masoandro to get I2C going on similiar pins with the SAMD21? I'll have a look later and see if I can get something working.

Starting to feel lazy for just quoting the datasheet verbatim.

MartinL

Reading between the lines of the SAMD51 datasheet, it looks like the I2C SERCOM pins are able to drive I2C Fast Plus mode and High Speed mode.

The SAMD51 datasheet section 54. Electrical characteristics at 85 - 54.9 I/O Pin Characteristics:

Quote
2. The pins PA08, PA09, PA12, PA13, PA16, PA17, PA22, PA23, PD08, PD09 have faster fall-time in
I2C Fast Plus mode (Fm+) and High Speed mode (HS). The fall-time can be in 1 ns range in Fm+
mode and in 5 ns range in HS mode.
Also in section 6. I/O Multiplexing and Considerations - Notes after Table 6.1 Multiplexed Peripheral Signals:

Quote
3. These pins are High Sink pins and have different properties than regular pins:
PA08, PA09, PA12, PA13, PA16, PA17, PA22, PA23, PD08, PD09.
It also suggests keeping a "steady signal" on port pins PB02 and PB03, in order to prevent clock jitter on the external crystal (XOSC32K), in section 6. I/O Multiplexing and Considerations - Table 6.3 XOSC32K Jitter Minimization.

I guess Adafruit have proved that it's possible to use an I2C SERCOM on port pins PB02 and PB03 for standard (100kHz) and fast (400kHz) modes of operation, but it might be causing some clock jitter.

MartinL

Hi masoandro,

Back to the SAMD21. Following the discussion with westfw it appears it might be possible get I2C communications on port pins PB02 and PB03 after all.

I've looked at getting I2C going on port pins PB02 and PB03, unfortuately however I don't have any boards with both of these pins broken out, in order to test any code. Your code for the I2C communication looks correct.

One point though, if you're using the Arduino Zero core code as the basis of custom board then SERCOM5 is already employed for the EDBG chip "Serial" communications, this is in addition to the native USB port "SerialUSB" and the UART "Serial1" on pins D0 and D1.

To free up SERCOM5 it's necessary to edit the core code's "variant.cpp" file and comment out the lines which initialise the Serial initialisation using SERCOM5:

Code: [Select]
Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
//Uart Serial( &sercom5, PIN_SERIAL_RX, PIN_SERIAL_TX, PAD_SERIAL_RX, PAD_SERIAL_TX ) ;
void SERCOM0_Handler()
{
  Serial1.IrqHandler();
}

//void SERCOM5_Handler()
//{
//  Serial.IrqHandler();
//}

Go Up