Pārlūkot izejas kodu

Add base i2c error detection.

Vladimir N. Shilov 4 gadi atpakaļ
vecāks
revīzija
176919fc06
3 mainītis faili ar 60 papildinājumiem un 19 dzēšanām
  1. 5 1
      Inc/main.h
  2. 43 18
      Src/main.c
  3. 12 0
      Src/stm32g0xx_it.c

+ 5 - 1
Inc/main.h

@@ -72,14 +72,18 @@ volatile struct {
   uint32_t SPI_TX_End:  1;
   uint32_t I2C_TX_End:  1;
   uint32_t I2C_RX_End:  1;
+  uint32_t I2C_TX_Err:  1;
+  uint32_t I2C_RX_Err:  1;
   uint32_t BME280:      1;
-  uint32_t _reserv:     27;
+  uint32_t _reserv:    25;
 } Flag;
 
 /* USER CODE END ET */
 
 /* Exported constants --------------------------------------------------------*/
 /* USER CODE BEGIN EC */
+#define I2C_RET_OK    (int8_t)0
+#define I2C_RET_NACK  (int8_t)-1
 
 /* USER CODE END EC */
 

+ 43 - 18
Src/main.c

@@ -74,7 +74,7 @@ static uint8_t tubesBuffer[SPI_BUFFER_SIZE] = {0};
 static rtc_t Clock;
 static struct bme280_dev SensorDev;
 static struct bme280_data SensorData;
-static int8_t rsltSensor = BME280_OK;
+static int8_t rsltSensor = 33; //BME280_OK;
 
 /* USER CODE END PV */
 
@@ -91,8 +91,8 @@ static void MX_TIM17_Init(void);
 /* USER CODE BEGIN PFP */
 static void showDigit(tube_pos_t pos, uint8_t dig);
 static void SPI_StartTX(void);
-static int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len);
-static int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len);
+int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len);
+int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len);
 /* USER CODE END PFP */
 
 /* Private user code ---------------------------------------------------------*/
@@ -189,7 +189,7 @@ int main(void)
   SensorDev.read = user_i2c_read;
   SensorDev.write = user_i2c_write;
   SensorDev.delay_ms = tdelay_ms;
-  rsltSensor = bme280_init(&SensorDev);
+  //rsltSensor = bme280_init(&SensorDev);
   if (rsltSensor == BME280_OK) {
     Flag.BME280 = 1;
   }
@@ -281,38 +281,57 @@ static void SPI_StartTX(void) {
   LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
 }
 
-static int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len) {
-  Flag.I2C_TX_End = 0;
-
-  DMA1_Channel2->CMAR = (uint32_t)data;
-  DMA1_Channel2->CPAR = (uint32_t)&(I2C1->RXDR);
-  DMA1_Channel2->CNDTR = len;
-  DMA1_Channel2->CCR |= DMA_CCR_EN;
+int8_t user_i2c_read(const uint8_t id, const uint8_t reg_addr, uint8_t *data, const uint16_t len) {
+  Flag.I2C_RX_End = 0;
+  Flag.I2C_RX_Err = 0;
 
+  /* wait for i2c */
   while ( I2C1->ISR & I2C_ISR_BUSY ) {};
 
+  /* 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 );
-
+  /* gen START */
   I2C1->CR2 |= ( I2C_CR2_START );
 
+  /* wait for start end */
   while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
+
+  /* check if devce is present */
+  if ((I2C1->ISR & I2C_ISR_NACKF) != 0) {
+    /* no device present, reset i2c */
+    I2C1->CR1 &= ~I2C_CR1_PE;
+    while ((I2C1->CR1 & I2C_CR1_PE) != 0) {};
+    I2C1->CR1 |= I2C_CR1_PE;
+    /* exit with NACK */
+    return I2C_RET_NACK;
+  }
+
+  /* device ok, send reg addr */
   I2C1->TXDR = reg_addr;
 
+  /* wait for i2c */
   while ( I2C1->ISR & I2C_ISR_BUSY ) {};
-  Flag.I2C_RX_End = 0;
 
+  /* prepare dma channel for receiving data */
+  DMA1_Channel2->CMAR = (uint32_t)data;
+  DMA1_Channel2->CPAR = (uint32_t)&(I2C1->RXDR);
+  DMA1_Channel2->CNDTR = len;
+  DMA1_Channel2->CCR |= DMA_CCR_EN;
+
+  /* prepare i2c for receiving data */
   I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
   I2C1->CR2 |= ( id | len << I2C_CR2_NBYTES_Pos | I2C_CR2_RD_WRN);
-
+  /* launch receiving */
   I2C1->CR1 |= ( I2C_CR1_RXDMAEN );
   I2C1->CR2 |= ( I2C_CR2_START );
 
-  return 0;
+  return I2C_RET_OK;
 }
 
-static int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len) {
+int8_t user_i2c_write(const uint8_t id, const uint8_t reg_addr, uint8_t *data, const uint16_t len) {
   Flag.I2C_TX_End = 0;
+  Flag.I2C_TX_Err = 0;
 
   //DMA1_Channel3->CCR &= ~DMA_CCR_EN;
   DMA1_Channel3->CMAR = (uint32_t)data;
@@ -323,15 +342,21 @@ static int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16
 
   I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
   I2C1->CR2 |= ( id | (len + 1) << I2C_CR2_NBYTES_Pos );
-  I2C1->CR1 |= ( I2C_CR1_TXDMAEN );
   I2C1->CR2 |= ( I2C_CR2_START );
 
   while ( !( I2C1->CR2 & I2C_CR2_START ) ) {};
+  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;
+  }
   I2C1->TXDR = reg_addr;
 
   DMA1_Channel3->CCR |= DMA_CCR_EN;
+  I2C1->CR1 |= ( I2C_CR1_TXDMAEN );
 
-  return 0;
+  return I2C_RET_OK;
 }
 
 /**

+ 12 - 0
Src/stm32g0xx_it.c

@@ -218,6 +218,12 @@ void DMA1_Channel2_3_IRQHandler(void)
     DMA1_Channel2->CCR &= ~DMA_CCR_EN;
     Flag.I2C_RX_End = 1;
   }
+  if (LL_DMA_IsActiveFlag_TE2(DMA1) != 0) {
+    DMA1->IFCR |= DMA_IFCR_CTEIF2;
+    DMA1_Channel2->CCR &= ~DMA_CCR_EN;
+    Flag.I2C_RX_End = 1;
+    Flag.I2C_RX_Err = 1;
+  }
   /* USER CODE END DMA1_Channel2_3_IRQn 0 */
 
   /* USER CODE BEGIN DMA1_Channel2_3_IRQn 1 */
@@ -228,6 +234,12 @@ void DMA1_Channel2_3_IRQHandler(void)
     DMA1_Channel3->CCR &= ~DMA_CCR_EN;
     Flag.I2C_TX_End = 1;
   }
+  if (LL_DMA_IsActiveFlag_TE3(DMA1) != 0) {
+    DMA1->IFCR |= DMA_IFCR_CTEIF3;
+    DMA1_Channel3->CCR &= ~DMA_CCR_EN;
+    Flag.I2C_TX_End = 1;
+    Flag.I2C_TX_Err = 1;
+  }
   /* USER CODE END DMA1_Channel2_3_IRQn 1 */
 }