2018-10-18 08:18 AM
Hi All,
I am using STM32CubeMX HAL functions (STM32CubeF1 FW package V1.6.1 in STM32F100RCT MCU project) to handle 24LC128 I2C EEPROM comms. Followed the advice in the HAL library help:
DMA mode IO MEM operation:
address using HAL_I2C_Mem_Read_DMA()
So my code looks as follows:
Writing:
if(CheckI2C1DeviceReady() == FALSE)
{
return I2C_ERR;
}
ResultI2C1 = HAL_BUSY;
do
{
I2cStatus = HAL_I2C_Mem_Write_DMA(&hi2c1,EE_DEV_ADDR,Addr,sizeof(EEADR),WrBufferEE,WrPreBytes);
if(I2cStatus == HAL_OK)
{
break;
}
else if(I2cStatus == HAL_ERROR || I2cStatus == HAL_TIMEOUT)
{
return I2C_ERR;
}
}while(I2cStatus == HAL_BUSY);
if(CheckI2C1EndWrite() == FALSE)
{
return I2C_ERR;
}
where:
static BOOLEAN CheckI2C1DeviceReady(void)
{
// INT32U TimeOut = WAIT_I2C1_READY;
HAL_StatusTypeDef I2C1Status;
do
{
I2C1Status = HAL_I2C_IsDeviceReady(&hi2c1,EE_DEV_ADDR,EE_READY_TRIES,EE_READY_TOUT);
if(/*--TimeOut <= 0 ||*/ I2C1Status == HAL_TIMEOUT || I2C1Status == HAL_ERROR)
{
return FALSE;
}
}while(I2C1Status != HAL_OK);
return TRUE;
}
static BOOLEAN CheckI2C1EndWrite(void)
{
// INT32U TimeOut = WAIT_I2C1_TRANSFER;
while(ResultI2C1 != HAL_OK)
{
if(/*--TimeOut <= 0 ||*/ ResultI2C1 == HAL_ERROR)
{
return FALSE;
}
}
HAL_Delay(5U);
return TRUE;
}
The end of transfer and error handling comes from the call-back functions:
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if(hi2c->Instance == I2C1)
{
I2C1_TxComplete();
}
if(hi2c->Instance == I2C2)
{
I2C2_TxComplete();
}
}
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if(hi2c->Instance == I2C1)
{
I2C1_RxComplete();
}
if(hi2c->Instance == I2C2)
{
I2C2_RxComplete();
}
}
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
if(hi2c->Instance == I2C1)
{
I2C1_Error();
}
if(hi2c->Instance == I2C2)
{
I2C2_Error();
}
}
and goes trough handling functions:
/***************************************************************************************************
* TX COMPLETE WHEN WRITE A BLOCK OF DATA TO EEPROM ON THE I2C1 BUS
*
* Description : End of TX when write multiple bytes to EEPROM on the I2C1 via DMA channel
* Arguments : None
* Returns : None
* Notes : None
*
***************************************************************************************************/
void I2C1_TxComplete(void)
{
ResultI2C1 = HAL_OK;
}
/***************************************************************************************************
* RX COMPLETE WHEN READ A BLOCK OF DATA TO EEPROM ON THE I2C1 BUS
*
* Description : End of RX when read multiple bytes to EEPROM on the I2C1 via DMA channel
* Arguments : None
* Returns : None
* Notes : None
*
***************************************************************************************************/
void I2C1_RxComplete(void)
{
ResultI2C1 = HAL_OK;
}
/***************************************************************************************************
* ERROR WHEN WRITE OR READ A BLOCK OF DATA TO/FROM EEPROM ON THE I2C1 BUS
*
* Description : Error when write or read multiple bytes to/from EEPROM on the I2C1 via DMA channel
* Arguments : None
* Returns : None
* Notes : None
*
***************************************************************************************************/
void I2C1_Error(void)
{
ResultI2C1 = HAL_ERROR;
}
Reading:
if(CheckI2C1DeviceReady() == FALSE)
{
return I2C_ERR;
}
ResultI2C1 = HAL_BUSY;
do
{
I2cStatus = HAL_I2C_Mem_Read_DMA(&hi2c1,EE_DEV_ADDR,Addr,sizeof(EEADR),RdBufferEE,RdPreBytes);
if(I2cStatus == HAL_OK)
{
break;
}
else if(I2cStatus == HAL_ERROR || I2cStatus == HAL_TIMEOUT)
{
return I2C_ERR;
}
}while(I2cStatus == HAL_BUSY);
if(CheckI2C1EndRead() == FALSE)
{
return I2C_ERR;
}
static BOOLEAN CheckI2C1EndRead(void)
{
// INT32U TimeOut = WAIT_I2C1_TRANSFER;
while(ResultI2C1 != HAL_OK)
{
if(/*--TimeOut <= 0 ||*/ ResultI2C1 == HAL_ERROR)
{
return FALSE;
}
}
return TRUE;
}
Sometimes the execution is stacked in static BOOLEAN CheckI2C1DeviceReady(void)...
MY QUESTIONS:
Regards,
Anani
NB: I have found a post related to my issue - https://community.st.com/s/feed/0D50X00009XkVw0SAF
but still confused... In my CubeMX I2C interrupts are enabled (see below):
and my FW is stacked after HAL_I2C_Mem_Read_DMA() call...
RE: The result of my debugging:
The execution of HAL_I2C_IsDeviceReady() ALWAYS returns HAL_BUSY although I2C_WaitOnFlagUntilTimeout() ALWAYS returns HAL_TIMEOUT!!!
(see attached I2C Debug.docx)
Re: New event captured (see attached file).
Re: I have increased the priority of I2C and relevant DMA interrupts to the absolute maximum level of 0 (see attached screenshots).
FreeRTOS still works fine. BUT…. Same event as described in the doc file yesterday happened…
RE: I am trying to resolve my I2C issue by experimenting with some abort communication code (see attached picture). I assume that the closing of I2C communication by the Master (MCU) is not done correctly in some cases when I2C interrupts are not the only ones with highest priority.
I have caught another event displayed on the pictures below:
Surprisingly it looks like the current byte read is interrupted after just 3 bits been read (well, my scope resolution is quite poor)! ITERREN flag is set, but my I2C error interrupt service routine break-point is not hit! I have NO reasonable explanation whatsoever!
What could that be?