cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103C6 never enters interrupt handler and because of that holds SCL low because of RxNE is set, BTF is set and DR hasn't been read after first data byte received, stopping reception, why?.

VRami.1
Associate III

I'm trying to send some data from master to a slave (the STM32F103C6) with HAL functions, with HAL_I2C_Slave_Receive() -no interrupt mode- the reception works flawlessly but with HAL_I2C_Slave_Receive_IT() -the one needed- the slave acknowledges its address and receives the first byte of the string -I got the ack too-, after that the SCL line is hold low by the slave and none of the modifications that I did fixed the problem.

After read several documents finally I found the explanation for that in the reference manual for that microcontroller, it says that this behavior is because the NxRE bit is set and the DR register hasn't been read before the arrival of the next data byte, causing that the BTF bit is set I suppose because the next data byte arrived and the only way to solve that problem is to read SR1 followed by a read to DR. I have a big problem here because to me I tought the handling of RxNE, BTF, DR and SR1 was totally internal to the _IT functions and I don't know what to do to solve the problem. I taught in make a force rading inside the interrupt handler but I previously put some flags inside the handler and those flags never sets what makes me think that the interrupt is never handled even when inside the function HAL_I2C_MspInit() the interrupt for the I2C peripheral has been enabled.

Has anyone had that error before?. How can I solve it.

