Skip to main content
TDJ
Senior III
August 7, 2021
Question

I2C Slave - clock stretching disables communication and other problems (STM32L0)

  • August 7, 2021
  • 16 replies
  • 5082 views

I try to implement I2C slave so it behaves like a typical EPROM and master can read/write using HAL_I2C_Mem_Read/HAL_I2C_Mem_Write functions.

After 3 days of searching and trying I found only one, partially working example: STM32F072 I2C slave Receive callback

Problems:

  1. Communication seems to work only when clock stretching is disabled (Clock No Stretch Mode = Enable/I2C_NOSTRETCH_ENABLE). Enabling clock stretching causes slave to pull SCL line down indefinitely once it receives its address.
  2. Description of I2C_XFEROPTIONS (I2C_FIRST_FRAME, I2C_NEXT_FRAME, I2C_LAST_FRAME) found in UM1940 is completely cryptic and no description in HAL source code is found.
  3. I am able to receive data but not to send. I receive odd address, call HAL_I2C_Slave_Seq_Transmit_IT(hi2c, &_dataBuffer[_offset], 1, I2C_NEXT_FRAME) and that results in HAL_I2C_ERROR_OVR error.

I read many posts discouraging use of HAL functions for slave implementation but I hoped the functionality has been improved recent years and maybe now it is usable.

I use the latest STM32Cube_FW_L0_V1.12.1, functions calls in interrupt mode (*_IT) and STM32L041.

I am familiar with the I2C_TwoBoards_RestartAdvComIT example. It does provide some insight but it does not address the above two problems. This example is provided for Nucleo-L073RZ only, which may or may not indicate that tests with other L0 Nucleos were not successful. Moreover, HAL_I2C_EnableListen_IT() is called in the loop which indicates author(s) of this example could not find a better yet reliable solution.

Please advise.

This topic has been closed for replies.

16 replies

KnarfB
Super User
August 8, 2021

Once I did some example code: https://gitlab.com/stm32mcu/i2c_master_and_servant. It does not handle clock-stretching but memory type read and write worked fine.

hth

KnarfB

TDJ
TDJAuthor
Senior III
August 24, 2021

@KnarfB​ I think you managed to get it working because Nucleo-STM32F401RE you used for for tests has much different and simpler I2C interface than the newer MCUs.

TDJ
TDJAuthor
Senior III
August 9, 2021

I have tested your example using popular Bus Pirate interface and the following commands:

[0x60 0x00 0x00 0x01 0x02 0x03 0x04 0x05]

