diff --git a/ports/psoc6/main.c b/ports/psoc6/main.c index 9641fe25d1e9..da9916081d54 100644 --- a/ports/psoc6/main.c +++ b/ports/psoc6/main.c @@ -58,6 +58,7 @@ extern void network_init(void); extern void network_deinit(void); extern void mod_pin_deinit(void); extern void mod_adc_block_deinit(void); +extern void mod_i2c_deinit(void); void mpy_task(void *arg); @@ -179,6 +180,7 @@ void mpy_task(void *arg) { machine_deinit(); mod_pin_deinit(); mod_adc_block_deinit(); + mod_i2c_deinit(); mod_pin_phy_deinit(); #if MICROPY_PY_NETWORK mod_network_deinit(); diff --git a/ports/psoc6/modules/machine/machine_i2c.c b/ports/psoc6/modules/machine/machine_i2c.c index 4c971d6b293d..29d22d5860f9 100644 --- a/ports/psoc6/modules/machine/machine_i2c.c +++ b/ports/psoc6/modules/machine/machine_i2c.c @@ -15,26 +15,46 @@ // port-specific includes #include "modmachine.h" +#include "machine_pin_phy.h" #include "mplogger.h" +#define MAX_I2C 10 // TODO: Change as per bsp? #define DEFAULT_I2C_FREQ (400000) -#define MICROPY_HW_I2C_SCL (CYBSP_I2C_SCL) -#define MICROPY_HW_I2C_SDA (CYBSP_I2C_SDA) #define PSOC_I2C_MASTER_MODE (CYHAL_I2C_MODE_MASTER) typedef struct _machine_i2c_obj_t { mp_obj_base_t base; cyhal_i2c_t i2c_obj; uint8_t i2c_id; - uint8_t scl; - uint8_t sda; + machine_pin_phy_obj_t *scl; + machine_pin_phy_obj_t *sda; uint32_t freq; } machine_i2c_obj_t; -STATIC cy_rslt_t i2c_init(machine_i2c_obj_t *machine_i2c_obj) { - // free first in case object has been initialized before - cyhal_i2c_free(&machine_i2c_obj->i2c_obj); +machine_i2c_obj_t *i2c_obj[MAX_I2C] = { NULL }; + +static inline machine_i2c_obj_t *i2c_obj_alloc() { + for (uint8_t i = 0; i < MAX_I2C; i++) + { + if (i2c_obj[i] == NULL) { + i2c_obj[i] = mp_obj_malloc(machine_i2c_obj_t, &machine_i2c_type); + return i2c_obj[i]; + } + } + return NULL; +} + +static inline void i2c_obj_free(machine_i2c_obj_t *i2c_obj_ptr) { + for (uint8_t i = 0; i < MAX_I2C; i++) + { + if (i2c_obj[i] == i2c_obj_ptr) { + i2c_obj[i] = NULL; + } + } +} + +STATIC cy_rslt_t i2c_init(machine_i2c_obj_t *machine_i2c_obj) { // Define the I2C master configuration structure cyhal_i2c_cfg_t i2c_master_config = { @@ -44,28 +64,47 @@ STATIC cy_rslt_t i2c_init(machine_i2c_obj_t *machine_i2c_obj) { }; // Initialize I2C master, set the SDA and SCL pins and assign a new clock - cy_rslt_t result = cyhal_i2c_init(&machine_i2c_obj->i2c_obj, machine_i2c_obj->sda, machine_i2c_obj->scl, NULL); + cy_rslt_t result = cyhal_i2c_init(&machine_i2c_obj->i2c_obj, machine_i2c_obj->sda->addr, machine_i2c_obj->scl->addr, NULL); return result == CY_RSLT_SUCCESS ? cyhal_i2c_configure(&machine_i2c_obj->i2c_obj, &i2c_master_config) : result; } -STATIC cy_rslt_t i2c_read(cyhal_i2c_t *i2c_obj, uint16_t addr, uint8_t *buf, size_t len, uint32_t timeout, bool send_stop) { - return cyhal_i2c_master_read(i2c_obj, addr, buf, len, timeout, send_stop); +STATIC inline void i2c_sda_alloc(machine_i2c_obj_t *i2c_obj, mp_obj_t pin_name) { + machine_pin_phy_obj_t *sda = pin_phy_realloc(pin_name, PIN_PHY_FUNC_I2C); + + if (sda == NULL) { + size_t slen; + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SDA pin (%s) not found !"), mp_obj_str_get_data(pin_name, &slen)); + } + + i2c_obj->sda = sda; +} + +STATIC inline void i2c_sda_free(machine_i2c_obj_t *i2c_obj) { + pin_phy_free(i2c_obj->sda); } -STATIC cy_rslt_t i2c_write(cyhal_i2c_t *i2c_obj, uint16_t addr, uint8_t *buf, size_t len, uint32_t timeout, bool send_stop) { - return cyhal_i2c_master_write(i2c_obj, addr, buf, len, timeout, send_stop); +STATIC inline void i2c_scl_alloc(machine_i2c_obj_t *i2c_obj, mp_obj_t pin_name) { + machine_pin_phy_obj_t *scl = pin_phy_realloc(pin_name, PIN_PHY_FUNC_I2C); + + if (scl == NULL) { + size_t slen; + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SCL pin (%s) not found !"), mp_obj_str_get_data(pin_name, &slen)); + } + + i2c_obj->scl = scl; } -extern mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj); +STATIC inline void i2c_scl_free(machine_i2c_obj_t *i2c_obj) { + pin_phy_free(i2c_obj->scl); +} STATIC void machine_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "I2C(%u, freq=%u, scl=%u, sda=%u)", self->i2c_id, self->freq, self->scl, self->sda); + mp_printf(print, "I2C(%u, freq=%u, scl=%u, sda=%u)", self->i2c_id, self->freq, self->scl->addr, self->sda->addr); } - mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mplogger_print("%q constructor invoked\n", MP_QSTR_I2C); enum { ARG_id, ARG_freq, ARG_scl, ARG_sda }; @@ -88,35 +127,20 @@ mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("I2C id '%d' not supported !"), i2c_id); } - machine_i2c_obj_t *self = mp_obj_malloc(machine_i2c_obj_t, &machine_i2c_type); - self->base.type = &machine_i2c_type; + machine_i2c_obj_t *self = i2c_obj_alloc(); self->i2c_id = i2c_id; - // get scl & Sda pins & configure them + // get scl & sda pins & configure them if (args[ARG_scl].u_obj != mp_const_none) { - int scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj); - - if (self->scl == -1) { - size_t slen; - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SCL pin (%s) not found !"), mp_obj_str_get_data(args[ARG_scl].u_obj, &slen)); - } - - self->scl = scl; + i2c_scl_alloc(self, args[ARG_scl].u_obj); } else { - self->scl = MICROPY_HW_I2C_SCL; + mp_raise_TypeError(MP_ERROR_TEXT("SCL pin must be provided")); } - if (args[ARG_sda].u_obj != mp_const_none) { - int sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj); - - if (self->sda == -1) { - size_t slen; - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SDA pin (%s) not found !"), mp_obj_str_get_data(args[ARG_sda].u_obj, &slen)); - } - self->sda = sda; + i2c_sda_alloc(self, args[ARG_sda].u_obj); } else { - self->sda = MICROPY_HW_I2C_SDA; + mp_raise_TypeError(MP_ERROR_TEXT("SDA pin must be provided")); } self->freq = args[ARG_freq].u_int; @@ -130,6 +154,13 @@ mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n return MP_OBJ_FROM_PTR(self); } +STATIC void machine_i2c_deinit(mp_obj_base_t *self_in) { + machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + cyhal_i2c_free(&(self->i2c_obj)); + i2c_sda_free(self); + i2c_scl_free(self); + i2c_obj_free(self); +} STATIC int machine_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags) { machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -138,7 +169,7 @@ STATIC int machine_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t le uint32_t timeout = 0; if ((flags & MP_MACHINE_I2C_FLAG_READ) == MP_MACHINE_I2C_FLAG_READ) { - result = i2c_read(&self->i2c_obj, addr, buf, len, timeout, send_stop); + result = cyhal_i2c_master_read(&self->i2c_obj, addr, buf, len, timeout, send_stop); if (result != CY_RSLT_SUCCESS) { mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("cyhal_i2c_master_read failed with return code %lx !"), result); @@ -148,7 +179,7 @@ STATIC int machine_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t le } else { // handle scan type bus checks and send stop if (buf == NULL) { - result = i2c_write(&self->i2c_obj, addr, buf, 0, 50, send_stop); + result = cyhal_i2c_master_write(&self->i2c_obj, addr, buf, 0, 50, send_stop); if ((result != CY_RSLT_SUCCESS)) { // these 2 errors occur if nothing is attached to sda/scl, but they are pulled-up (0xaa2004) or not pulled-up (0xaa2003). @@ -162,8 +193,7 @@ STATIC int machine_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t le return len; } else { - result = i2c_write(&self->i2c_obj, addr, buf, len, timeout, send_stop); - + result = cyhal_i2c_master_write(&self->i2c_obj, addr, buf, len, timeout, send_stop); if (result != CY_RSLT_SUCCESS) { mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("cyhal_i2c_master_write failed with return code %lx !"), result); } @@ -173,13 +203,12 @@ STATIC int machine_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t le } } - STATIC const mp_machine_i2c_p_t machine_i2c_p = { + .deinit = machine_i2c_deinit, .transfer_single = machine_i2c_transfer, .transfer = mp_machine_i2c_transfer_adaptor }; - MP_DEFINE_CONST_OBJ_TYPE( machine_i2c_type, MP_QSTR_I2C, @@ -189,3 +218,11 @@ MP_DEFINE_CONST_OBJ_TYPE( protocol, &machine_i2c_p, locals_dict, &mp_machine_i2c_locals_dict ); + +void mod_i2c_deinit() { + for (uint8_t i = 0; i < MAX_I2C; i++) { + if (i2c_obj[i] != NULL) { + machine_i2c_deinit((mp_obj_base_t *)(i2c_obj[i])); + } + } +} diff --git a/ports/psoc6/modules/machine/machine_pin_phy.h b/ports/psoc6/modules/machine/machine_pin_phy.h index 194cb5cb4405..ec5c318fb175 100644 --- a/ports/psoc6/modules/machine/machine_pin_phy.h +++ b/ports/psoc6/modules/machine/machine_pin_phy.h @@ -22,8 +22,8 @@ typedef struct _machine_pin_phy_obj_t { extern machine_pin_phy_obj_t machine_pin_phy_obj[PIN_PHY_NUM_MAX]; bool pin_phy_is_alloc(machine_pin_phy_obj_t *obj); -machine_pin_phy_obj_t *pin_phy_alloc(mp_obj_t addr, machine_pin_phy_func_t func); -machine_pin_phy_obj_t *pin_phy_realloc(mp_obj_t addr, machine_pin_phy_func_t func); +machine_pin_phy_obj_t *pin_phy_alloc(mp_obj_t pin_name, machine_pin_phy_func_t func); +machine_pin_phy_obj_t *pin_phy_realloc(mp_obj_t pin_name, machine_pin_phy_func_t func); void pin_phy_free(machine_pin_phy_obj_t *obj); void mod_pin_phy_deinit(void);