Skip to content

Commit e221b05

Browse files
committed
硬件i2c直接使用rtt框架
1 parent 806b482 commit e221b05

File tree

1 file changed

+248
-3
lines changed

1 file changed

+248
-3
lines changed

port/modules/machine/machine_hw_i2c.c

Lines changed: 248 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@
3636

3737
STATIC const mp_obj_type_t machine_hard_i2c_type;
3838

39+
STATIC const mp_arg_t machine_i2c_mem_allowed_args[] = {
40+
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
41+
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
42+
{ MP_QSTR_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
43+
{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
44+
};
45+
3946
typedef struct _machine_hard_i2c_obj_t {
4047
mp_obj_base_t base;
4148
struct rt_i2c_bus_device *i2c_bus;
@@ -53,12 +60,66 @@ STATIC void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp
5360
return;
5461
}
5562

56-
int machine_hard_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop) {
63+
STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, const uint8_t *buf, size_t len) {
64+
machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t*)MP_OBJ_TO_PTR(self_in);
65+
66+
// Create buffer with memory address
67+
size_t memaddr_len = 0;
68+
uint8_t memaddr_buf[4];
69+
for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
70+
memaddr_buf[memaddr_len++] = memaddr >> i;
71+
}
72+
73+
struct rt_i2c_msg msg[2];
74+
75+
msg[0].buf = memaddr_buf;
76+
msg[0].len = (addrsize + 7)/8;
77+
msg[0].flags = RT_I2C_WR;
78+
msg[0].addr = addr;
79+
80+
msg[1].buf = (rt_uint8_t*)buf;
81+
msg[1].len = len;
82+
msg[1].flags = RT_I2C_WR;
83+
msg[1].addr = addr;
84+
85+
if (rt_i2c_transfer(self->i2c_bus, msg, 2) != 2)
86+
return -MP_EIO;
87+
88+
return len;
89+
}
90+
91+
STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) {
92+
machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t*)MP_OBJ_TO_PTR(self_in);
93+
uint8_t memaddr_buf[4];
94+
size_t memaddr_len = 0;
95+
for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
96+
memaddr_buf[memaddr_len++] = memaddr >> i;
97+
}
98+
99+
struct rt_i2c_msg msg[2];
100+
101+
msg[0].buf = memaddr_buf;
102+
msg[0].len = (addrsize + 7)/8;
103+
msg[0].flags = RT_I2C_WR;
104+
msg[0].addr = addr;
105+
106+
msg[1].buf = buf;
107+
msg[1].len = len;
108+
msg[1].flags = RT_I2C_RD;
109+
msg[1].addr = addr;
110+
111+
if (rt_i2c_transfer(self->i2c_bus, msg, 2) != 2)
112+
return -MP_EIO;
113+
114+
return len;
115+
}
116+
117+
STATIC int mp_machine_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop) {
57118
machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
58119
return rt_i2c_master_recv(self->i2c_bus, addr, 0, dest, len);
59120
}
60121

