From 98937dcfc23c29d17e0d5215ade0d5a71b2c1589 Mon Sep 17 00:00:00 2001
From: Damien George <damien@micropython.org>
Date: Thu, 9 Mar 2023 11:14:47 +1100
Subject: [PATCH] stm32/i2c: Return error code and raise exception if I2C init
 fails.

Signed-off-by: Damien George <damien@micropython.org>
---
 ports/stm32/i2c.h     |  4 ++--
 ports/stm32/pyb_i2c.c | 24 ++++++++++++------------
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/ports/stm32/i2c.h b/ports/stm32/i2c.h
index d494ad66d5..04a7e928bd 100644
--- a/ports/stm32/i2c.h
+++ b/ports/stm32/i2c.h
@@ -47,8 +47,8 @@ extern const mp_obj_type_t pyb_i2c_type;
 extern const pyb_i2c_obj_t pyb_i2c_obj[4];
 
 void i2c_init0(void);
-void pyb_i2c_init(I2C_HandleTypeDef *i2c);
-void pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq);
+int pyb_i2c_init(I2C_HandleTypeDef *i2c);
+int pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq);
 uint32_t pyb_i2c_get_baudrate(I2C_HandleTypeDef *i2c);
 void i2c_ev_irq_handler(mp_uint_t i2c_id);
 void i2c_er_irq_handler(mp_uint_t i2c_id);
diff --git a/ports/stm32/pyb_i2c.c b/ports/stm32/pyb_i2c.c
index 2463669ed0..6bf04aa1b1 100644
--- a/ports/stm32/pyb_i2c.c
+++ b/ports/stm32/pyb_i2c.c
@@ -24,10 +24,8 @@
  * THE SOFTWARE.
  */
 
-#include <stdio.h>
-#include <string.h>
-
 #include "py/runtime.h"
+#include "py/mperrno.h"
 #include "py/mphal.h"
 #include "irq.h"
 #include "pin.h"
@@ -290,7 +288,7 @@ void i2c_init0(void) {
     #endif
 }
 
-void pyb_i2c_init(I2C_HandleTypeDef *i2c) {
+int pyb_i2c_init(I2C_HandleTypeDef *i2c) {
     int i2c_unit;
     const pin_obj_t *scl_pin;
     const pin_obj_t *sda_pin;
@@ -326,7 +324,7 @@ void pyb_i2c_init(I2C_HandleTypeDef *i2c) {
     #endif
     } else {
         // I2C does not exist for this board (shouldn't get here, should be checked by caller)
-        return;
+        return -MP_EINVAL;
     }
 
     // init the GPIO lines
@@ -338,10 +336,7 @@ void pyb_i2c_init(I2C_HandleTypeDef *i2c) {
     // init the I2C device
     if (HAL_I2C_Init(i2c) != HAL_OK) {
         // init error
-        // TODO should raise an exception, but this function is not necessarily going to be
-        // called via Python, so may not be properly wrapped in an NLR handler
-        printf("OSError: HAL_I2C_Init failed\n");
-        return;
+        return -MP_EIO;
     }
 
     // invalidate the DMA channels so they are initialised on first use
@@ -371,6 +366,8 @@ void pyb_i2c_init(I2C_HandleTypeDef *i2c) {
         HAL_NVIC_EnableIRQ(I2C4_ER_IRQn);
     #endif
     }
+
+    return 0; // success
 }
 
 void i2c_deinit(I2C_HandleTypeDef *i2c) {
@@ -411,7 +408,7 @@ void i2c_deinit(I2C_HandleTypeDef *i2c) {
     }
 }
 
-void pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq) {
+int pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq) {
     I2C_InitTypeDef *init = &self->i2c->Init;
 
     init->AddressingMode = I2C_ADDRESSINGMODE_7BIT;
@@ -428,7 +425,7 @@ void pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq) {
 
     // init the I2C bus
     i2c_deinit(self->i2c);
-    pyb_i2c_init(self->i2c);
+    return pyb_i2c_init(self->i2c);
 }
 
 STATIC void i2c_reset_after_error(I2C_HandleTypeDef *i2c) {
@@ -704,7 +701,10 @@ STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, size_t n_args, co
 
     // init the I2C bus
     i2c_deinit(self->i2c);
-    pyb_i2c_init(self->i2c);
+    int ret = pyb_i2c_init(self->i2c);
+    if (ret != 0) {
+        mp_raise_OSError(-ret);
+    }
 
     return mp_const_none;
 }