1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 
5 #include "aos_hal_spi.h"
6 #include "board_mgr.h"
7 #include "py/builtin.h"
8 #include "py/mperrno.h"
9 #include "py/obj.h"
10 #include "py/runtime.h"
11 #include "ulog/ulog.h"
12 
13 #define LOG_TAG "driver_spi"
14 
15 extern const mp_obj_type_t driver_spi_type;
16 
17 #define SPI_CHECK_PARAMS(cnt)                                                       \
18     if (n_args < cnt) {                                                             \
19         LOGE(LOG_TAG, "%s: args num is illegal :n_args = %d;\n", __func__, n_args); \
20         return MP_OBJ_NEW_SMALL_INT(-MP_E2BIG);                                     \
21     }                                                                               \
22     mp_spi_obj_t *driver_obj = (mp_spi_obj_t *)MP_OBJ_TO_PTR(args[0]);              \
23     do {                                                                            \
24         if (driver_obj == NULL) {                                                   \
25             LOGE(LOG_TAG, "driver_obj[SPI]] is NULL\n");                            \
26             return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL);                                \
27         }                                                                           \
28     } while (0)
29 
30 #define SPI_NODE_GET()                                                                          \
31     spi_dev_t *spi_device = py_board_get_node_by_handle(MODULE_SPI, &(driver_obj->spi_handle)); \
32     do {                                                                                        \
33         if (NULL == spi_device) {                                                               \
34             LOGE(LOG_TAG, "%s: py_board_get_node_by_handle failed;\n", __func__);               \
35             py_board_disattach_item(MODULE_SPI, &(driver_obj->spi_handle));                     \
36             return MP_OBJ_NEW_SMALL_INT(-MP_ENXIO);                                             \
37         }                                                                                       \
38     } while (0)
39 
40 #define SPI_TIMEOUT (1000)
41 
42 // this is the actual C-structure for our new object
43 typedef struct {
44     // base represents some basic information, like type
45     mp_obj_base_t Base;
46     // a member created by us
47     char *ModuleName;
48     item_handle_t spi_handle;
49 } mp_spi_obj_t;
50 
spi_obj_print(const mp_print_t * print,mp_obj_t self_in,mp_print_kind_t kind)51 void spi_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
52 {
53     mp_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
54     mp_printf(print, "ModuleName(%s)", self->ModuleName);
55 }
56 
spi_obj_make_new(const mp_obj_type_t * type,size_t n_args,size_t n_kw,const mp_obj_t * args)57 STATIC mp_obj_t spi_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args)
58 {
59     mp_spi_obj_t *driver_obj = m_new_obj(mp_spi_obj_t);
60     if (!driver_obj) {
61         mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Memory malloc failed"));
62     }
63     memset(driver_obj, 0, sizeof(mp_spi_obj_t));
64 
65     driver_obj->Base.type = &driver_spi_type;
66     driver_obj->ModuleName = "spi";
67 
68     return MP_OBJ_FROM_PTR(driver_obj);
69 }
70 
spi_open(size_t n_args,const mp_obj_t * args)71 STATIC mp_obj_t spi_open(size_t n_args, const mp_obj_t *args)
72 {
73     mp_int_t ret = -1;
74 
75     SPI_CHECK_PARAMS(2);
76 
77     char *id = NULL;
78     if (mp_obj_is_str(args[1])) {
79         id = (char *)mp_obj_str_get_str(args[1]);
80     } else {
81         LOGE(LOG_TAG, "%s: 2nd parameter should be string\n", __func__);
82         return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL);
83     }
84 
85     ret = py_board_mgr_init();
86     if (ret != 0) {
87         LOGE(LOG_TAG, "%s:py_board_mgr_init failed\n", __func__);
88         return MP_OBJ_NEW_SMALL_INT(-MP_ENOENT);
89     }
90 
91     ret = py_board_attach_item(MODULE_SPI, id, &(driver_obj->spi_handle));
92     if (ret != 0) {
93         LOGE(LOG_TAG, "%s: py_board_attach_item failed ret = %d\n", __func__, ret);
94         goto fail;
95     }
96 
97     SPI_NODE_GET();
98 
99     LOGD(LOG_TAG, "%s: port = %d;\n", __func__, spi_device->port);
100     LOGD(LOG_TAG, "%s: role = %d;\n", __func__, spi_device->config.role);
101     LOGD(LOG_TAG, "%s: firstbit = %d;\n", __func__, spi_device->config.firstbit);
102     LOGD(LOG_TAG, "%s: mode = %d;\n", __func__, spi_device->config.mode);
103     LOGD(LOG_TAG, "%s: t_mode = %d;\n", __func__, spi_device->config.t_mode);
104     LOGD(LOG_TAG, "%s: freq = %d;\n", __func__, spi_device->config.freq);
105     LOGD(LOG_TAG, "%s: serial_len = %d;\n", __func__, spi_device->config.serial_len);
106     LOGD(LOG_TAG, "%s: data_size = %d;\n", __func__, spi_device->config.data_size);
107     LOGD(LOG_TAG, "%s: cs = %d;\n", __func__, spi_device->config.cs);
108 
109     ret = aos_hal_spi_init(spi_device);
110 fail:
111     if (ret < 0) {
112         LOGE(LOG_TAG, "%s: spi_open failed ret = %d\n", __func__, ret);
113         py_board_disattach_item(MODULE_SPI, &(driver_obj->spi_handle));
114     }
115 
116     return MP_OBJ_NEW_SMALL_INT(ret);
117 }
118 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(spi_open_obj, 2, spi_open);
119 
spi_close(size_t n_args,const mp_obj_t * args)120 STATIC mp_obj_t spi_close(size_t n_args, const mp_obj_t *args)
121 {
122     mp_int_t ret = -1;
123 
124     SPI_CHECK_PARAMS(1);
125     SPI_NODE_GET();
126 
127     ret = aos_hal_spi_finalize(spi_device);
128     if (ret != 0) {
129         LOGE(LOG_TAG, "%s: hal_spi_finalize failed\n", __func__);
130     }
131 
132     py_board_disattach_item(MODULE_SPI, &(driver_obj->spi_handle));
133     return MP_OBJ_NEW_SMALL_INT(ret);
134 }
135 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(spi_close_obj, 1, spi_close);
136 
spi_read(size_t n_args,const mp_obj_t * args)137 STATIC mp_obj_t spi_read(size_t n_args, const mp_obj_t *args)
138 {
139     mp_int_t ret = -1;
140 
141     SPI_CHECK_PARAMS(4);
142     SPI_NODE_GET();
143 
144     mp_buffer_info_t read_bufinfo;
145     mp_get_buffer_raise(args[1], &read_bufinfo, MP_BUFFER_WRITE);
146     memset(read_bufinfo.buf, 0, read_bufinfo.len);
147 
148     mp_uint_t read_size = mp_obj_get_int(args[2]);
149     if (read_size > read_bufinfo.len) {
150         LOGE(LOG_TAG, "%s: read size[%d] exceed buffer size[%d]\n", __func__, read_size, read_bufinfo.len);
151         return MP_OBJ_NEW_SMALL_INT(-MP_ENFILE);
152     }
153 
154     ret = aos_hal_spi_recv(spi_device, read_bufinfo.buf, read_size, SPI_TIMEOUT);
155     if (ret < 0) {
156         LOGE(LOG_TAG, "%s: hal_spi_recv failed;\n", __func__);
157         return MP_OBJ_NEW_SMALL_INT(ret);
158     } else {
159         uint8_t *data = (uint8_t *)read_bufinfo.buf;
160         LOGD(LOG_TAG, "data = 0x%x, size=%d\n", data[0], read_size);
161         return MP_OBJ_NEW_SMALL_INT(read_size);
162     }
163 }
164 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(spi_read_obj, 4, spi_read);
165 
spi_write(size_t n_args,const mp_obj_t * args)166 STATIC mp_obj_t spi_write(size_t n_args, const mp_obj_t *args)
167 {
168     SPI_CHECK_PARAMS(3);
169     SPI_NODE_GET();
170 
171     mp_buffer_info_t bufinfo;
172     mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
173 
174     mp_uint_t write_size = mp_obj_get_int(args[2]);
175     if (write_size > bufinfo.len) {
176         LOGE(LOG_TAG, "%s: write size[%d] exceed buffer size[%d]\n", __func__, write_size, bufinfo.len);
177         return MP_OBJ_NEW_SMALL_INT(-MP_ENFILE);
178     }
179 
180     char *data = (char *)bufinfo.buf;
181     LOGD(LOG_TAG, "data = 0x%x, 0x%x, size=%d\n", data[0], data[1], write_size);
182 
183     mp_int_t ret = aos_hal_spi_send(spi_device, bufinfo.buf, write_size, SPI_TIMEOUT);
184     if (ret < 0) {
185         LOGE(LOG_TAG, "%s: hal_spi_send failed;\n", __func__);
186         return MP_OBJ_NEW_SMALL_INT(ret);
187     } else {
188         return MP_OBJ_NEW_SMALL_INT(write_size);
189     }
190 }
191 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(spi_write_obj, 3, spi_write);
192 
spi_writeRead(size_t n_args,const mp_obj_t * args)193 STATIC mp_obj_t spi_writeRead(size_t n_args, const mp_obj_t *args)
194 {
195     SPI_CHECK_PARAMS(4);
196     SPI_NODE_GET();
197 
198     mp_uint_t tx_data = mp_obj_get_int(args[1]);
199 
200     mp_buffer_info_t read_bufinfo;
201     mp_get_buffer_raise(args[2], &read_bufinfo, MP_BUFFER_WRITE);
202 
203     mp_uint_t read_size = mp_obj_get_int(args[3]);
204     if (read_size > read_bufinfo.len) {
205         LOGE(LOG_TAG, "%s: read size[%d] exceed buffer size[%d]\n", __func__, read_size, read_bufinfo.len);
206         return MP_OBJ_NEW_SMALL_INT(-MP_ENFILE);
207     }
208 
209     mp_int_t ret = aos_hal_spi_send_recv(spi_device, &tx_data, read_bufinfo.buf, read_size, SPI_TIMEOUT);
210     if (ret < 0) {
211         LOGE(LOG_TAG, "hal_spi_send_recv failed\n");
212         return MP_OBJ_NEW_SMALL_INT(ret);
213     } else {
214         return MP_OBJ_NEW_SMALL_INT(read_size);
215     }
216 }
217 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(spi_writeRead_obj, 4, spi_writeRead);
218 
spi_writeAndRead(size_t n_args,const mp_obj_t * args)219 STATIC mp_obj_t spi_writeAndRead(size_t n_args, const mp_obj_t *args)
220 {
221     mp_int_t ret = -1;
222 
223     SPI_CHECK_PARAMS(5);
224     SPI_NODE_GET();
225 
226     mp_buffer_info_t write_bufinfo;
227     mp_get_buffer_raise(args[1], &write_bufinfo, MP_BUFFER_READ);
228 
229     mp_uint_t write_size = mp_obj_get_int(args[2]);
230     if (write_size > write_bufinfo.len) {
231         LOGE(LOG_TAG, "%s: read size[%d] exceed buffer size[%d]\n", __func__, write_size, write_bufinfo.len);
232         return MP_OBJ_NEW_SMALL_INT(-MP_ENFILE);
233     }
234 
235     mp_buffer_info_t read_bufinfo;
236     mp_get_buffer_raise(args[3], &read_bufinfo, MP_BUFFER_WRITE);
237     memset(read_bufinfo.buf, 0, read_bufinfo.len);
238 
239     mp_uint_t read_size = mp_obj_get_int(args[4]);
240     if (read_size > read_bufinfo.len) {
241         LOGE(LOG_TAG, "%s: read size[%d] exceed buffer size[%d]\n", __func__, read_size, read_bufinfo.len);
242         return MP_OBJ_NEW_SMALL_INT(-MP_ENFILE);
243     }
244 
245     ret = aos_hal_spi_send_and_recv(spi_device, write_bufinfo.buf, write_size, read_bufinfo.buf, read_size, SPI_TIMEOUT);
246     if (ret < 0) {
247         LOGE(LOG_TAG, "%s: hal_spi_recv failed;\n", __func__);
248         return MP_OBJ_NEW_SMALL_INT(ret);
249     } else {
250         return MP_OBJ_NEW_SMALL_INT(read_size);
251     }
252 }
253 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(spi_writeAndRead_obj, 5, spi_writeAndRead);
254 
255 STATIC const mp_rom_map_elem_t spi_locals_dict_table[] = {
256     { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_SPI) },
257     { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&spi_open_obj) },
258     { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&spi_close_obj) },
259     { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&spi_read_obj) },
260     { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&spi_write_obj) },
261     { MP_ROM_QSTR(MP_QSTR_writeRead), MP_ROM_PTR(&spi_writeRead_obj) },
262     { MP_ROM_QSTR(MP_QSTR_writeAndRead), MP_ROM_PTR(&spi_writeAndRead_obj) },
263 };
264 
265 STATIC MP_DEFINE_CONST_DICT(spi_locals_dict, spi_locals_dict_table);
266 
267 const mp_obj_type_t driver_spi_type = {
268     .base = { &mp_type_type },
269     .name = MP_QSTR_SPI,
270     .print = spi_obj_print,
271     .make_new = spi_obj_make_new,
272     .locals_dict = (mp_obj_dict_t *)&spi_locals_dict,
273 };
274