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