Search code examples
embeddedstm32i2c

STM32 as I2C Slave: Data recieved LED not working


I'm trying to setup an STM32F401RBT as an I2C slave with an Arduino Uno as the master. The Arduino code looks as follows:

Arduino Code

I'm simply trying to transmit "3". The STM32 side looks like this:

STM32 Code

I use these three callback functions to manage the data. I am successfully recieving the correct number on the STM32 however the sub routine in the HAL_I2C_SlaveRxCpltCallback is not working. I'm trying to light up and LED for 100ms and off again for 100ms however the LED is constantly on and doesn't blink. Also, once the LED first turns on the STM32 ignores all other communication from the Arduino as it doesn't send an ACK bit on the next transaction. So somehow when it goes into this sub routine it freezes and doesn't do anything. Any ideas as to what the issue is? Thanks.


Solution

  • HAL_I2C_SlaveRxCpltCallback() gets called by the HAL's I2C interrupt handler routine. You should not be calling HAL_Delay() from within the context of an interrupt because delaying within an interrupt handler makes your system slow and unresponsive. Instead interrupt code should set a flag (or event or semaphore...) to signal the non-interrupt code to handle the event.

    Furthermore, HAL_Delay() relies on the SysTick interrupt to occur regularly and increment the tick to pass the time. If you call HAL_Delay() within an interrupt handler that is higher priority than the SysTick interrupt then the SysTick interrupt gets blocked from executing by the higher priority interrupt and your code gets stuck in a deadlock. This is my guess of what is happening in your case. Set breakpoints before and after the first call to HAL_Delay(). Run your code and when it reaches the first breakpoint before calling HAL_Delay(), set another breakpoint in the SysTick handler. Then run the code and I expect SysTick will not be reached because it's blocked by the higher priority interrupt and then HAL_Delay will never return because SysTicks are not occurring.

    You should change your HAL_I2C_SlaveRxCpltCallback() function to simply set a global flag variable. Then add code to the main loop to read the flag and do the LED flash and delays from within the main loop.