cancel
Showing results for 
Search instead for 
Did you mean: 

I2C Slave Receive in DMA mode on STM32U575 series

maxborglowe
Associate III

Hi,

I'm attempting to set up an STM32U575 as an I2C slave. (The master is a F301)

My problem is that the slave only receives one byte, and then proceeds to disregard all of the following data.
I have set up a switch that turns on an RGB LED, depending on the value received by the slave at the variable secondary_mcu_state (0 = LED OFF, 1 = LED RED, 2 = LED GREEN, 3 = LED BLUE). The master continually counts 0-3 and sends to slave.

What I find curious is that after having started HAL_I2C_Slave_Receive_DMA() and then stepping through the while loop code, the program acts as desired: The LED is changing color continuously, and the i2c handler mode is appropriately set to HAL_I2C_MODE_SLAVE:

Screenshot 2024-04-11 at 05.51.14.png

Here's a look at the scope, which also shows that the I2C writes from the master device is neatly ACKed:
Screenshot 2024-04-11 at 05.53.02.png

As I start running the program without breakpoints, the handler mode immediately jumps into the state HAL_I2C_MODE_NONE, and the device stops receiving data from the master. See below:

Screenshot 2024-04-11 at 06.00.40.png
Scope now shows the data sent from master being NAKed instead:

Screenshot 2024-04-11 at 06.15.33.png

When I run the program without debug, the device receives the first byte, and ignores the rest. This I prove by resetting the slave device (hardware reset with button), and seeing the LEDs assert a solid color. If the slave was working properly, the color should continue to change.

The code below describes the slave setup. I've added in HAL_I2C_SlaveRxCpltCallback() and HAL_I2C_AddrCallback() to the main.c file, but these are never even called.

 

 

uint8_t secondary_mcu_state = 0;

int main(void)
{
  /* OMITTING INIT STUFF FOR CLARITY */

    HAL_StatusTypeDef HAL_I2C_status = HAL_I2C_Slave_Receive_DMA(&hi2c1, &secondary_mcu_state, sizeof(secondary_mcu_state));

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  __enable_irq();
  while (1)
  {
			switch (secondary_mcu_state) {
				/* Inverted values -> 0xFFFF = fully OFF, 0x0 = fully ON */
				case 0:
					/* LED OFF */
					TIM2->CCR1 = 0xFFFF;
					TIM2->CCR2 = 0xFFFF;
					TIM2->CCR3 = 0xFFFF;
					break;
				case 1:
					/* LED RED */
					TIM2->CCR1 = 0;
					TIM2->CCR2 = 0xFFFF;
					TIM2->CCR3 = 0xFFFF;
					break;
				case 2:
					/* LED GRN */
					TIM2->CCR1 = 0xFFFF;
					TIM2->CCR2 = 0;
					TIM2->CCR3 = 0xFFFF;
					break;
				case 3:
					/* LED BLU */
					TIM2->CCR1 = 0xFFFF;
					TIM2->CCR2 = 0xFFFF;
					TIM2->CCR3 = 0;
					break;
				default:
					break;
			}
			
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

 

 

I should also note that I've disabled clock stretching on both devices, as this seems to "hang" the I2C line completely (SDA HIGH, SCL LOW).

Let me know if there's any information I've omitted.

Any help on this issue is greatly appreciated!

Br,
Max

 

0 REPLIES 0