title: STM32 how to recover from lock up
body: <p>I am trying to communicate with an SMBus battery. That has 2 sections so I am using 2 I2C modules. After the first I2C module makes a successful communication second module gets stuck. And it gets stuck in Busy. In that case I thought I need to reset that I2C module. However, I could not do it. </p>
  
  <p>I tried following ways:</p>
  
  <p>1) By using HAL library deiniting and then initing the module again:</p>
  
  <pre><code>HAL_I2C_DeInit(&amp;hi2c1);
  HAL_I2C_Init(&amp;hi2c1);
  </code></pre>
  
  <p>2) Adding Swrst lines to first method:</p>
  
  <pre><code>//Set Swrst bit
          I2C2-&gt;CR1 |= I2C_CR1_SWRST;
  //Clear Swrst bit
      I2C2-&gt;CR1 &amp;= ~(I2C_CR1_SWRST);
      HAL_I2C_DeInit(&amp;hi2c1);
      HAL_I2C_Init(&amp;hi2c1);
  </code></pre>
  
  <p>3)</p>
  
  <pre><code> __HAL_RCC_I2C1_CLK_ENABLE();
   __HAL_RCC_I2C1_FORCE_RESET();
   __HAL_RCC_I2C1_RELEASE_RESET();
  </code></pre>
  
  <p>4) Using the errata document and this line of codes:</p>
  
  <pre><code>void I2C_Errate_Workaround(int module){
  
      if(module==1){
          //Disable The I2C's
          I2C1 -&gt; CR1 &amp;= ~(I2C_CR1_PE);
          //Pins are general purpose output open-drain
          GPIOB-&gt;CRL |= 0b01&lt;&lt;24; //I2C1 SCL Open Drain
          GPIOB-&gt;CRL |= 0b01&lt;&lt;28; //I2C1 SDA Open Drain
          //Make SCL/SDA High
          GPIOB-&gt; ODR |= GPIO_ODR_ODR6;
          GPIOB -&gt; ODR |= GPIO_ODR_ODR7;
          //Check whether pins are high
          if((GPIOB-&gt;IDR &amp; GPIO_PIN_6) == GPIO_PIN_RESET || (GPIOB -&gt;IDR &amp; GPIO_PIN_7) == GPIO_PIN_RESET)
          {
              for(;;){}
          }
          //SDA Low Level
          GPIOB-&gt;ODR &amp;= ~(GPIO_ODR_ODR7);
          // Check if SDA pins are really low
          if((GPIOB-&gt;IDR &amp; GPIO_PIN_7)== GPIO_PIN_SET){
              for(;;){}
          }
          // SCL Pin to Low
          GPIOB -&gt; ODR &amp;= ~(GPIO_ODR_ODR6);
          // Check whether SCL pins are cleared
          if((GPIOB-&gt;IDR &amp; GPIO_PIN_6)== GPIO_PIN_SET){
              for(;;){}
          }
          //Configure SCL to High
          GPIOB-&gt;ODR |= GPIO_ODR_ODR6;
          //Check if SCL High
          if((GPIOB-&gt;IDR &amp; GPIO_PIN_6)== GPIO_PIN_RESET)
          {
              for(;;){}
          }
          //Set SDA High
          GPIOB-&gt;ODR |=GPIO_ODR_ODR7;
          //Check if SDA high
          if((GPIOB-&gt;IDR &amp; GPIO_PIN_7)== GPIO_PIN_RESET)
          {
              for(;;){}
          }
          //Set all to alternate function open drain
          GPIOB-&gt;CRL |= 0b11&lt;&lt;24; //I2C1 SCL Open Drain
          GPIOB-&gt;CRL |= 0b11&lt;&lt;28; //I2C1 SDA Open Drain
          //Set Swrst bit
          I2C1-&gt;CR1 |= I2C_CR1_SWRST;
          //Clear Swrst bit
          I2C1-&gt;CR1 &amp;= ~(I2C_CR1_SWRST);
          //Enable I2C modules
          I2C1-&gt;CR1 |= I2C_CR1_PE;
      } else if (module ==2){
          //Disable The I2C's
          I2C2 -&gt; CR1 &amp;= ~( I2C_CR1_PE);
          // Pins are general purpose output open-drain
          GPIOB-&gt;CRH |= 0b01&lt;&lt;8;
          GPIOB-&gt;CRH |= 0b01&lt;&lt;10;
          //Set pins as outputs
          GPIOB -&gt; ODR |= GPIO_ODR_ODR10;
          GPIOB -&gt; ODR |= GPIO_ODR_ODR11;
          //Check whether pins are high
          if((GPIOB -&gt;IDR &amp; GPIO_PIN_11) == GPIO_PIN_RESET || (GPIOB -&gt; IDR &amp; GPIO_PIN_10)== GPIO_PIN_RESET)
          {
              for(;;){}
          }
          //SDA Low Level
          GPIOB -&gt;ODR &amp;= ~(GPIO_ODR_ODR11);
          // Check if SDA pins are really low
          if((GPIOB-&gt;IDR &amp; GPIO_PIN_11)== GPIO_PIN_SET)
          {
              for(;;){}
          }
          // SCL Pins to Low
          GPIOB -&gt; ODR &amp;= ~(GPIO_ODR_ODR10);
          // Check whether SCL pins are cleared
          if((GPIOB-&gt;IDR &amp; GPIO_PIN_10)== GPIO_PIN_SET)
          {
              for(;;){}
          }
          //Configure SCL to High
          GPIOB-&gt;ODR |= GPIO_ODR_ODR10;
          //Check if SCL High
          if((GPIOB-&gt; IDR &amp; GPIO_PIN_10)== GPIO_PIN_RESET)
          {
              for(;;){}
          }
          //Set SDA High
          GPIOB-&gt;ODR |= GPIO_ODR_ODR11;
  
          //Check if SDA high
          if((GPIOB-&gt;IDR &amp; GPIO_PIN_11)== GPIO_PIN_RESET)
          {
              for(;;){}
          }
          //Set all to alternate function open drain
          GPIOB-&gt;CRH |= 0b11&lt;&lt;8; // I2C2 SCL Open Drain
          GPIOB-&gt;CRH |= 0b11&lt;&lt;10; //I2C2 SDA Open Drain
          //Set Swrst bit
          I2C2-&gt;CR1 |= I2C_CR1_SWRST;
          //Clear Swrst bit
          I2C2-&gt;CR1 &amp;= ~(I2C_CR1_SWRST);
          //Enable I2C modules
          I2C2-&gt;CR1 |= I2C_CR1_PE;
      }
  }
  </code></pre>
  
  <p>Is there a proper way to reset the I2C module in STM32? How can I recover from a lockup? </p>
  
  <p>Edit: I am using STM32F103C8. Now I added MX_GPIO_Init function and I can reset the modules : </p>
  
  <pre><code>        HAL_I2C_DeInit(&amp;hi2c2);
          osDelay(50);
          MX_GPIO_Init();
          HAL_I2C_Init(&amp;hi2c2);
  </code></pre>
  
  <p>But second module in the transmission always fails. If I use hi2c1 first then hi2c2 then hi2c2 fails. If I use hi2c2 first then vice versa. I tried to disable first module then try to communicate with second one but that did not work neither.</p>