You've already forked Core2forAWS-MicroPython
mirror of
https://github.com/m5stack/Core2forAWS-MicroPython.git
synced 2026-05-20 10:30:31 -07:00
Merge remote-tracking branch 'upstream/master' into builtins
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
The Micro Python project
|
||||
========================
|
||||
<p align="center">
|
||||
<img src="https://raw2.github.com/micropython/micropython/master/logo/upython-with-micro.png" alt="MicroPython Logo"/>
|
||||
</p>
|
||||
|
||||
This is the Micro Python project, which aims to put an implementation
|
||||
of Python 3.x on a microcontroller.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 563 KiB |
+1
-1
@@ -339,7 +339,7 @@ static mp_obj_t mp_builtin_sorted(mp_obj_t args, mp_map_t *kwargs) {
|
||||
}
|
||||
mp_obj_t self = list_type.make_new((mp_obj_t)&list_type, 1, args_items);
|
||||
mp_obj_t new_args = rt_build_tuple(1, &self);
|
||||
list_sort(new_args, kwargs);
|
||||
mp_obj_list_sort(new_args, kwargs);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+1
-1
@@ -614,7 +614,7 @@ mp_lexer_t *mp_lexer_new(const char *src_name, void *stream_data, mp_lexer_strea
|
||||
lex->num_indent_level = 1;
|
||||
lex->indent_level = m_new(uint16_t, lex->alloc_indent_level);
|
||||
lex->indent_level[0] = 0;
|
||||
vstr_init(&lex->vstr);
|
||||
vstr_init(&lex->vstr, 32);
|
||||
|
||||
// preload characters
|
||||
lex->chr0 = stream_next_char(stream_data);
|
||||
|
||||
@@ -59,15 +59,19 @@ typedef struct _vstr_t {
|
||||
bool had_error;
|
||||
} vstr_t;
|
||||
|
||||
void vstr_init(vstr_t *vstr);
|
||||
void vstr_init(vstr_t *vstr, int alloc);
|
||||
void vstr_clear(vstr_t *vstr);
|
||||
vstr_t *vstr_new(void);
|
||||
vstr_t *vstr_new_size(int alloc);
|
||||
void vstr_free(vstr_t *vstr);
|
||||
void vstr_reset(vstr_t *vstr);
|
||||
bool vstr_had_error(vstr_t *vstr);
|
||||
char *vstr_str(vstr_t *vstr);
|
||||
int vstr_len(vstr_t *vstr);
|
||||
void vstr_hint_size(vstr_t *vstr, int size);
|
||||
char *vstr_extend(vstr_t *vstr, int size);
|
||||
bool vstr_set_size(vstr_t *vstr, int size);
|
||||
bool vstr_shrink(vstr_t *vstr);
|
||||
char *vstr_add_len(vstr_t *vstr, int len);
|
||||
void vstr_add_byte(vstr_t *vstr, byte v);
|
||||
void vstr_add_char(vstr_t *vstr, unichar chr);
|
||||
|
||||
@@ -292,7 +292,7 @@ extern const mp_obj_type_t list_type;
|
||||
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg);
|
||||
void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
|
||||
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
|
||||
mp_obj_t list_sort(mp_obj_t args, struct _mp_map_t *kwargs);
|
||||
mp_obj_t mp_obj_list_sort(mp_obj_t args, struct _mp_map_t *kwargs);
|
||||
|
||||
// enumerate
|
||||
extern const mp_obj_type_t enumerate_type;
|
||||
|
||||
@@ -57,6 +57,12 @@ static mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
return elem->value;
|
||||
}
|
||||
}
|
||||
case RT_COMPARE_OP_IN:
|
||||
case RT_COMPARE_OP_NOT_IN:
|
||||
{
|
||||
mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
|
||||
return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (elem == NULL));
|
||||
}
|
||||
default:
|
||||
// op not supported
|
||||
return NULL;
|
||||
@@ -362,10 +368,20 @@ static void dict_view_print(void (*print)(void *env, const char *fmt, ...), void
|
||||
print(env, "])");
|
||||
}
|
||||
|
||||
static mp_obj_t dict_view_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
/* only supported for the 'keys' kind until sets and dicts are refactored */
|
||||
mp_obj_dict_view_t *o = lhs_in;
|
||||
if (o->kind != MP_DICT_VIEW_KEYS) return NULL;
|
||||
if (op != RT_COMPARE_OP_IN && op != RT_COMPARE_OP_NOT_IN) return NULL;
|
||||
return dict_binary_op(op, o->dict, rhs_in);
|
||||
}
|
||||
|
||||
|
||||
static const mp_obj_type_t dict_view_type = {
|
||||
{ &mp_const_type },
|
||||
"dict_view",
|
||||
.print = dict_view_print,
|
||||
.binary_op = dict_view_binary_op,
|
||||
.getiter = dict_view_getiter,
|
||||
};
|
||||
|
||||
|
||||
+46
-65
@@ -8,105 +8,86 @@
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "obj.h"
|
||||
#include "objtuple.h"
|
||||
|
||||
// This is unified class for C-level and Python-level exceptions
|
||||
// Python-level exception have empty ->msg and all arguments are in
|
||||
// args tuple. C-level excepttion likely have ->msg, and may as well
|
||||
// have args tuple (or otherwise have it as NULL).
|
||||
typedef struct mp_obj_exception_t {
|
||||
mp_obj_base_t base;
|
||||
qstr id;
|
||||
int n_args;
|
||||
const void *args[];
|
||||
qstr msg;
|
||||
mp_obj_tuple_t args;
|
||||
} mp_obj_exception_t;
|
||||
|
||||
void exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
|
||||
mp_obj_exception_t *o = o_in;
|
||||
switch (o->n_args) {
|
||||
case 0:
|
||||
print(env, "%s", qstr_str(o->id));
|
||||
break;
|
||||
case 1:
|
||||
print(env, "%s: %s", qstr_str(o->id), (const char*)o->args[0]);
|
||||
break;
|
||||
case 2:
|
||||
print(env, "%s: ", qstr_str(o->id));
|
||||
print(env, (const char*)o->args[0], o->args[1]);
|
||||
break;
|
||||
default: // here we just assume at least 3 args, but only use first 3
|
||||
print(env, "%s: ", qstr_str(o->id));
|
||||
print(env, (const char*)o->args[0], o->args[1], o->args[2]);
|
||||
break;
|
||||
if (o->msg != 0) {
|
||||
print(env, "%s: %s", qstr_str(o->id), qstr_str(o->msg));
|
||||
} else {
|
||||
print(env, "%s", qstr_str(o->id));
|
||||
tuple_print(print, env, &o->args);
|
||||
}
|
||||
}
|
||||
|
||||
// args in reversed order
|
||||
static mp_obj_t exception_call(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
|
||||
mp_obj_exception_t *base = self_in;
|
||||
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t*, n_args);
|
||||
o->base.type = &exception_type;
|
||||
o->id = base->id;
|
||||
o->msg = 0;
|
||||
o->args.len = n_args;
|
||||
|
||||
// TODO: factor out as reusable copy_reversed()
|
||||
int j = 0;
|
||||
for (int i = n_args - 1; i >= 0; i--) {
|
||||
o->args.items[i] = args[j++];
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
const mp_obj_type_t exception_type = {
|
||||
{ &mp_const_type },
|
||||
"exception",
|
||||
.print = exception_print,
|
||||
.call_n = exception_call,
|
||||
};
|
||||
|
||||
mp_obj_t mp_obj_new_exception(qstr id) {
|
||||
mp_obj_exception_t *o = m_new_obj(mp_obj_exception_t);
|
||||
o->base.type = &exception_type;
|
||||
o->id = id;
|
||||
o->n_args = 0;
|
||||
return o;
|
||||
return mp_obj_new_exception_msg_varg(id, NULL);
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_new_exception_msg(qstr id, const char *msg) {
|
||||
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 1);
|
||||
o->base.type = &exception_type;
|
||||
o->id = id;
|
||||
o->n_args = 1;
|
||||
o->args[0] = msg;
|
||||
return o;
|
||||
return mp_obj_new_exception_msg_varg(id, msg);
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_new_exception_msg_1_arg(qstr id, const char *fmt, const char *a1) {
|
||||
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 2);
|
||||
o->base.type = &exception_type;
|
||||
o->id = id;
|
||||
o->n_args = 2;
|
||||
o->args[0] = fmt;
|
||||
o->args[1] = a1;
|
||||
return o;
|
||||
return mp_obj_new_exception_msg_varg(id, fmt, a1);
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_new_exception_msg_2_args(qstr id, const char *fmt, const char *a1, const char *a2) {
|
||||
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 3);
|
||||
o->base.type = &exception_type;
|
||||
o->id = id;
|
||||
o->n_args = 3;
|
||||
o->args[0] = fmt;
|
||||
o->args[1] = a1;
|
||||
o->args[2] = a2;
|
||||
return o;
|
||||
return mp_obj_new_exception_msg_varg(id, fmt, a1, a2);
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...) {
|
||||
// count number of arguments by number of % signs, excluding %%
|
||||
int n_args = 1; // count fmt
|
||||
for (const char *s = fmt; *s; s++) {
|
||||
if (*s == '%') {
|
||||
if (s[1] == '%') {
|
||||
s += 1;
|
||||
} else {
|
||||
n_args += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make exception object
|
||||
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, n_args);
|
||||
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t*, 0);
|
||||
o->base.type = &exception_type;
|
||||
o->id = id;
|
||||
o->n_args = n_args;
|
||||
o->args[0] = fmt;
|
||||
|
||||
// extract args and store them
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
for (int i = 1; i < n_args; i++) {
|
||||
o->args[i] = va_arg(ap, void*);
|
||||
o->args.len = 0;
|
||||
if (fmt == NULL) {
|
||||
o->msg = 0;
|
||||
} else {
|
||||
// render exception message
|
||||
vstr_t *vstr = vstr_new();
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vstr_vprintf(vstr, fmt, ap);
|
||||
va_end(ap);
|
||||
o->msg = qstr_from_str_take(vstr->buf, vstr->alloc);
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
+2
-2
@@ -248,7 +248,7 @@ static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, bool r
|
||||
}
|
||||
}
|
||||
|
||||
mp_obj_t list_sort(mp_obj_t args, mp_map_t *kwargs) {
|
||||
mp_obj_t mp_obj_list_sort(mp_obj_t args, mp_map_t *kwargs) {
|
||||
mp_obj_t *args_items = NULL;
|
||||
uint args_len = 0;
|
||||
|
||||
@@ -381,7 +381,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(list_insert_obj, list_insert);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_pop_obj, 1, 2, list_pop);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_2(list_remove_obj, list_remove);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(list_reverse_obj, list_reverse);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, 0, list_sort);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, 0, mp_obj_list_sort);
|
||||
|
||||
static const mp_method_t list_type_methods[] = {
|
||||
{ "append", &list_append_obj },
|
||||
|
||||
@@ -45,6 +45,7 @@ void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj
|
||||
print(env, "}");
|
||||
}
|
||||
|
||||
|
||||
static mp_obj_t set_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
|
||||
switch (n_args) {
|
||||
case 0:
|
||||
@@ -405,6 +406,13 @@ static mp_obj_t set_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
return set_issuperset(lhs, rhs);
|
||||
case RT_COMPARE_OP_NOT_EQUAL:
|
||||
return MP_BOOL(set_equal(lhs, rhs) == mp_const_false);
|
||||
case RT_COMPARE_OP_IN:
|
||||
case RT_COMPARE_OP_NOT_IN:
|
||||
{
|
||||
mp_obj_set_t *o = lhs;
|
||||
mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP);
|
||||
return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (elem == NULL));
|
||||
}
|
||||
default:
|
||||
// op not supported
|
||||
return NULL;
|
||||
|
||||
@@ -85,6 +85,15 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
return mp_obj_new_str(qstr_from_str_take(val, alloc_len));
|
||||
}
|
||||
break;
|
||||
case RT_COMPARE_OP_IN:
|
||||
case RT_COMPARE_OP_NOT_IN:
|
||||
/* NOTE `a in b` is `b.__contains__(a)` */
|
||||
if (MP_OBJ_IS_TYPE(rhs_in, &str_type)) {
|
||||
const char *rhs_str = qstr_str(((mp_obj_str_t*)rhs_in)->qstr);
|
||||
/* FIXME \0 in strs */
|
||||
return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (strstr(lhs_str, rhs_str) == NULL));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
|
||||
+11
-13
@@ -12,12 +12,6 @@ typedef struct _mp_obj_zip_t {
|
||||
mp_obj_t iters[];
|
||||
} mp_obj_zip_t;
|
||||
|
||||
static mp_obj_t zip_getiter(mp_obj_t self_in) {
|
||||
return self_in;
|
||||
}
|
||||
|
||||
static mp_obj_t zip_iternext(mp_obj_t self_in);
|
||||
|
||||
static mp_obj_t zip_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
|
||||
/* NOTE: args are backwards */
|
||||
mp_obj_zip_t *o = m_new_obj_var(mp_obj_zip_t, mp_obj_t, n_args);
|
||||
@@ -29,13 +23,9 @@ static mp_obj_t zip_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args)
|
||||
return o;
|
||||
}
|
||||
|
||||
const mp_obj_type_t zip_type = {
|
||||
{ &mp_const_type },
|
||||
"zip",
|
||||
.make_new = zip_make_new,
|
||||
.iternext = zip_iternext,
|
||||
.getiter = zip_getiter,
|
||||
};
|
||||
static mp_obj_t zip_getiter(mp_obj_t self_in) {
|
||||
return self_in;
|
||||
}
|
||||
|
||||
static mp_obj_t zip_iternext(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &zip_type));
|
||||
@@ -57,3 +47,11 @@ static mp_obj_t zip_iternext(mp_obj_t self_in) {
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
const mp_obj_type_t zip_type = {
|
||||
{ &mp_const_type },
|
||||
"zip",
|
||||
.make_new = zip_make_new,
|
||||
.getiter = zip_getiter,
|
||||
.iternext = zip_iternext,
|
||||
};
|
||||
|
||||
+41
-6
@@ -569,22 +569,57 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
} else if (MP_OBJ_IS_TYPE(rhs, &complex_type)) {
|
||||
return mp_obj_complex_binary_op(op, lhs_val, 0, rhs);
|
||||
}
|
||||
} else {
|
||||
if (MP_OBJ_IS_OBJ(lhs)) {
|
||||
mp_obj_base_t *o = lhs;
|
||||
}
|
||||
|
||||
/* deal with `in` and `not in`
|
||||
*
|
||||
* NOTE `a in b` is `b.__contains__(a)`, hence why the generic dispatch
|
||||
* needs to go below
|
||||
*/
|
||||
if (op == RT_COMPARE_OP_IN || op == RT_COMPARE_OP_NOT_IN) {
|
||||
if (!MP_OBJ_IS_SMALL_INT(rhs)) {
|
||||
mp_obj_base_t *o = rhs;
|
||||
if (o->type->binary_op != NULL) {
|
||||
mp_obj_t result = o->type->binary_op(op, lhs, rhs);
|
||||
if (result != NULL) {
|
||||
return result;
|
||||
mp_obj_t res = o->type->binary_op(op, rhs, lhs);
|
||||
if (res != NULL) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
if (o->type->getiter != NULL) {
|
||||
/* second attempt, walk the iterator */
|
||||
mp_obj_t next = NULL;
|
||||
mp_obj_t iter = rt_getiter(rhs);
|
||||
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
|
||||
if (mp_obj_equal(next, lhs)) {
|
||||
return MP_BOOL(op == RT_COMPARE_OP_IN);
|
||||
}
|
||||
}
|
||||
return MP_BOOL(op != RT_COMPARE_OP_IN);
|
||||
}
|
||||
}
|
||||
|
||||
nlr_jump(mp_obj_new_exception_msg_varg(
|
||||
MP_QSTR_TypeError, "'%s' object is not iterable",
|
||||
mp_obj_get_type_str(rhs)));
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
if (MP_OBJ_IS_OBJ(lhs)) {
|
||||
mp_obj_base_t *o = lhs;
|
||||
if (o->type->binary_op != NULL) {
|
||||
mp_obj_t result = o->type->binary_op(op, lhs, rhs);
|
||||
if (result != NULL) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// TODO implement dispatch for reverse binary ops
|
||||
}
|
||||
|
||||
// TODO specify in error message what the operator is
|
||||
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError,
|
||||
"unsupported operand types for binary operator: '%s', '%s'",
|
||||
mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs)));
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t rt_make_function_from_id(int unique_code_id) {
|
||||
|
||||
+42
@@ -51,5 +51,47 @@ static mp_obj_t stream_write(mp_obj_t self_in, mp_obj_t arg) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: should be in mpconfig.h
|
||||
#define READ_SIZE 256
|
||||
static mp_obj_t stream_readall(mp_obj_t self_in) {
|
||||
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in;
|
||||
if (o->type->stream_p.read == NULL) {
|
||||
// CPython: io.UnsupportedOperation, OSError subclass
|
||||
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_OSError, "Operation not supported"));
|
||||
}
|
||||
|
||||
int total_size = 0;
|
||||
vstr_t *vstr = vstr_new_size(READ_SIZE);
|
||||
char *buf = vstr_str(vstr);
|
||||
char *p = buf;
|
||||
int error;
|
||||
int current_read = READ_SIZE;
|
||||
while (true) {
|
||||
machine_int_t out_sz = o->type->stream_p.read(self_in, p, current_read, &error);
|
||||
if (out_sz == -1) {
|
||||
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error));
|
||||
}
|
||||
if (out_sz == 0) {
|
||||
break;
|
||||
}
|
||||
total_size += out_sz;
|
||||
if (out_sz < current_read) {
|
||||
current_read -= out_sz;
|
||||
p += out_sz;
|
||||
} else {
|
||||
current_read = READ_SIZE;
|
||||
p = vstr_extend(vstr, current_read);
|
||||
if (p == NULL) {
|
||||
// TODO
|
||||
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError/*MP_QSTR_RuntimeError*/, "Out of memory"));
|
||||
}
|
||||
}
|
||||
}
|
||||
vstr_set_size(vstr, total_size + 1); // TODO: for \0
|
||||
buf[total_size] = 0;
|
||||
return mp_obj_new_str(qstr_from_str_take(buf, total_size + 1));
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_read_obj, stream_read);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_readall_obj, stream_readall);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write_obj, stream_write);
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
extern const mp_obj_fun_native_t mp_stream_read_obj;
|
||||
extern const mp_obj_fun_native_t mp_stream_readall_obj;
|
||||
extern const mp_obj_fun_native_t mp_stream_write_obj;
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
// returned value is always at least 1 greater than argument
|
||||
#define ROUND_ALLOC(a) (((a) & ((~0) - 7)) + 8)
|
||||
|
||||
void vstr_init(vstr_t *vstr) {
|
||||
vstr->alloc = 32;
|
||||
void vstr_init(vstr_t *vstr, int alloc) {
|
||||
vstr->alloc = alloc;
|
||||
vstr->len = 0;
|
||||
vstr->buf = m_new(char, vstr->alloc);
|
||||
if (vstr->buf == NULL) {
|
||||
@@ -28,7 +28,16 @@ vstr_t *vstr_new(void) {
|
||||
if (vstr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
vstr_init(vstr);
|
||||
vstr_init(vstr, 32);
|
||||
return vstr;
|
||||
}
|
||||
|
||||
vstr_t *vstr_new_size(int alloc) {
|
||||
vstr_t *vstr = m_new(vstr_t, 1);
|
||||
if (vstr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
vstr_init(vstr, alloc);
|
||||
return vstr;
|
||||
}
|
||||
|
||||
@@ -63,6 +72,36 @@ int vstr_len(vstr_t *vstr) {
|
||||
return vstr->len;
|
||||
}
|
||||
|
||||
// Extend vstr strictly to by requested size, return pointer to newly added chunk
|
||||
char *vstr_extend(vstr_t *vstr, int size) {
|
||||
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size);
|
||||
if (new_buf == NULL) {
|
||||
vstr->had_error = true;
|
||||
return NULL;
|
||||
}
|
||||
char *p = new_buf + vstr->alloc;
|
||||
vstr->alloc += size;
|
||||
vstr->buf = new_buf;
|
||||
return p;
|
||||
}
|
||||
|
||||
// Shrink vstr to be given size
|
||||
bool vstr_set_size(vstr_t *vstr, int size) {
|
||||
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, size);
|
||||
if (new_buf == NULL) {
|
||||
vstr->had_error = true;
|
||||
return false;
|
||||
}
|
||||
vstr->buf = new_buf;
|
||||
vstr->alloc = vstr->len = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Shrink vstr allocation to its actual length
|
||||
bool vstr_shrink(vstr_t *vstr) {
|
||||
return vstr_set_size(vstr, vstr->len);
|
||||
}
|
||||
|
||||
bool vstr_ensure_extra(vstr_t *vstr, int size) {
|
||||
if (vstr->len + size + 1 > vstr->alloc) {
|
||||
int new_alloc = ROUND_ALLOC((vstr->len + size + 1) * 2);
|
||||
|
||||
+4
-1
@@ -33,6 +33,7 @@ CFLAGS += -Os -DNDEBUG
|
||||
endif
|
||||
|
||||
LDFLAGS = --nostdlib -T stm32f405.ld
|
||||
LIBS = $(shell $(CC) -print-libgcc-file-name)
|
||||
|
||||
SRC_C = \
|
||||
main.c \
|
||||
@@ -57,6 +58,7 @@ SRC_C = \
|
||||
pybwlan.c \
|
||||
i2c.c \
|
||||
usrsw.c \
|
||||
adc.c \
|
||||
|
||||
SRC_S = \
|
||||
startup_stm32f40xx.s \
|
||||
@@ -100,6 +102,7 @@ SRC_STM = \
|
||||
usbd_storage_msd.c \
|
||||
stm324x7i_eval.c \
|
||||
stm324x7i_eval_sdio_sd.c \
|
||||
stm32f4xx_adc.c \
|
||||
|
||||
#SRC_STM_OTG = \
|
||||
# usb_hcd.c \
|
||||
@@ -143,7 +146,7 @@ $(BUILD)/flash1.bin: $(BUILD)/flash.elf
|
||||
|
||||
$(BUILD)/flash.elf: $(OBJ)
|
||||
$(ECHO) "LINK $@"
|
||||
$(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ)
|
||||
$(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
|
||||
$(Q)$(SIZE) $@
|
||||
|
||||
$(BUILD)/%.o: %.s
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
#include <stdio.h>
|
||||
#include <stm32f4xx_rcc.h>
|
||||
#include <stm32f4xx_gpio.h>
|
||||
#include <stm32f4xx_adc.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "obj.h"
|
||||
#include "adc.h"
|
||||
|
||||
/* ADC defintions */
|
||||
#define ADCx (ADC1)
|
||||
#define ADCx_CLK (RCC_APB2Periph_ADC1)
|
||||
#define ADC_NUM_CHANNELS (16)
|
||||
|
||||
/* Internally connected ADC channels Temp/VBAT/VREF*/
|
||||
#if defined (STM32F40XX) || defined(STM32F41XX)
|
||||
#define ADC_TEMP_CHANNEL (16)
|
||||
#define ADC_VBAT_CHANNEL (18)
|
||||
#define ADC_VREF_CHANNEL (17)
|
||||
#elif defined (STM32F42XX) || defined(STM32F43XX)
|
||||
#define ADC_TEMP_CHANNEL (18)
|
||||
#define ADC_VBAT_CHANNEL (18) /* same channel as TEMP */
|
||||
#define ADC_VREF_CHANNEL (17)
|
||||
#endif
|
||||
|
||||
/* Core temperature sensor definitions */
|
||||
#define CORE_TEMP_V25 (943) /* (0.76v/3.3v)*(2^ADC resoultion) */
|
||||
#define CORE_TEMP_AVG_SLOPE (3) /* (2.5mv/3.3v)*(2^ADC resoultion) */
|
||||
|
||||
/* VBAT divider */
|
||||
#if defined (STM32F40XX) || defined(STM32F41XX)
|
||||
#define VBAT_DIV (2)
|
||||
#elif defined (STM32F42XX) || defined(STM32F43XX)
|
||||
#define VBAT_DIV (4)
|
||||
#endif
|
||||
|
||||
/* GPIO struct */
|
||||
typedef struct {
|
||||
GPIO_TypeDef* port;
|
||||
uint32_t pin;
|
||||
} gpio_t;
|
||||
|
||||
/* ADC GPIOs */
|
||||
static gpio_t adc_gpio[] = {
|
||||
{GPIOA, GPIO_Pin_0}, /* ADC123_IN0 */
|
||||
{GPIOA, GPIO_Pin_1}, /* ADC123_IN1 */
|
||||
{GPIOA, GPIO_Pin_2}, /* ADC123_IN2 */
|
||||
{GPIOA, GPIO_Pin_3}, /* ADC123_IN3 */
|
||||
{GPIOA, GPIO_Pin_4}, /* ADC12_IN4 */
|
||||
{GPIOA, GPIO_Pin_5}, /* ADC12_IN5 */
|
||||
{GPIOA, GPIO_Pin_6}, /* ADC12_IN6 */
|
||||
{GPIOA, GPIO_Pin_7}, /* ADC12_IN7 */
|
||||
{GPIOB, GPIO_Pin_0}, /* ADC12_IN8 */
|
||||
{GPIOB, GPIO_Pin_1}, /* ADC12_IN9 */
|
||||
{GPIOC, GPIO_Pin_0}, /* ADC123_IN10 */
|
||||
{GPIOC, GPIO_Pin_1}, /* ADC123_IN11 */
|
||||
{GPIOC, GPIO_Pin_2}, /* ADC123_IN12 */
|
||||
{GPIOC, GPIO_Pin_3}, /* ADC123_IN13 */
|
||||
{GPIOC, GPIO_Pin_4}, /* ADC12_IN14 */
|
||||
{GPIOC, GPIO_Pin_5}, /* ADC12_IN15 */
|
||||
|
||||
};
|
||||
|
||||
void adc_init(uint32_t resolution) {
|
||||
ADC_InitTypeDef ADC_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
ADC_CommonInitTypeDef ADC_CommonInitStructure;
|
||||
|
||||
/* Enable ADCx, DMA and GPIO clocks */
|
||||
#if 0
|
||||
/* GPIO clocks enabled in main */
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA |
|
||||
RCC_AHB1Periph_GPIOB |
|
||||
RCC_AHB1Periph_GPIOC, ENABLE);
|
||||
#endif
|
||||
RCC_APB2PeriphClockCmd(ADCx_CLK, ENABLE);
|
||||
|
||||
/* ADC Common Init */
|
||||
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
|
||||
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
|
||||
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
|
||||
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
|
||||
ADC_CommonInit(&ADC_CommonInitStructure);
|
||||
|
||||
/* Configure ADC GPIOs */
|
||||
for (int i=0; i<ADC_NUM_CHANNELS; i++) {
|
||||
GPIO_InitStructure.GPIO_Pin = adc_gpio[i].pin;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(adc_gpio[i].port, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
/* ADCx Init */
|
||||
// ADC_DeInit();
|
||||
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
|
||||
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
|
||||
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
|
||||
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
|
||||
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
|
||||
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
|
||||
ADC_InitStructure.ADC_NbrOfConversion = 1;
|
||||
ADC_Init(ADCx, &ADC_InitStructure);
|
||||
|
||||
/* Enable ADCx */
|
||||
ADC_Cmd(ADCx, ENABLE);
|
||||
|
||||
/* Enable VBAT/VREF monitor */
|
||||
ADC_VBATCmd(ENABLE);
|
||||
|
||||
/* Enable temperature sensor */
|
||||
ADC_TempSensorVrefintCmd(ENABLE);
|
||||
}
|
||||
|
||||
uint32_t adc_read_channel(int channel)
|
||||
{
|
||||
int timeout = 10000;
|
||||
|
||||
if (channel > (ADC_NUM_CHANNELS-1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ADC regular channel config ADC/Channel/SEQ Rank/Sample time */
|
||||
ADC_RegularChannelConfig(ADCx, channel, 1, ADC_SampleTime_15Cycles);
|
||||
|
||||
/* Start ADC single conversion */
|
||||
ADC_SoftwareStartConv(ADCx);
|
||||
|
||||
/* Wait for conversion to be complete*/
|
||||
while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) {
|
||||
}
|
||||
|
||||
/* ADC conversion timed out */
|
||||
if (timeout == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return converted data */
|
||||
return ADC_GetConversionValue(ADCx);
|
||||
}
|
||||
|
||||
int adc_read_core_temp()
|
||||
{
|
||||
int timeout = 10000;
|
||||
|
||||
/* ADC temperature sensor channel config ADC/Channel/SEQ Rank/Sample time */
|
||||
/* Note: sample time must be higher than minimum sample time */
|
||||
ADC_RegularChannelConfig(ADCx, ADC_TEMP_CHANNEL, 1, ADC_SampleTime_480Cycles);
|
||||
|
||||
/* Start ADC single conversion */
|
||||
ADC_SoftwareStartConv(ADCx);
|
||||
|
||||
/* Wait for conversion to be complete*/
|
||||
while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) {
|
||||
}
|
||||
|
||||
/* ADC conversion timed out */
|
||||
if (timeout == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert ADC reading to temperature */
|
||||
/* Temperature formula from datasheet P.411 */
|
||||
return ((ADC_GetConversionValue(ADCx) - CORE_TEMP_V25) / CORE_TEMP_AVG_SLOPE) + 25;
|
||||
}
|
||||
|
||||
float adc_read_core_vbat()
|
||||
{
|
||||
int timeout = 10000;
|
||||
|
||||
/* ADC VBAT channel config ADC/Channel/SEQ Rank/Sample time */
|
||||
/* Note: sample time must be higher than minimum sample time */
|
||||
ADC_RegularChannelConfig(ADCx, ADC_VBAT_CHANNEL, 1, ADC_SampleTime_144Cycles);
|
||||
|
||||
/* Start ADC single conversion */
|
||||
ADC_SoftwareStartConv(ADCx);
|
||||
|
||||
/* Wait for conversion to be complete */
|
||||
while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) {
|
||||
}
|
||||
|
||||
/* ADC conversion timed out */
|
||||
if (timeout == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert ADC reading to voltage, VBAT pin is
|
||||
internally connected to a bridge divider by VBAT_DIV */
|
||||
return ADC_GetConversionValue(ADCx)*VBAT_DIV/4096.0f*3.3f;
|
||||
}
|
||||
|
||||
float adc_read_core_vref()
|
||||
{
|
||||
int timeout = 10000;
|
||||
|
||||
/* ADC VBAT channel config ADC/Channel/SEQ Rank/Sample time */
|
||||
/* Note: sample time must be higher than minimum sample time */
|
||||
ADC_RegularChannelConfig(ADCx, ADC_VREF_CHANNEL, 1, ADC_SampleTime_112Cycles);
|
||||
|
||||
/* Start ADC single conversion */
|
||||
ADC_SoftwareStartConv(ADCx);
|
||||
|
||||
/* Wait for conversion to be complete*/
|
||||
while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) {
|
||||
}
|
||||
|
||||
/* ADC conversion timed out */
|
||||
if (timeout == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert ADC reading to voltage */
|
||||
return ADC_GetConversionValue(ADCx)/4096.0f*3.3f;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Micro Python bindings */
|
||||
|
||||
typedef struct _pyb_adc_obj_t {
|
||||
mp_obj_base_t base;
|
||||
int adc_id;
|
||||
bool is_enabled;
|
||||
} pyb_adc_obj_t;
|
||||
|
||||
static mp_obj_t adc_obj_read_channel(mp_obj_t self_in, mp_obj_t channel) {
|
||||
mp_obj_t ret = mp_const_none;
|
||||
pyb_adc_obj_t *self = self_in;
|
||||
|
||||
if (self->is_enabled) {
|
||||
uint32_t chan = mp_obj_get_int(channel);
|
||||
uint32_t data = adc_read_channel(chan);
|
||||
ret = mp_obj_new_int(data);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static mp_obj_t adc_obj_read_core_temp(mp_obj_t self_in) {
|
||||
mp_obj_t ret = mp_const_none;
|
||||
pyb_adc_obj_t *self = self_in;
|
||||
|
||||
if (self->is_enabled) {
|
||||
int data = adc_read_core_temp();
|
||||
ret = mp_obj_new_int(data);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static mp_obj_t adc_obj_read_core_vbat(mp_obj_t self_in) {
|
||||
mp_obj_t ret = mp_const_none;
|
||||
pyb_adc_obj_t *self = self_in;
|
||||
|
||||
if (self->is_enabled) {
|
||||
float data = adc_read_core_vbat();
|
||||
ret = mp_obj_new_float(data);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static mp_obj_t adc_obj_read_core_vref(mp_obj_t self_in) {
|
||||
mp_obj_t ret = mp_const_none;
|
||||
pyb_adc_obj_t *self = self_in;
|
||||
|
||||
if (self->is_enabled) {
|
||||
float data = adc_read_core_vref();
|
||||
ret = mp_obj_new_float(data);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void adc_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
|
||||
pyb_adc_obj_t *self = self_in;
|
||||
print(env, "<ADC %lu>", self->adc_id);
|
||||
}
|
||||
|
||||
static MP_DEFINE_CONST_FUN_OBJ_2(adc_obj_read_channel_obj, adc_obj_read_channel);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_temp_obj, adc_obj_read_core_temp);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_vbat_obj, adc_obj_read_core_vbat);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_vref_obj, adc_obj_read_core_vref);
|
||||
|
||||
static const mp_method_t adc_methods[] = {
|
||||
{ "read_channel", &adc_obj_read_channel_obj},
|
||||
{ "read_core_temp", &adc_obj_read_core_temp_obj},
|
||||
{ "read_core_vbat", &adc_obj_read_core_vbat_obj},
|
||||
{ "read_core_vref", &adc_obj_read_core_vref_obj},
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
static const mp_obj_type_t adc_obj_type = {
|
||||
{ &mp_const_type },
|
||||
"ADC",
|
||||
.print = adc_obj_print,
|
||||
.methods = adc_methods,
|
||||
};
|
||||
|
||||
mp_obj_t pyb_ADC(mp_obj_t resolution) {
|
||||
/* init ADC */
|
||||
adc_init(mp_obj_get_int(resolution));
|
||||
|
||||
pyb_adc_obj_t *o = m_new_obj(pyb_adc_obj_t);
|
||||
o->base.type = &adc_obj_type;
|
||||
o->adc_id = 1;
|
||||
o->is_enabled = true;
|
||||
return o;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user