cancel
Showing results for 
Search instead for 
Did you mean: 

ST-Link starts firmware and aborts it while downloading

mfrank9
Associate III

Hello,

I am using STM32CubeIDe V1.10.0.

my project is structured as follows:
-CubeMX inits
-HAL_I2C_IsDeviceReady
-HAL_I2C_Mem_Read //Read a large amount from an I2C EEPROM
-while(1)

I have now done a lot of troubleshooting to understand why HAL_I2C_IsDeviceReady very often returns HAL_BUSY.

The problem is that when debugging, the ST-Link restarts the program and then breaks. This interrupts the I2C communication. If SDA is low at this point (because the external EEPROM is pulling the SDA low) the i2c can never be used again. It is always HAL_BUSY.
Only when power is removed will the I2C be re-enabled.

When clicking on "Debug", the ST-Link must not restart the software and interrupt it in an undefined manner.

The J-Link does not have this problem. As a result, the I2C never hangs up here.

1 ACCEPTED SOLUTION

Accepted Solutions

The following worked for me.
However, there seem to be internal flags that are not reset correctly.
The I2C was still busy but the SDA level was finally high again.
I was only able to fix this with a software reset.

 

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C3_Init();
/* USER CODE BEGIN 2 */

Toogle_I2C_Clk_Pin(
  &hi2c3,
  MX_I2C3_Init, HAL_I2C_DeInit,
  GPIOA, GPIO_PIN_8,
  0b1010000 <<1);

 

 

static void Toogle_I2C_Clk_Pin(
      I2C_HandleTypeDef *hicPtr,
      void (*MX_I2CX_Init)(void),
      HAL_StatusTypeDef (*HAL_I2C_DeInit)(I2C_HandleTypeDef *hi2c),
      GPIO_TypeDef* clkGPIOx, uint16_t clkGPIO_Pin)
{
  if(clkGPIOx == NULL) return;
  if(MX_I2CX_Init == NULL) return;
  if(HAL_I2C_DeInit == NULL) return;

  HAL_StatusTypeDef state = HAL_I2C_IsDeviceReady(hicPtr, 0b1010000 <<1, 50, 5);

  if(state != HAL_BUSY) return;

  HAL_I2C_DeInit(hicPtr);

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  // __HAL_RCC_GPIOH_CLK_ENABLE();
  // __HAL_RCC_GPIOA_CLK_ENABLE();
  // __HAL_RCC_GPIOC_CLK_ENABLE();
  // __HAL_RCC_GPIOB_CLK_ENABLE();


  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(clkGPIOx, clkGPIO_Pin, GPIO_PIN_SET);


  GPIO_InitStruct.Pin = clkGPIO_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(clkGPIOx, &GPIO_InitStruct);

  //9 Flanken ausgeben
  for(uint8_t i =0; i < 9; i++)
  {
    HAL_GPIO_TogglePin(clkGPIOx, clkGPIO_Pin);
    HAL_Delay(1);
  }

  HAL_GPIO_WritePin(clkGPIOx, clkGPIO_Pin, GPIO_PIN_SET);

  MX_I2CX_Init();

  state = HAL_I2C_IsDeviceReady(hicPtr, 0b1010000 <<1, 50, 5);

  NVIC_SystemReset();
}

 

 

 

 

View solution in original post

6 REPLIES 6
TDK
Guru

At startup, initialize SCL as GPIO output (open drain) and toggle it 9 times in order to reset the slaves on the bus.

 

If you feel a post has answered your question, please click "Accept as Solution".
mfrank9
Associate III

That would work for sure.
But that would only be a workaround and the actual problem would not be solved.
I'm assuming that this will still be fixed, as this can affect other users and is generally an ugly behavior.

Consider if the debugger breaks in whilst code is executing, add some significant delay in Reset Handler so control can be gained prior to main code execution.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

This is how the I2C bus works for slaves, it's not something that can be fixed apart from toggling SCL. Slaves are literally required to behave this way in order to be I2C compliant.

SMBUS implements a timeout which gets around this issue.

> The problem is that when debugging, the ST-Link restarts the program and then breaks.

Okay, I see your complaint now. Yes, it does restart the connection twice which theoretically could be changed. The eclipse framework imposes some challenges with changing how things work. You can add a startup delay as a workaround.

> I'm assuming that this will still be fixed

I would not assume that, personally.

If you feel a post has answered your question, please click "Accept as Solution".

Watch also if the code could have started a watchdog before the debugger gains control and then starts the MCU code execution over from the beginning.

Low power modes, or pin reconfiguration, can also cause connections to drop.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

The following worked for me.
However, there seem to be internal flags that are not reset correctly.
The I2C was still busy but the SDA level was finally high again.
I was only able to fix this with a software reset.

 

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C3_Init();
/* USER CODE BEGIN 2 */

Toogle_I2C_Clk_Pin(
  &hi2c3,
  MX_I2C3_Init, HAL_I2C_DeInit,
  GPIOA, GPIO_PIN_8,
  0b1010000 <<1);

 

 

static void Toogle_I2C_Clk_Pin(
      I2C_HandleTypeDef *hicPtr,
      void (*MX_I2CX_Init)(void),
      HAL_StatusTypeDef (*HAL_I2C_DeInit)(I2C_HandleTypeDef *hi2c),
      GPIO_TypeDef* clkGPIOx, uint16_t clkGPIO_Pin)
{
  if(clkGPIOx == NULL) return;
  if(MX_I2CX_Init == NULL) return;
  if(HAL_I2C_DeInit == NULL) return;

  HAL_StatusTypeDef state = HAL_I2C_IsDeviceReady(hicPtr, 0b1010000 <<1, 50, 5);

  if(state != HAL_BUSY) return;

  HAL_I2C_DeInit(hicPtr);

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  // __HAL_RCC_GPIOH_CLK_ENABLE();
  // __HAL_RCC_GPIOA_CLK_ENABLE();
  // __HAL_RCC_GPIOC_CLK_ENABLE();
  // __HAL_RCC_GPIOB_CLK_ENABLE();


  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(clkGPIOx, clkGPIO_Pin, GPIO_PIN_SET);


  GPIO_InitStruct.Pin = clkGPIO_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(clkGPIOx, &GPIO_InitStruct);

  //9 Flanken ausgeben
  for(uint8_t i =0; i < 9; i++)
  {
    HAL_GPIO_TogglePin(clkGPIOx, clkGPIO_Pin);
    HAL_Delay(1);
  }

  HAL_GPIO_WritePin(clkGPIOx, clkGPIO_Pin, GPIO_PIN_SET);

  MX_I2CX_Init();

  state = HAL_I2C_IsDeviceReady(hicPtr, 0b1010000 <<1, 50, 5);

  NVIC_SystemReset();
}