Sercom I2C issues - timing?

Discussions around product based on ARM Cortex M0+ core.

Moderator: nferre

M14
Posts: 20
Joined: Thu Mar 27, 2014 10:51 am

Sercom I2C issues - timing?

Fri Apr 11, 2014 11:19 am

Hi all :).

I got some issues using the Sercom module in I2C master mode with a Xplained D20 board. When the ADDR register is written, the Sercom module (SMEN enabled) should generate a start-condition, write the address and read the ACK-response of the slave before generating a interrupt.

When the ADDR register is written direct after initiating the Sercom module, there is no activity visible on the bus at all. Only 1 interrupt is generated, the BUSERR bit set.
With a breakpoint set on the write to the ADDR register, or somewhere after initiating the Sercom module, there is no problem: A start-condition is generated, the address is written and communication starts.

I like to know what could cause this and how I can fix / prevent it. Has this something to do with synchronization between clock domains? I studied the ASF I2C master and noticed a while(syncbusy); loop before writing / reading registers. Is this necessary? I added a whileloop before writing the ADDR register but it didn't solve this problem. I think I also need to have some more information about the clock synchronization subject :).


The initialization of the Sercom module. The main clock is 48MHz, the Sercom peripheral clock is connected to it without any divider. Baudrate is calculated for 400KHz.

Code: Select all

void InitI2C_LL(void) {
	Set_PortConfig(PIN_PA16, PM_C, PD_NOT_USED, 0, PS_NOT_USED);
	Set_PortConfig(PIN_PA17, PM_C, PD_NOT_USED, 0, PS_NOT_USED);
	
	GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0) | GCLK_CLKCTRL_ID(0x0E));
	
	// Enable peripheral clock
	//PM->APBCMASK.bit.SERCOM1 = 1;
	PM->APBCMASK.reg |= PM_APBCMASK_SERCOM1;
	
	// Reset SERCOM module
	SERCOM1->I2CM.CTRLA.bit.SWRST = 1;
	while(SERCOM0->USART.CTRLA.bit.SWRST);
	
	SERCOM1->I2CM.CTRLA.bit.MODE = SERCOM_I2CM_CTRLA_MODE_I2C_MASTER_Val;
	SERCOM1->I2CM.CTRLA.bit.SDAHOLD = 2;	// SDAhold = 300ns - 600ns
	SERCOM1->I2CM.CTRLA.bit.INACTOUT = 3;	// Inactive timeout set to 20 SCL cycle
	SERCOM1->I2CM.CTRLA.bit.LOWTOUT = 1;	// Set SCL low timeout
	
	SERCOM1->I2CM.CTRLB.bit.SMEN = 1;
	
	SERCOM1->I2CM.STATUS.reg = (	  SERCOM_I2CM_STATUS_BUSERR				// Clear bus error
									| SERCOM_I2CM_STATUS_ARBLOST			// Clear arbitration lost
									| SERCOM_I2CM_STATUS_BUSSTATE(1)		// Set busstate to idle
									//| SERCOM_I2CM_STATUS_LOWTOUT			// Clear low timeout // Not required, write to ADDR clears this flag
								);
	
	SERCOM1->I2CM.BAUD.reg = 48;

	SERCOM1->I2CM.INTENCLR.reg = (SERCOM_I2CM_INTENSET_SB | SERCOM_I2CM_INTENSET_MB);	// Disable interrupt --> Only enabled when sending
	
	NVIC_EnableIRQ(SERCOM1_IRQn);
	NVIC_SetPriority(SERCOM1_IRQn, 1);	// Priority now at 1, right priority?
	
	SERCOM1->I2CM.CTRLA.bit.ENABLE = 1;	// Enable i2cm
}

Start write

Code: Select all

void I2C_Master_Write(UINT8 slaveAddress, UINT16 wrBufferLenght, UINT8 *pWrBuffer, void *pCallBack) {
	
// Some initstuff
	
	SERCOM1->I2CM.INTFLAG.reg = (SERCOM_I2CM_INTENSET_SB | SERCOM_I2CM_INTENSET_MB);	// Clear interrupt flag
	SERCOM1->I2CM.INTENSET.reg = (SERCOM_I2CM_INTENSET_SB | SERCOM_I2CM_INTENSET_MB);	// Enable interrupt
	
	while((masterModule.sercomPort->STATUS.reg & SERCOM_I2CM_STATUS_SYNCBUSY));
	SERCOM1->I2CM.ADDR.reg = ((masterModule.slaveAddress << 1) & 0xFE);	// Address - Write action	
}
Write direct after initialization:

Code: Select all

InitI2C_LL();
I2C_Master_Write(0x20, 3, write, NULL);

Besides that, I noticed a pretty long clock stretch (5.8us) between reading the ACK and writing the next byte on the bus. The D20 runs on 48MHz, I should expect this to be a lot shorter. A 8MHz Atmega328 with TWI on 400KHz can do this without any clock stretching.
Image
M14
Posts: 20
Joined: Thu Mar 27, 2014 10:51 am

Re: Sercom I2C issues - timing?

Wed Apr 30, 2014 12:31 pm

Bump :).

The main issue I described was caused by the busstate. Forcing the busstate to 1 before enabling the SERCOM module does not work. The SERCOM module needs to be enabled first.
phabib
Posts: 2
Joined: Fri Mar 07, 2014 11:09 pm

Re: Sercom I2C issues - timing?

Fri May 16, 2014 11:39 pm

I'm looking at your I2C master code but I'm not able to see where the Set_PportConfig routine comes from or the defines for PD_NOT_USED and PS_NOT_USED come from. Are they yours, or from some include file that I'm not finding?

Thanks.
M14
Posts: 20
Joined: Thu Mar 27, 2014 10:51 am

Re: Sercom I2C issues - timing?

Tue Jun 03, 2014 1:16 am

Thats my own code, used for setting a configuration of a specific I/O pin.

Return to “SAM D20 Cortex-M0+ MCU”

Who is online

Users browsing this forum: No registered users and 1 guest