[0x60 0x00 [0x61 r:6]

The first command writes 6 bytes to slave at address 0x60, starting from register 0x00. The second one attempts to read the previously written 6 bytes.

It could be that either your code or HAL has some glitches since only one (1st) byte gets returned, HAL_I2C_SlaveTxCpltCallback does not get called and HAL_I2C_ErrorCallback executes three times with error HAL_I2C_ERROR_OVR but at least it transfers this one byte! I have tested it with STM32F303K8T and STM32H7A3VI.

However, it does NOT work with STM32L041G6UxS. I can write (receive) but not read (transfer) at all. I suspect HAL bugs.

Moreover, you example only works with clock stretching disabled, which is consistent with my tests and probably indicates more HAL problem.

ST Technical Moderator
August 17, 2021

Hello @TJast​ ,

You can review the STM32L0 errata sheet related to your devices to check the known I2C peripheral limitations and if you have the same condition (If clock stretching is enabled).

0693W00000D2itQQAR.jpg 

When your question is answered, please close this topic by choosing Select as Best. This will help other users find that answer faster.

Imen

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
TDJ
TDJAuthor
Senior III
August 22, 2021

@Imen DAHMEN​ Thank you for the hint but in my case processor does not enter Stop mode. It must be something else.

I think first I need to make sure timings are correct - see my other post: Possible CubeMX I2C timing config bug (STM32L0x and other)

TDJ
TDJAuthor
Senior III
August 24, 2021

@Imen DAHMEN​ As far as I can tell, besides incorrect CubeMX-generated timing, the problem is that during HAL "slave operations" (HAL_I2C_Slave** functions) transfer options (XferOptions) are not used at all. They are passed but not used. All "master operations" (HAL_I2C_Master** functions) use I2C_TransferConfig() function for that purpose but no similar concept/approach is found in "slave" functions. It seems XferOptions are just ignored - that is, not being applied to the I2C_CR2 register.

If I am correct, HAL I2C Slave functions have serious bugs which render them unusable. Other posts on this topic I came across seem to confirm that.

ST Technical Moderator
August 26, 2021

Hi @TJast​ ,

Thanks for this details, I will raise your issue to CubeMx team.

Hello @Houda GHABRI​ ,

It seems this post is related to the CubeMX issue - see this post: Possible CubeMX I2C timing config bug (STM32L0x and other).

Can you please review and confirm this issue with CubeMx?

Thanks

Imen

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
TDJ
TDJAuthor
Senior III
August 27, 2021

I have done detailed I2C timing analysis in Excel based on available specs. I can email it.

However, it seems that this is not only CubeMX incorrect timing config problem. I am showing that HAL_I2C_Mem_Read() function execution can prevent SysTick_Handler() from firing. Consequently, HAL_I2C_Mem_Read() timeout never occurs because program execution goes into infinite loop since SysTick value does not increment. Tested with NUCLE0-F303K8. Yes, HAL_I2C_Mem_Read() is called from interrupt handler but this interrupt has lower priority than SysTick with PreemptPriority=0 (highest).

I begin to understand why some folks recommend using LL-HAL only and/or using HAL just for initial config but not for production grade systems.

TDJ
TDJAuthor
Senior III
August 31, 2021

@Amel NASRI​ The key concept here is to engage, make it work. It does not happen by just publishing stuff. "STM32Cube_MCU_Overall_Offer" repo has 4 (four) contributors, two pull requests, four registered issues total, zero releases, zero packages.

I do not think the goals of publishing HAL on Github have been achieved, do not you agree?

The name of the repo does not even make it possible to find it, if someone looks for STM32 HAL. Try it yourself.

Amel NASRI
ST Technical Moderator
September 1, 2021

For this feedback regarding Github, I add @ALABB​  to this discussion.

At package level, you can see that goal is achieved.

Select for example STM32CubeL4, you will find there 2 dedicated pull requests & 11 issues managed by the team engaged to provide required support there.

May be the name of the repository is not so significant (from your point of view), but this is the main page gathering all Cube firmware components for all families. So you need to select relevant component each time.

Thanks again for sharing your thoughts and giving me the opportunity to enlighten more about Github repository.

-Amel

To give better visibility on the answered topics, please click on "Best Answer" on the reply which solved your issue or answered your question.
ALABSTM
ST Employee
October 28, 2021

Hi,

Thank you @TJast​ for your feedback and thank you  @Amel NASRI​ for the details about our offer on GitHub. Indeed, the STM32Cube_MCU_Overall_Offer repository on the STMicroelectronics organization is the entry point for the STM32 MCU offer on GitHub. There, you can find a list of different repositories, from those containing whole firmware per series (e.g., STM32CubeL4, as mentioned above) to those containing particular components like CMSIS or HAL-LL (e.g., stm32l4xx_hal_driver). Each set of repositories addresses particular needs of our users and customers.

Hence, the STM32Cube_MCU_Overall_Offer repository is not intended to submit issues and pull-requests. In your case, you could have submitted your issue on the STM32CubeL0 repository, for instance. Now, since you submitted it to the ST Community, it is fine too, as both support channels are complementary.

Please note also that issues and pull-requests submitted via the GitHub channel are limited to the software published within each repository (criterium that your issue fulfills).

Other topics related to the hardware, the ecosystem, or the documentation (e.g., the reference manual), or any support request (help to port an existing application or to develop your own) shall be submitted to this community, whose scope is broader than the GitHub support channel's.

I hope this helps.

With regards,

S.Ma
Principal
November 21, 2021

Would having an emulated I2C slave RAM stm32 example help? With the example telling the relation between max non clock stretch bit rate vs core speed and max interrupt latency?