cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L0 - I2C - Bug in HAL_I2C_Master_Sequential_Transmit ?

feuerwolf
Senior
Posted on July 27, 2017 at 12:47

Hallo,

I am trying to Read GPS data from a uBlox LEA via I2C with a STM32L073RZ  (Nucleo Board). I am able to read EEPROMs with the HAL Libraries in Blocking and Interrupt Mode. The EEPROM i am using is a 24LC64 and it is not critical to I2C Specifications so I can read it using a HAL_transmit to tell the Adress I want to read and then use a HAL_read to read the number of Bytes. Unfortunately the HAL functions automatically generates a STOP condition after using it! My problem is, that the GPS chip I want to read strictly follows the I2C specifications and does Expect a RESTART/START condition in between the Transmit – Read actions and does not accept a STOP.

Here I come the Combined Transactions from HAL Lib into the game. With these functions I was able to  solve the I2C combined transaction Problem using the Transfer Options provided.

HAL_I2C_Master_Sequential_Transmit_IT

(hi2c, DevAddress, addr, 1, I2C_FIRST_FRAME);

HAL_I2C_Master_Sequential_Receive_IT

(hi2c, DevAddress, pData, len, I2C_LAST_FRAME);

 

Using my Logic Analyzer, I can See the I2C connection working and transfer Data correctly. The Data decrypted via the logic analyzer makes sense. All Adresses and read / write transactions are correct on the logic analyzer. My Problem is, that the HAL_I2C_Master_Sequential_Reveive_IT function doesn’t write Data in via the Pointer pData back in Buffer! So I can see everything works, but I don’t get the data back ? Did I just encounter a Library Bug? Do I use the function correctly?

Function:

HAL_StatusTypeDef I2C_uBlox_Read_SQ(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t len) {

    HAL_StatusTypeDef returnValue;

    uint8_t addr[2];

    addr[1] = (uint8_t) ((MemAddress & 0xFF00) >> 8);

    addr[0] = (uint8_t) (MemAddress & 0xFF);

    returnValue   = HAL_I2C_Master_Sequential_Transmit_IT(hi2c, DevAddress, addr, 1, I2C_FIRST_FRAME);

    if(returnValue != HAL_OK)

    return returnValue;

    HAL_Delay(1);

    returnValue   = HAL_I2C_Master_Sequential_Receive_IT(hi2c, DevAddress, pData, len, I2C_LAST_FRAME);

    return returnValue;

}

Function Call:

#define BUFFER_SIZE             500

uint8_t  bufferI2C_uint8[BUFFER_SIZE];

I2C_uBlox_Read_SQ(&hi2c1, UBLOX_I2C_SHIFTED_ADRESS,  0xFD , bufferI2C_uint8, (2) );

I2C_uBlox_Read_SQ(&hi2c1, UBLOX_I2C_SHIFTED_ADRESS,  0xFF , bufferI2C_uint8, (200  ) );

4 REPLIES 4
Posted on July 27, 2017 at 15:32

Hello!!

You use the non blocking version of theese transaction  functions. (HAL_I2C_Master_Sequential_Receive_IT)

Normaly you must check the callback function after transaction completion.  You introduce an 1 ms delay

between the transactions . Is it enough?

You define also' addr' at two bytes array but transmit one byte . is it your intention?

You try to get 200 bytes  from GPS Is it capable to transmit 200 bytes?  (and finaly finish your transaction? )

Did you tried  HAL_I2C_Mem_Read_IT?  for Random Read Access.? UBlox support it.

feuerwolf
Senior
Posted on July 27, 2017 at 16:24

Hi,

1. is it really a MUST to check or even implement callback functions? Usually it would be to clear at least a Interrupt Flag... I just changed from PIC32, so not experienced on STM32. My callbacks look like:

void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c){

__NOP();//test if we reach this position

}

void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c){

__NOP();//test if we reach this position

}

2. 1ms delay is just a wild guess. It works fine regarding to my Logic Analyzer output. Actually i wanted to use the

    HAL_I2C_IsDeviceReady function instead/later.

3. well, the two byte array is a relict from the EEPROM Code which needed 16  bits adresses, its not really necessary here,  but does the job

4. Yes, the GPS is able to be read with even more bytes. I can read exactly this GPS with I2C using the online mbed comiler generated code. 200 bytes here are only for Test purpose, usually i would first get the number of bytes stored in the gps at a certain adress, then i would read that number ob bytes at another adress

5. I did not try HAL_I2C_Mem_Read_IT . I will, but i wanted to code this manually, which i always did on other plattforms and microcontrollers

Posted on July 27, 2017 at 16:57

Hi!

1. It is  not a must  ofcourse..  In such a  case it's better to use the blocking functions (not to have the delay issue)

2.   One  millisecond (calculated ofcourse)   is not enough in my opinion. I had a lot of pitfalls because of a single one ms.! (when i calculate 1 , i put 3 at least(when timing is not critical)

check if  HAL_I2C_MasterRxCpltCallback is called ( finished transaction)  or return an error  HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) and what error is it. .

feuerwolf
Senior
Posted on August 17, 2017 at 09:57

Hi,

So I2C with uBlox works now. I solved the communication problem by using the HAL Memory I2C functions. I am pretty sure that HAL I2C Sequential is not correct implemented for L0 prozessors, which also Carmine Noviello in his book Mastering STM32 in the I2C chapter  on page 486 describes.