Browse Source

Added I2C error handle.

Vladimir N. Shilov 3 years ago
parent
commit
8f8fbb7863
3 changed files with 53 additions and 25 deletions
  1. 2 2
      Inc/main.h
  2. 1 0
      Inc/stm32g0xx_it.h
  3. 50 23
      Src/main.c

+ 2 - 2
Inc/main.h

@@ -112,9 +112,9 @@ typedef union {
 /* USER CODE BEGIN EC */
 #define I2C_RET_OK    (int8_t)0
 #define I2C_RET_NACK  (int8_t)-1
-#define I2C_RET_TOUT  (int8_t)-2
+#define I2C_RET_ERR   (int8_t)-2
 
-#define I2C_SHT_ADDR  0x80
+#define SHT_I2C_ADDR  0x80
 #define SHT_SOFT_RST  0xFE
 #define SHT_STRT_HUMD 0xF5
 #define SHT_STRT_TEMP 0xF3

+ 1 - 0
Inc/stm32g0xx_it.h

@@ -59,6 +59,7 @@ void DMA1_Channel2_3_IRQHandler(void);
 void TIM14_IRQHandler(void);
 void TIM16_IRQHandler(void);
 void TIM17_IRQHandler(void);
+void I2C1_IRQHandler(void);
 void SPI1_IRQHandler(void);
 /* USER CODE BEGIN EFP */
 

+ 50 - 23
Src/main.c

@@ -322,37 +322,61 @@ static void SPI_StartTX(void) {
  * @retval I2C return code
  */
 int8_t user_i2c_read(const uint8_t id, const uint8_t reg_addr, uint8_t *data, const uint16_t len) {
+  int8_t r = 0;
+
   Flag.I2C_RX_End = 0;
   Flag.I2C_RX_Err = 0;
+  Flag.I2C_TX_Err = 0;
 
   /* wait for i2c */
-  while ( I2C1->ISR & I2C_ISR_BUSY ) {};
+  while ( I2C1->ISR & I2C_ISR_BUSY ) { __NOP(); };
 
   /* prepare i2c for sending reg addr */
   I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
   I2C1->CR2 |= ( id | 1 << I2C_CR2_NBYTES_Pos );
-  I2C1->CR1 |= I2C_CR1_NOSTRETCH;
   /* gen START */
   I2C1->CR2 |= ( I2C_CR2_START );
 
   /* wait for start end */
-  while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
+//  while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
 
-  /* check if devce is present */
-  if ((I2C1->ISR & I2C_ISR_NACKF) != 0) {
-    /* no device present, reset i2c */
+  /* wait for byte request or any error */
+  while ((I2C1->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR | I2C_ISR_STOPF | I2C_ISR_NACKF | I2C_ISR_TXE)) == 0) { __NOP(); };
+
+  if ((I2C2->ISR & I2C_ISR_TXE) != 0) {
+  /* device ok, send reg addr */
+    I2C1->TXDR = reg_addr;
+  } else if ((I2C1->ISR & I2C_ISR_NACKF) != 0) {
+  /* device not present */
+    r = I2C_RET_NACK;
+  } else {
+  /* other error */
+    r = I2C_RET_ERR;
+  }
+  if (r != 0) {
+    Flag.I2C_TX_Err = 1;
     I2C1->CR1 &= ~I2C_CR1_PE;
     while ((I2C1->CR1 & I2C_CR1_PE) != 0) {};
     I2C1->CR1 |= I2C_CR1_PE;
-    /* exit with NACK */
-    return I2C_RET_NACK;
+    return r;
   }
 
-  /* device ok, send reg addr */
-  I2C1->TXDR = reg_addr;
-
-  /* wait for i2c */
-  while ( I2C1->ISR & I2C_ISR_BUSY ) {
+  /* wait for i2c or any error */
+  while (((I2C1->ISR & I2C_ISR_BUSY) != 0) && ((I2C1->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR | I2C_ISR_STOPF | I2C_ISR_NACKF)) == 0)) { __NOP(); };
+  /* check for errors */
+  if ((I2C1->ISR & I2C_ISR_NACKF) != 0) {
+  /* device not present */
+    r = I2C_RET_NACK;
+  } else if ((I2C1->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR | I2C_ISR_STOPF)) != 0) {
+  /* other error */
+    r = I2C_RET_ERR;
+  }
+  if (r != 0) {
+    Flag.I2C_TX_Err = 1;
+    I2C1->CR1 &= ~I2C_CR1_PE;
+    while ((I2C1->CR1 & I2C_CR1_PE) != 0) {};
+    I2C1->CR1 |= I2C_CR1_PE;
+    return r;
   }
 
   /* prepare dma channel for receiving data */
@@ -368,6 +392,7 @@ int8_t user_i2c_read(const uint8_t id, const uint8_t reg_addr, uint8_t *data, co
   I2C1->CR1 |= ( I2C_CR1_RXDMAEN );
   I2C1->CR2 |= ( I2C_CR2_START );
 
+  /* wait for receiving data */
   while (Flag.I2C_RX_End == 0) {};
 
   return I2C_RET_OK;
@@ -392,13 +417,15 @@ int8_t user_i2c_write(const uint8_t id, const uint8_t reg_addr, uint8_t *data, c
   I2C1->CR2 |= ( id | (len + 1) << I2C_CR2_NBYTES_Pos );
   I2C1->CR2 |= ( I2C_CR2_START );
 
-  while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
-  I2C1->TXDR = reg_addr;
-  if ((I2C1->ISR & I2C_ISR_NACKF) != 0) {
+//  while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
+  while ((I2C1->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR | I2C_ISR_STOPF | I2C_ISR_NACKF | I2C_ISR_TXE)) == 0) { __NOP(); };
+  if ((I2C2->ISR & I2C_ISR_TXE) != 0) {
+    I2C1->TXDR = reg_addr;
+  } else { /* if ((I2C1->ISR & I2C_ISR_NACKF) != 0) */
     I2C1->CR1 &= ~I2C_CR1_PE;
     while ((I2C1->CR1 & I2C_CR1_PE) != 0) {};
     I2C1->CR1 |= I2C_CR1_PE;
-    return I2C_RET_NACK;
+    return I2C_RET_ERR;
   }
 
   DMA1_Channel3->CCR |= DMA_CCR_EN;
@@ -426,7 +453,7 @@ int8_t user_i2c_write_byte(const uint8_t id, const uint8_t data) {
   /* wait for start end */
   while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
 
-  /* check if devce is present */
+  /* check if device is present */
   if ((I2C1->ISR & I2C_ISR_NACKF) != 0) {
     /* no device present, reset i2c */
     I2C1->CR1 &= ~I2C_CR1_PE;
@@ -449,7 +476,7 @@ int8_t user_i2c_write_byte(const uint8_t id, const uint8_t data) {
 static int8_t SHT_Init(void) {
   int8_t res;
 
-  res = user_i2c_write_byte (I2C_SHT_ADDR, SHT_SOFT_RST);
+  res = user_i2c_write_byte (SHT_I2C_ADDR, SHT_SOFT_RST);
   if (res == I2C_RET_OK) {
       tdelay_ms(15);
   }
@@ -464,7 +491,7 @@ static int8_t SHT_Init(void) {
 static int8_t SHT_StartH(void) {
   int8_t res;
 
-  res = user_i2c_write_byte (I2C_SHT_ADDR, SHT_STRT_HUMD);
+  res = user_i2c_write_byte (SHT_I2C_ADDR, SHT_STRT_HUMD);
   if (res == I2C_RET_OK) {
       tdelay_ms(16);
   }
@@ -478,7 +505,7 @@ static int8_t SHT_StartH(void) {
 static int8_t SHT_StartT(void) {
   int8_t res;
 
-  res = user_i2c_write_byte (I2C_SHT_ADDR, SHT_STRT_TEMP);
+  res = user_i2c_write_byte (SHT_I2C_ADDR, SHT_STRT_TEMP);
   if (res == I2C_RET_OK) {
       tdelay_ms(50);
   }
@@ -506,7 +533,7 @@ static int16_t SHT_GetH(void) {
 
   /* prepare i2c for receiving data */
   I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
-  I2C1->CR2 |= ( I2C_SHT_ADDR | SHT_DATA_LEN << I2C_CR2_NBYTES_Pos | I2C_CR2_RD_WRN);
+  I2C1->CR2 |= ( SHT_I2C_ADDR | SHT_DATA_LEN << I2C_CR2_NBYTES_Pos | I2C_CR2_RD_WRN);
   /* launch receiving */
   I2C1->CR1 |= ( I2C_CR1_RXDMAEN );
   I2C1->CR2 |= ( I2C_CR2_START );
@@ -544,7 +571,7 @@ static int16_t SHT_GetT(void) {
 
   /* prepare i2c for receiving data */
   I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
-  I2C1->CR2 |= ( I2C_SHT_ADDR | SHT_DATA_LEN << I2C_CR2_NBYTES_Pos | I2C_CR2_RD_WRN);
+  I2C1->CR2 |= ( SHT_I2C_ADDR | SHT_DATA_LEN << I2C_CR2_NBYTES_Pos | I2C_CR2_RD_WRN);
   /* launch receiving */
   I2C1->CR1 |= ( I2C_CR1_RXDMAEN );
   I2C1->CR2 |= ( I2C_CR2_START );