cancel
Showing results for 
Search instead for 
Did you mean: 

I2C

loeffel2
Associate III
Posted on October 18, 2017 at 14:50

Hi

I'm using I2C1 periphery of a STM32F205 device in master mode. The firmware is based on the 

HAL 

V1.2.1 driver with interrupt approach

. Three slaves are attached to the bus and 7bit address mode is used. 

I'm able to communicate with two slave devices but the communication with the third device fails. I following sequence could be observed within the 'HAL_I2C_EV_IRQHandler()' handler:

Valid sequence:

1. SB bit was set (Start send)

2. ADDR bit was set (Slave address send)

Void seqence:

1. SB bit was set 

(Start send)

2. ADD10 bit was set 

(First byte of 10bit address send) -> Should be ADDR

   

The communication fails because the ADD10 bit of the I2C_SR1 got set instead of the ADDR bit. 7bit mode is still configured I2C_OAR1= 0x4000. 

The obvious difference within the code is the slave address which is 0xF0 for the device which fails and 0xEC and 0x90 for the other ones.   

Has someone any idea why the I2C master rise a ADD10 interrupt instead of the ADDR? The only difference within the code is the slave address which is 0xF0 for the device which fails and 0xEC and 0x90 for the other ones.   

The I2C initialization code generated by cube is:

/* I2C1 init function */

void MX_I2C1_Init(void)

{

hi2c1.Instance = I2C1;

hi2c1.Init.ClockSpeed = 400000;

hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;

hi2c1.Init.OwnAddress1 = 0;

hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;

hi2c1.Init.OwnAddress2 = 0;

hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;

hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

if (HAL_I2C_Init(&hi2c1) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

}

Start of transfer is:

// Send the byte stream by ISR

if ( HAL_OK == HAL_I2C_Master_Transmit_IT( ptrToHandle, ptrToStreamTx->addr, ptrToStreamTx->ptrToData, ptrToStreamTx->size ) ) {

1 ACCEPTED SOLUTION

Accepted Solutions
Posted on October 20, 2017 at 00:34

Hello Raphael!

You are right about the version. Is the newest. Had in my mind

Firmware

v1.6.

About the 10 bit  address behaviour, when initialize the I2c with I2C_ADDRESSINGMODE_10BIT  the first byte sent is the Header 0b11110XXy  and the second is the LO  address byte 0bXXXXXXXX. 

Take a look inside I2C_Master_SB function (called when the SB flag is set )  for the first byte and inside  I2C_Master_ADD10  for the second byte.

My conclusion is that for your case , is enough to change the 'Init.AddressingMode' before you transmit the 10-bit address  and restore it to 7 bits mode after

finish the transaction

. I2C_OAR1 concerns slave mode only.

ptrToHandle->Init.AddressingMode = I2C_ADDRESSINGMODE_10BIT;

HAL_I2C_Master_Transmit_IT(.... 10bit addr); // func  for transmit.

//  after finish transaction and before you call the next transmit_IT function change the addressing mode again.

// .....

ptrToHandle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

//....

Regards

vf

View solution in original post

6 REPLIES 6
loeffel2
Associate III
Posted on October 18, 2017 at 16:40

Hi

The observed behavior could be explained as follow:

First the slave address of 0xF0 is in the range of the reserved pattern for the 10bit device addressing '11110xx'. In master mode the I2C periphery will automatically switch to 10bit mode if the 10bit pattern will be detected independent of the 

I2C_SR1 settings.

 This results in the rising of the ADD10 interrupt. 

Second the interrupt approach of the 

HAL 

V1.2.1 I2C driver

 is buggy. 10bit mode is not properly implemented. The result is, that the low byte of the 16bit slave address will be send twice and the content of the high byte will not be transferred. 
Posted on October 18, 2017 at 16:57

Hello!

HAL 

V1.2.1

is an old version.

Sugest to upgrade to latest version.

I don't use F2 family but the approach for Device address lenght handling, is better in latest version than 1.2.

By the way the  0xF0 is a 10bit  address.

Regards

vf

emalund
Associate III
Posted on October 18, 2017 at 17:32

where do I find, at least some, documentation for the stmF0 I2C library.

sorry about butting in here, but trying to make a new thread states 'add a title' with no place to add the title

loeffel2
Associate III
Posted on October 19, 2017 at 09:36

Dear Vangelis

Thanks for the feedback. 

The HAL file of the I2C driver 'stm32f2xx_hal_i2c.c' has the verison V1.2.1. and date '14-April-2017'. The file is part of the 'STM32Cube_FW_F2_V1.6.0' package installed by Cube. This is the latest package I could find with Cube. Are you sure there is a newer one and where do I get it?   

Thanks Raphael

Posted on October 20, 2017 at 00:34

Hello Raphael!

You are right about the version. Is the newest. Had in my mind

Firmware

v1.6.

About the 10 bit  address behaviour, when initialize the I2c with I2C_ADDRESSINGMODE_10BIT  the first byte sent is the Header 0b11110XXy  and the second is the LO  address byte 0bXXXXXXXX. 

Take a look inside I2C_Master_SB function (called when the SB flag is set )  for the first byte and inside  I2C_Master_ADD10  for the second byte.

My conclusion is that for your case , is enough to change the 'Init.AddressingMode' before you transmit the 10-bit address  and restore it to 7 bits mode after

finish the transaction

. I2C_OAR1 concerns slave mode only.

ptrToHandle->Init.AddressingMode = I2C_ADDRESSINGMODE_10BIT;

HAL_I2C_Master_Transmit_IT(.... 10bit addr); // func  for transmit.

//  after finish transaction and before you call the next transmit_IT function change the addressing mode again.

// .....

ptrToHandle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

//....

Regards

vf

Posted on October 20, 2017 at 08:32

Dear Vangelis

Your conclusion is correct, thanks. Interrupt approach with 10bit master mode work's in the actual HAL implementation. 

Fortunately I only has to write to the 7bit slave device with a slave address equal to the 10bit header. As a workaround I could configure the I2C for 10bit addressing (This solves the issue with sending the low byte of the slave address twice). Mask the first data byte into the slave address low byte and start a transfer.

Regards Raphael