int main(void)
{
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_I2C1_Init();
  MX_RTC_Init();
  MX_TIM2_Init();
  MX_CRC_Init();
 
  HAL_I2C_MspInit(&hi2c1);
 
  HAL_GPIO_WritePin(GPIOA, FASE1_AMA_Pin, GPIO_PIN_SET);
    HAL_Delay(33000);
    HAL_GPIO_WritePin(GPIOA, FASE1_AMA_Pin, GPIO_PIN_RESET);
 
  	if(HAL_I2C_Slave_Receive_IT(&hi2c1, mensaje, 11) != HAL_OK)
  	{
  		HAL_GPIO_WritePin(GPIOA, FASE6_ROJO_Pin, GPIO_PIN_SET);
  	}
 
  	HAL_GPIO_WritePin(GPIOA, FASE1_ROJO_Pin, GPIO_PIN_SET);
  	HAL_Delay(5000);
 
  	switch(HAL_I2C_GetError(&hi2c1))
  	{
  		case HAL_I2C_ERROR_NONE:
  		{
  			HAL_GPIO_WritePin(GPIOB,FASE3_VERDE_Pin, GPIO_PIN_SET);
  			HAL_GPIO_WritePin(GPIOB,FASE4_VERDE_Pin | FASE4_AMA_Pin | FASE4_ROJO_Pin, GPIO_PIN_RESET);
  		} break;
  		case HAL_I2C_ERROR_BERR:
  		{
  			HAL_GPIO_WritePin(GPIOB,FASE4_VERDE_Pin, GPIO_PIN_SET);
  			HAL_GPIO_WritePin(GPIOB,FASE3_VERDE_Pin | FASE4_AMA_Pin | FASE4_ROJO_Pin, GPIO_PIN_RESET);
  		} break;
  		case HAL_I2C_ERROR_ARLO:
  		{
  			HAL_GPIO_WritePin(GPIOB,FASE3_VERDE_Pin | FASE4_VERDE_Pin, GPIO_PIN_SET);
  			HAL_GPIO_WritePin(GPIOB,FASE4_AMA_Pin | FASE4_ROJO_Pin, GPIO_PIN_RESET);
  		} break;
  		case HAL_I2C_ERROR_AF:
  		{
  			HAL_GPIO_WritePin(GPIOB,FASE4_AMA_Pin, GPIO_PIN_SET);
  			HAL_GPIO_WritePin(GPIOB,FASE3_VERDE_Pin | FASE4_VERDE_Pin | FASE4_ROJO_Pin, GPIO_PIN_RESET);
  		} break;
  		case HAL_I2C_ERROR_OVR:
  		{
  			HAL_GPIO_WritePin(GPIOB, FASE3_VERDE_Pin | FASE4_AMA_Pin, GPIO_PIN_SET);
  			HAL_GPIO_WritePin(GPIOB,FASE4_VERDE_Pin | FASE4_ROJO_Pin, GPIO_PIN_RESET);
  		} break;
  		case HAL_I2C_ERROR_DMA:
  		{
  			HAL_GPIO_WritePin(GPIOB, FASE4_VERDE_Pin | FASE4_AMA_Pin, GPIO_PIN_SET);
  			HAL_GPIO_WritePin(GPIOB,FASE3_VERDE_Pin | FASE4_ROJO_Pin, GPIO_PIN_RESET);
  		} break;
  		case HAL_I2C_ERROR_TIMEOUT:
  		{
  			HAL_GPIO_WritePin(GPIOB,FASE3_VERDE_Pin | FASE4_VERDE_Pin | FASE4_AMA_Pin, GPIO_PIN_SET);
  			HAL_GPIO_WritePin(GPIOB,FASE4_ROJO_Pin, GPIO_PIN_RESET);
  		} break;
  		case HAL_I2C_ERROR_SIZE:
  		{
  			HAL_GPIO_WritePin(GPIOB,FASE4_ROJO_Pin, GPIO_PIN_SET);
  			HAL_GPIO_WritePin(GPIOB,FASE3_VERDE_Pin | FASE4_VERDE_Pin | FASE4_AMA_Pin, GPIO_PIN_RESET);
  		} break;
  		case HAL_I2C_ERROR_DMA_PARAM:
  		{
  			HAL_GPIO_WritePin(GPIOB,FASE3_VERDE_Pin | FASE4_ROJO_Pin, GPIO_PIN_SET);
  			HAL_GPIO_WritePin(GPIOB,FASE3_VERDE_Pin | FASE4_AMA_Pin, GPIO_PIN_RESET);
  		} break;
  	}
 
  	switch(HAL_I2C_GetState(&hi2c1))	/* Para ver el estado del periférico I2C */
    {								/* en cuando sale de las condiciones.    */
    	  case HAL_I2C_STATE_RESET:
    	  {
    		  HAL_GPIO_WritePin(GPIOB,FASE3_AMA_Pin,GPIO_PIN_SET);
    		  HAL_GPIO_WritePin(GPIOB,FASE6_VERDE_Pin | FASE6_AMA_Pin | FASE1_VERDE_Pin, GPIO_PIN_RESET);
    	  } break;
    	  case HAL_I2C_STATE_READY:
    	  {
    		  HAL_GPIO_WritePin(GPIOB,FASE6_VERDE_Pin,GPIO_PIN_SET);
    		  HAL_GPIO_WritePin(GPIOB,FASE3_AMA_Pin | FASE6_AMA_Pin | FASE1_VERDE_Pin, GPIO_PIN_RESET);
    	  } break;
    	  case HAL_I2C_STATE_BUSY:
    	  {
    		  HAL_GPIO_WritePin(GPIOB,FASE3_AMA_Pin | FASE6_VERDE_Pin,GPIO_PIN_SET);
    		  HAL_GPIO_WritePin(GPIOB,FASE6_AMA_Pin | FASE1_VERDE_Pin, GPIO_PIN_RESET);
    	  } break;
    	  case HAL_I2C_STATE_BUSY_TX:
    	  {
    		  HAL_GPIO_WritePin(GPIOB,FASE6_AMA_Pin,GPIO_PIN_SET);
    		  HAL_GPIO_WritePin(GPIOB,FASE3_AMA_Pin | FASE6_VERDE_Pin | FASE1_VERDE_Pin, GPIO_PIN_RESET);
    	  } break;
    	  case HAL_I2C_STATE_BUSY_RX:
    	  {
    		  HAL_GPIO_WritePin(GPIOB,FASE3_AMA_Pin | FASE6_AMA_Pin,GPIO_PIN_SET);
    		  HAL_GPIO_WritePin(GPIOB,FASE6_VERDE_Pin | FASE1_VERDE_Pin, GPIO_PIN_RESET);
    	  } break;
    	  case HAL_I2C_STATE_LISTEN:
    	  {
    		  HAL_GPIO_WritePin(GPIOB,FASE6_VERDE_Pin | FASE6_AMA_Pin,GPIO_PIN_SET);
    		  HAL_GPIO_WritePin(GPIOB,FASE3_AMA_Pin | FASE1_VERDE_Pin, GPIO_PIN_RESET);
    	  } break;
    	  case HAL_I2C_STATE_BUSY_TX_LISTEN:
    	  {
    		  HAL_GPIO_WritePin(GPIOB,FASE3_AMA_Pin | FASE6_VERDE_Pin | FASE6_AMA_Pin,GPIO_PIN_SET);
    		  HAL_GPIO_WritePin(GPIOB,FASE1_VERDE_Pin, GPIO_PIN_RESET);
    	  } break;
    	  case HAL_I2C_STATE_BUSY_RX_LISTEN:
    	  {
    		  HAL_GPIO_WritePin(GPIOB,FASE1_VERDE_Pin,GPIO_PIN_SET);
    		  HAL_GPIO_WritePin(GPIOB,FASE3_AMA_Pin | FASE6_VERDE_Pin | FASE6_AMA_Pin, GPIO_PIN_RESET);
    	  } break;
    	  case HAL_I2C_STATE_ABORT:
    	  {
    		  HAL_GPIO_WritePin(GPIOB,FASE3_AMA_Pin | FASE1_VERDE_Pin,GPIO_PIN_SET);
    		  HAL_GPIO_WritePin(GPIOB,FASE6_VERDE_Pin | FASE6_AMA_Pin, GPIO_PIN_RESET);
    	  } break;
    	  case HAL_I2C_STATE_TIMEOUT:
    	  {
    		  HAL_GPIO_WritePin(GPIOB,FASE3_AMA_Pin | FASE6_VERDE_Pin,GPIO_PIN_SET);
    		  HAL_GPIO_WritePin(GPIOB,FASE6_AMA_Pin | FASE1_AMA_Pin, GPIO_PIN_RESET);
    	  } break;
    	  case HAL_I2C_STATE_ERROR:
    	  {
    		  HAL_GPIO_WritePin(GPIOB,FASE3_AMA_Pin | FASE6_VERDE_Pin | FASE6_AMA_Pin,GPIO_PIN_SET);
    		  HAL_GPIO_WritePin(GPIOB,FASE1_VERDE_Pin, GPIO_PIN_RESET);
    	  } break;
    }
 
  while (1)
  {
 
  }
}