61-
int machine_hard_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop) {
122+
STATIC int mp_machine_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop) {
62123
uint8_t buf[1] = {0};
63124
machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
64125
if (len == 0){
@@ -73,6 +134,188 @@ int machine_hard_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_
73134
return rt_i2c_master_send(self->i2c_bus, addr, 0, src, len);
74135
}
75136

137+
STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
138+
mp_obj_base_t *self = MP_OBJ_TO_PTR(self_in);
139+
mp_obj_t list = mp_obj_new_list(0, NULL);
140+
// 7-bit addresses 0b0000xxx and 0b1111xxx are reserved
141+
for (int addr = 0x08; addr < 0x78; ++addr) {
142+
int ret = mp_machine_i2c_writeto(self, addr, NULL, 0, true);
143+
if (ret == 0) {
144+
mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
145+
}
146+
}
147+
return list;
148+
}
149+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan);
150+
151+
STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) {
152+
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
153+
mp_int_t addr = mp_obj_get_int(args[1]);
154+
vstr_t vstr;
155+
vstr_init_len(&vstr, mp_obj_get_int(args[2]));
156+
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
157+
int ret = mp_machine_i2c_readfrom(self, addr, (uint8_t*)vstr.buf, vstr.len, stop);
158+
if (ret < 0) {
159+
mp_raise_OSError(-ret);
160+
}
161+
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
162+
}
163+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_readfrom);
164+
165+
STATIC mp_obj_t machine_i2c_readfrom_into(size_t n_args, const mp_obj_t *args) {
166+
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
167+
mp_int_t addr = mp_obj_get_int(args[1]);
168+
mp_buffer_info_t bufinfo;
169+
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE);
170+
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
171+
int ret = mp_machine_i2c_readfrom(self, addr, bufinfo.buf, bufinfo.len, stop);
172+
if (ret < 0) {
173+
mp_raise_OSError(-ret);
174+
}
175+
return mp_const_none;
176+
}
177+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_into_obj, 3, 4, machine_i2c_readfrom_into);
178+
179+
STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) {
180+
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
181+
mp_int_t addr = mp_obj_get_int(args[1]);
182+
mp_buffer_info_t bufinfo;
183+
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
184+
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
185+
int ret = mp_machine_i2c_writeto(self, addr, bufinfo.buf, bufinfo.len, stop);
186+
if (ret < 0) {
187+
mp_raise_OSError(-ret);
188+
}
189+
// return number of acks received
190+
return MP_OBJ_NEW_SMALL_INT(ret);
191+
}
192+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machine_i2c_writeto);
193+
194+
STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) {
195+
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
196+
mp_int_t addr = mp_obj_get_int(args[1]);
197+
198+
// Get the list of data buffer(s) to write
199+
size_t nitems;
200+
const mp_obj_t *items;
201+
mp_obj_get_array(args[2], &nitems, (mp_obj_t**)&items);
202+
203+
// Get the stop argument
204+
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
205+
206+
// Extract all buffer data, skipping zero-length buffers
207+
size_t alloc = nitems == 0 ? 1 : nitems;
208+
size_t nbufs = 0;
209+
struct rt_i2c_msg *bufs = mp_local_alloc(alloc * sizeof(struct rt_i2c_msg));
210+
for (; nitems--; ++items) {
211+
mp_buffer_info_t bufinfo;
212+
mp_get_buffer_raise(*items, &bufinfo, MP_BUFFER_READ);
213+
if (bufinfo.len > 0) {
214+
bufs[nbufs].addr = addr;
215+
bufs[nbufs].flags = RT_I2C_WR;
216+
bufs[nbufs].len = bufinfo.len;
217+
bufs[nbufs++].buf = bufinfo.buf;
218+
}
219+
}
220+
221+
// Make sure there is at least one buffer, empty if needed
222+
if (nbufs == 0) {
223+
bufs[0].len = 0;
224+
bufs[0].buf = NULL;
225+
nbufs = 1;
226+
}
227+
228+
// Do the I2C transfer
229+
machine_hard_i2c_obj_t *i2c_p = (machine_hard_i2c_obj_t*)self;
230+
int ret = rt_i2c_transfer(i2c_p->i2c_bus, bufs, nbufs);
231+
mp_local_free(bufs);
232+
233+
if (ret < 0) {
234+
mp_raise_OSError(-ret);
235+
}
236+
237+
// Return number of acks received
238+
return MP_OBJ_NEW_SMALL_INT(ret);
239+
}
240+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writevto_obj, 3, 4, machine_i2c_writevto);
241+
242+
STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
243+
enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize };
244+
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
245+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
246+
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
247+
248+
// create the buffer to store data into
249+
vstr_t vstr;
250+
vstr_init_len(&vstr, mp_obj_get_int(args[ARG_n].u_obj));
251+
252+
// do the transfer
253+
int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
254+
args[ARG_addrsize].u_int, (uint8_t*)vstr.buf, vstr.len);
255+
if (ret < 0) {
256+
mp_raise_OSError(-ret);
257+
}
258+
259+
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
260+
}
261+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem);
262+
263+
STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
264+
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
265+
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
266+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
267+
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
268+
269+
// get the buffer to store data into
270+
mp_buffer_info_t bufinfo;
271+
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE);
272+
273+
// do the transfer
274+
int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
275+
args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
276+
if (ret < 0) {
277+
mp_raise_OSError(-ret);
278+
}
279+
return mp_const_none;
280+
}
281+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into);
282+
283+
STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
284+
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
285+
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
286+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
287+
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
288+
289+
// get the buffer to write the data from
290+
mp_buffer_info_t bufinfo;
291+
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ);
292+
293+
// do the transfer
294+
int ret = write_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
295+
args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
296+
if (ret < 0) {
297+
mp_raise_OSError(-ret);
298+
}
299+
300+
return mp_const_none;
301+
}
302+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem);
303+
304+
STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = {
305+
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&machine_i2c_scan_obj) },
306+
307+
// standard bus operations
308+
{ MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) },
309+
{ MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) },
310+
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) },
311+
{ MP_ROM_QSTR(MP_QSTR_writevto), MP_ROM_PTR(&machine_i2c_writevto_obj) },
312+
313+
// memory operations
314+
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) },
315+
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) },
316+
{ MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) },
317+
};
318+
76319
/******************************************************************************/
77320
/* MicroPython bindings for machine API */
78321

@@ -94,6 +337,8 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz
94337
return (mp_obj_t) self;
95338
}
96339

340+
MP_DEFINE_CONST_DICT(mp_machine_hard_i2c_locals_dict, machine_i2c_locals_dict_table);
341+
97342
STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = {
98343
.start = NULL,
99344
.stop = NULL,
@@ -109,7 +354,7 @@ STATIC const mp_obj_type_t machine_hard_i2c_type = {
109354
.print = machine_hard_i2c_print,
110355
.make_new = machine_hard_i2c_make_new,
111356
.protocol = &machine_hard_i2c_p,
112-
.locals_dict = (mp_obj_dict_t*)&mp_machine_soft_i2c_locals_dict,
357+
.locals_dict = (mp_obj_dict_t*)&mp_machine_hard_i2c_locals_dict,
113358
};
114359

115360
#endif // MICROPYTHON_USING_MACHINE_I2C

0 commit comments

Comments
 (0)