#include <stdio.h> #include <stdlib.h> #include <string.h> #include "aos_hal_i2c.h" #include "board_mgr.h" #include "py/builtin.h" #include "py/mperrno.h" #include "py/obj.h" #include "py/runtime.h" #include "ulog/ulog.h" #define LOG_TAG "DRIVER_I2C" #define I2C_CHECK_PARAMS(count) \ if (n_args < count) { \ LOGE(LOG_TAG, "%s: args count is illegal: n_args = %d;\n", __func__, n_args); \ return MP_OBJ_NEW_SMALL_INT(-MP_E2BIG); \ } \ mp_i2c_obj_t *driver_obj = (mp_i2c_obj_t *)MP_OBJ_TO_PTR(args[0]); \ do { \ if (driver_obj == NULL) { \ LOGE(LOG_TAG, "driver_obj[I2C] is NULL\n"); \ return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); \ } \ } while (0) #define I2C_NODE_GET() \ i2c_dev_t *i2c_device = py_board_get_node_by_handle(MODULE_I2C, &(driver_obj->i2c_handle)); \ do { \ if (NULL == i2c_device) { \ LOGE(LOG_TAG, "%s: py_board_get_node_by_handle failed;\n", __func__); \ py_board_disattach_item(MODULE_I2C, &(driver_obj->i2c_handle)); \ return MP_OBJ_NEW_SMALL_INT(-MP_ENXIO); \ } \ } while (0) #define I2C_TIMEOUT_MS (0xFFFFFF) #define I2C_CHANNEL_MAX (4) static bool g_is_dev_inited[I2C_CHANNEL_MAX] = { 0 }; extern const mp_obj_type_t driver_i2c_type; // this is the actual C-structure for our new object typedef struct { // base represents some basic information, like type mp_obj_base_t Base; const char *ModuleName; item_handle_t i2c_handle; } mp_i2c_obj_t; void i2c_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "ModuleName(%s)", self->ModuleName); } STATIC mp_obj_t i2c_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_i2c_obj_t *driver_obj = m_new_obj(mp_i2c_obj_t); if (!driver_obj) { mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Memory malloc failed")); } memset(driver_obj, 0, sizeof(mp_i2c_obj_t)); driver_obj->Base.type = &driver_i2c_type; driver_obj->ModuleName = "i2c"; return MP_OBJ_FROM_PTR(driver_obj); } STATIC mp_obj_t i2c_open(size_t n_args, const mp_obj_t *args) { int ret = -1; I2C_CHECK_PARAMS(2); char *id = NULL; if (mp_obj_is_str(args[1])) { id = (char *)mp_obj_str_get_str(args[1]); } else { LOGE(LOG_TAG, "%s: 2nd arg should be string\n", __func__); return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); } ret = py_board_mgr_init(); if (ret != 0) { LOGE(LOG_TAG, "%s:py_board_mgr_init failed\n", __func__); return MP_OBJ_NEW_SMALL_INT(-MP_ENOENT); } ret = py_board_attach_item(MODULE_I2C, id, &(driver_obj->i2c_handle)); if (ret != 0) { LOGE(LOG_TAG, "%s: py_board_attach_item[%s] failed, ret = %d;\n", __func__, id, ret); goto fail; } I2C_NODE_GET(); LOGD(LOG_TAG, "%s: port = %d;\n", __func__, i2c_device->port); LOGD(LOG_TAG, "%s: address_width = %d;\n", __func__, i2c_device->config.address_width); LOGD(LOG_TAG, "%s: freq = %d;\n", __func__, i2c_device->config.freq); LOGD(LOG_TAG, "%s: mode = %d;\n", __func__, i2c_device->config.mode); LOGD(LOG_TAG, "%s: dev_addr = %d;\n", __func__, i2c_device->config.dev_addr); if (i2c_device->port >= I2C_CHANNEL_MAX) { ret = -MP_ENODEV; goto fail; } if (g_is_dev_inited[i2c_device->port] == false) { ret = aos_hal_i2c_init(i2c_device); } else { ret = 0; } fail: if (ret < 0) { py_board_disattach_item(MODULE_I2C, &(driver_obj->i2c_handle)); } else { g_is_dev_inited[i2c_device->port] = true; } return MP_OBJ_NEW_SMALL_INT(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(i2c_open_obj, 2, i2c_open); STATIC mp_obj_t i2c_close(size_t n_args, const mp_obj_t *args) { int ret = -1; I2C_CHECK_PARAMS(1); I2C_NODE_GET(); if (g_is_dev_inited[i2c_device->port] == true) { ret = aos_hal_i2c_finalize(i2c_device); if (ret == 0) { g_is_dev_inited[i2c_device->port] = false; py_board_disattach_item(MODULE_I2C, &(driver_obj->i2c_handle)); } } else { ret = 0; } if (ret < 0) { LOGE(LOG_TAG, "%s: i2c_close failed\n", __func__); } return MP_OBJ_NEW_SMALL_INT(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(i2c_close_obj, 1, i2c_close); STATIC mp_obj_t i2c_write(size_t n_args, const mp_obj_t *args) { int ret = -1; I2C_CHECK_PARAMS(3); I2C_NODE_GET(); mp_buffer_info_t bufinfo = { 0 }; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); char *buf = (char *)bufinfo.buf; mp_uint_t write_size = mp_obj_get_int(args[2]); if (write_size > bufinfo.len) { LOGE(LOG_TAG, "%s: write size[%d] exceed buffer size[%d]\n", __func__, write_size, bufinfo.len); return MP_OBJ_NEW_SMALL_INT(-MP_ENFILE); } ret = aos_hal_i2c_mem_write(i2c_device, i2c_device->config.dev_addr, buf[0], 1, &buf[1], write_size - 1, I2C_TIMEOUT); if (ret < 0) { LOGE(LOG_TAG, "aos_hal_i2c_mem_write failed\n"); return MP_OBJ_NEW_SMALL_INT(ret); } else { return MP_OBJ_NEW_SMALL_INT(write_size); } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(i2c_write_obj, 3, i2c_write); STATIC mp_obj_t i2c_read(size_t n_args, const mp_obj_t *args) { int ret = -1; I2C_CHECK_PARAMS(2); I2C_NODE_GET(); mp_buffer_info_t bufinfo = { 0 }; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); const char *buf = (const char *)bufinfo.buf; mp_uint_t read_size = mp_obj_get_int(args[2]); if (read_size > bufinfo.len) { LOGE(LOG_TAG, "%s: read size[%d] exceed buffer size[%d]\n", __func__, read_size, bufinfo.len); return MP_OBJ_NEW_SMALL_INT(-MP_ENFILE); } ret = aos_hal_i2c_mem_write(i2c_device, i2c_device->config.dev_addr, buf[0], 1, &buf[0], 1, I2C_TIMEOUT); if (ret < 0) { LOGE(LOG_TAG, "aos_hal_i2c_master_send failed\n"); return MP_OBJ_NEW_SMALL_INT(ret); } ret = aos_hal_i2c_mem_read(i2c_device, i2c_device->config.dev_addr, buf[0], 1, &buf[0], read_size, I2C_TIMEOUT_MS); if (ret < 0) { LOGE(LOG_TAG, "hal_i2c_master_recv failed\n"); return MP_OBJ_NEW_SMALL_INT(ret); } else { return MP_OBJ_NEW_SMALL_INT(read_size); } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(i2c_read_obj, 2, i2c_read); STATIC const mp_rom_map_elem_t i2c_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_I2C) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&i2c_open_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&i2c_close_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&i2c_read_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&i2c_write_obj) }, }; STATIC MP_DEFINE_CONST_DICT(i2c_locals_dict, i2c_locals_dict_table); const mp_obj_type_t driver_i2c_type = { .base = { &mp_type_type }, .name = MP_QSTR_I2C, .print = i2c_obj_print, .make_new = i2c_obj_make_new, .locals_dict = (mp_obj_dict_t *)&i2c_locals_dict, };