Following is the i2c initialization function:

I2C_HandleTypeDef hi2c1;
 
 
 
/* I2C1 init function */
 
void MX_I2C1_Init(void)
 
{
 
    hi2c1.Instance = I2C1;
 
    hi2c1.Init.ClockSpeed = 100000;
 
    hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
 
    hi2c1.Init.OwnAddress1 = 34;
 
    hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
 
    hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
 
    hi2c1.Init.OwnAddress2 = 0;
 
    hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
 
    hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
 
    if (HAL_I2C_Init(&hi2c1) != HAL_OK)
 
    {
 
        Error_Handler();
 
    }
 
}

Following is the i2c initialization function with the respective NVIC priority setting:

void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
 
{
 
    GPIO_InitTypeDef GPIO_InitStruct = {0};
 
    if(i2cHandle->Instance==I2C1)
 
    {  
 
        __HAL_RCC_GPIOB_CLK_ENABLE();
 
        GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
 
        GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
 
        GPIO_InitStruct.Pull = GPIO_PULLUP;
 
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
 
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
        /* I2C1 clock enable */
 
        __HAL_RCC_I2C1_CLK_ENABLE();
 
        /* I2C1 interrupt Init */
 
        HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
 
        HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
 
        HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
 
        HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
 
    }
 
}

I let the interrupt priority in default mode as there are defined in HAL repository examples as NVIC_PRIORITY_GROUP_4 wich lets the interrupt priority handling in the order of the NVIC vector table like seen bellow:

HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

and in the MX_I2C_Init() the priority for the I2C peripheral is set for the highest priority so I don't think sistick is messing with the I2C interrupt.

So I need help, can anyone help me with the I2C held low problem?.

I forgot to tell that when I use the HAL_I2C_Slave_Receive() -blocking function- the handling of error and status gaves no error and I2C ready repectively but when I use the HAL_I2C_Slave_Receive_IT() function the code apparently hangs in the line where the interrupt function is. I noted that because of the flags that I've placed before and after that function.

Thanks a lot in advance for the help.

0 REPLIES 0