/// \method names() /// Returns the cpu and board names for this pin. STATIC mp_obj_t pin_names(mp_obj_t self_in) { pin_obj_t *self = self_in; mp_obj_t result = mp_obj_new_list(0, NULL); mp_obj_list_append(result, MP_OBJ_NEW_QSTR(self->name)); mp_map_t *map = mp_obj_dict_get_map((mp_obj_t)&pin_board_pins_locals_dict); mp_map_elem_t *elem = map->table; for (mp_uint_t i = 0; i < map->used; i++, elem++) { if (elem->value == self) { mp_obj_list_append(result, elem->key); } } return result; }
STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) { // TODO: Implement all args assert(n_args == 2); assert(MP_OBJ_IS_STR(args[0])); const char *host = mp_obj_str_get_str(args[0]); const char *serv = NULL; // getaddrinfo accepts port in string notation, so however // it may seem stupid, we need to convert int to str if (MP_OBJ_IS_SMALL_INT(args[1])) { int port = (short)MP_OBJ_SMALL_INT_VALUE(args[1]); char buf[6]; sprintf(buf, "%d", port); serv = buf; } else { serv = mp_obj_str_get_str(args[1]); } struct addrinfo hints; struct addrinfo *addr; memset(&hints, 0, sizeof(hints)); int res = getaddrinfo(host, serv, NULL/*&hints*/, &addr); if (res != 0) { // CPython: socket.gaierror nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[addrinfo error %d]", res)); } assert(addr); mp_obj_t list = mp_obj_new_list(0, NULL); for (; addr; addr = addr->ai_next) { mp_obj_tuple_t *t = mp_obj_new_tuple(5, NULL); t->items[0] = MP_OBJ_NEW_SMALL_INT((machine_int_t)addr->ai_family); t->items[1] = MP_OBJ_NEW_SMALL_INT((machine_int_t)addr->ai_socktype); t->items[2] = MP_OBJ_NEW_SMALL_INT((machine_int_t)addr->ai_protocol); // "canonname will be a string representing the canonical name of the host // if AI_CANONNAME is part of the flags argument; else canonname will be empty." ?? if (addr->ai_canonname) { t->items[3] = MP_OBJ_NEW_QSTR(qstr_from_str(addr->ai_canonname)); } else { t->items[3] = mp_const_none; } t->items[4] = mp_obj_new_bytearray(addr->ai_addrlen, addr->ai_addr); mp_obj_list_append(list, t); } return list; }
// method socket.listen(backlog) STATIC mp_obj_t esp_socket_listen(mp_obj_t self_in, mp_obj_t backlog) { esp_socket_obj_t *s = self_in; if (esp_socket_listening != NULL) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "only one espconn can listen at a time")); } esp_socket_listening = s; s->connlist = mp_obj_new_list(0, NULL); espconn_regist_connectcb(s->espconn, esp_socket_connect_callback_server); espconn_accept(s->espconn); espconn_regist_time(s->espconn, 1500, 0); return mp_const_none; }
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, machine_uint_t line, qstr block) { #if MICROPY_ENABLE_GC if (gc_is_locked()) { // We can't allocate memory, so don't bother to try return; } #endif GET_NATIVE_EXCEPTION(self, self_in); // for traceback, we are just using the list object for convenience, it's not really a list of Python objects if (self->traceback == MP_OBJ_NULL) { self->traceback = mp_obj_new_list(0, NULL); } mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)file); mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)line); mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)block); }
// function usocket.getaddrinfo(host, port) /// \function getaddrinfo(host, port) STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { mp_uint_t hlen; const char *host = mp_obj_str_get_data(host_in, &hlen); mp_int_t port = mp_obj_get_int(port_in); // ipv4 only uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; int32_t result = wlan_gethostbyname(host, hlen, out_ip, AF_INET); if (result != 0) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(result))); } mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCK_STREAM); tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_LITTLE); return mp_obj_new_list(1, (mp_obj_t*)&tuple); }
/// \method scan(timeout) /// Scan for devices. Timeout is in milliseconds and will set the duration /// of the scanning. /// STATIC mp_obj_t scanner_scan(mp_obj_t self_in, mp_obj_t timeout_in) { ubluepy_scanner_obj_t * self = MP_OBJ_TO_PTR(self_in); mp_int_t timeout = mp_obj_get_int(timeout_in); self->adv_reports = mp_obj_new_list(0, NULL); ble_drv_adv_report_handler_set(MP_OBJ_FROM_PTR(self), adv_event_handler); // start ble_drv_scan_start(false); // sleep mp_hal_delay_ms(timeout); // stop ble_drv_scan_stop(); return self->adv_reports; }
mp_obj_t mp_seq_extract_slice(uint len, const mp_obj_t *seq, mp_bound_slice_t *indexes) { machine_int_t start = indexes->start, stop = indexes->stop; machine_int_t step = indexes->step; mp_obj_t res = mp_obj_new_list(0, NULL); if (step < 0) { stop--; while (start <= stop) { mp_obj_list_append(res, seq[stop]); stop += step; } } else { while (start < stop) { mp_obj_list_append(res, seq[start]); start += step; } } return res; }
/// \method scan() /// Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond. /// Only valid when in master mode. STATIC mp_obj_t pyb_i2c_scan(mp_obj_t self_in) { pyb_i2c_obj_t *self = self_in; if (!in_master_mode(self)) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "I2C must be a master")); } mp_obj_t list = mp_obj_new_list(0, NULL); for (uint addr = 1; addr <= 127; addr++) { for (int i = 0; i < 10; i++) { HAL_StatusTypeDef status = HAL_I2C_IsDeviceReady(self->i2c, addr << 1, 10, 200); if (status == HAL_OK) { mp_obj_list_append(list, mp_obj_new_int(addr)); break; } } } return list; }
mp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes) { (void)len; // TODO can we remove len from the arg list? mp_int_t start = indexes->start, stop = indexes->stop; mp_int_t step = indexes->step; mp_obj_t res = mp_obj_new_list(0, NULL); if (step < 0) { while (start >= stop) { mp_obj_list_append(res, seq[start]); start += step; } } else { while (start < stop) { mp_obj_list_append(res, seq[start]); start += step; } } return res; }
STATIC mp_obj_t re_split(mp_uint_t n_args, const mp_obj_t *args) { mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]); Subject subj; mp_uint_t len; subj.begin = mp_obj_str_get_data(args[1], &len); subj.end = subj.begin + len; int caps_num = (self->re.sub + 1) * 2; int maxsplit = 0; if (n_args > 2) { maxsplit = mp_obj_get_int(args[2]); } mp_obj_t retval = mp_obj_new_list(0, NULL); const char **caps = alloca(caps_num * sizeof(char*)); while (true) { // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char memset((char**)caps, 0, caps_num * sizeof(char*)); int res = re1_5_recursiveloopprog(&self->re, &subj, caps, caps_num, false); // if we didn't have a match, or had an empty match, it's time to stop if (!res || caps[0] == caps[1]) { break; } mp_obj_t s = mp_obj_new_str(subj.begin, caps[0] - subj.begin, false); mp_obj_list_append(retval, s); if (self->re.sub > 0) { mp_not_implemented("Splitting with sub-captures"); } subj.begin = caps[1]; if (maxsplit > 0 && --maxsplit == 0) { break; } } mp_obj_t s = mp_obj_new_str(subj.begin, subj.end - subj.begin, false); mp_obj_list_append(retval, s); return retval; }
STATIC mp_obj_t re_split(uint n_args, const mp_obj_t *args) { mp_obj_re_t *self = args[0]; Subject subj; mp_uint_t len; subj.begin = mp_obj_str_get_data(args[1], &len); subj.end = subj.begin + len; int caps_num = (self->re.sub + 1) * 2; int maxsplit = 0; if (n_args > 2) { maxsplit = mp_obj_int_get_truncated(args[2]); } mp_obj_t retval = mp_obj_new_list(0, NULL); const char **caps = alloca(caps_num * sizeof(char*)); while (true) { int res = re1_5_recursiveloopprog(&self->re, &subj, caps, caps_num, false); // if we didn't have a match, or had an empty match, it's time to stop if (!res || caps[0] == caps[1]) { break; } mp_obj_t s = mp_obj_new_str(subj.begin, caps[0] - subj.begin, false); mp_obj_list_append(retval, s); if (self->re.sub > 0) { mp_not_implemented("Splitting with sub-captures"); } subj.begin = caps[1]; if (maxsplit > 0 && --maxsplit == 0) { break; } } mp_obj_t s = mp_obj_new_str(subj.begin, subj.end - subj.begin, false); mp_obj_list_append(retval, s); return retval; }
/// \method poll([timeout]) /// Timeout is in milliseconds. STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) { mp_obj_poll_t *self = args[0]; // work out timeout (its given already in ms) mp_uint_t timeout = -1; if (n_args == 2) { if (args[1] != mp_const_none) { mp_int_t timeout_i = mp_obj_get_int(args[1]); if (timeout_i >= 0) { timeout = timeout_i; } } } mp_uint_t start_tick = HAL_GetTick(); for (;;) { // poll the objects mp_uint_t n_ready = poll_map_poll(&self->poll_map, NULL); if (n_ready > 0 || (timeout != -1 && HAL_GetTick() - start_tick >= timeout)) { // one or more objects are ready, or we had a timeout mp_obj_list_t *ret_list = mp_obj_new_list(n_ready, NULL); mp_uint_t n_ready = 0; for (mp_uint_t i = 0; i < self->poll_map.alloc; ++i) { if (!MP_MAP_SLOT_IS_FILLED(&self->poll_map, i)) { continue; } poll_obj_t *poll_obj = (poll_obj_t*)self->poll_map.table[i].value; if (poll_obj->flags_ret != 0) { mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret)}; ret_list->items[n_ready++] = mp_obj_new_tuple(2, tuple); } } return ret_list; } __WFI(); } }
STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) { mp_obj_poll_t *self = args[0]; mp_uint_t n_ready = poll_poll_internal(n_args, args); // one or more objects are ready, or we had a timeout mp_obj_list_t *ret_list = mp_obj_new_list(n_ready, NULL); n_ready = 0; for (mp_uint_t i = 0; i < self->poll_map.alloc; ++i) { if (!MP_MAP_SLOT_IS_FILLED(&self->poll_map, i)) { continue; } poll_obj_t *poll_obj = (poll_obj_t*)self->poll_map.table[i].value; if (poll_obj->flags_ret != 0) { mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret)}; ret_list->items[n_ready++] = mp_obj_new_tuple(2, tuple); if (self->flags & FLAG_ONESHOT) { // Don't poll next time, until new event flags will be set explicitly poll_obj->flags = 0; } } } return ret_list; }
static mp_obj_t str_split(uint n_args, const mp_obj_t *args) { int splits = -1; mp_obj_t sep = mp_const_none; if (n_args > 1) { sep = args[1]; if (n_args > 2) { splits = MP_OBJ_SMALL_INT_VALUE(args[2]); } } assert(sep == mp_const_none); (void)sep; // unused; to hush compiler warning mp_obj_t res = mp_obj_new_list(0, NULL); GET_STR_DATA_LEN(args[0], s, len); const byte *top = s + len; const byte *start; // Initial whitespace is not counted as split, so we pre-do it while (s < top && is_ws(*s)) s++; while (s < top && splits != 0) { start = s; while (s < top && !is_ws(*s)) s++; rt_list_append(res, mp_obj_new_str(start, s - start, false)); if (s >= top) { break; } while (s < top && is_ws(*s)) s++; if (splits > 0) { splits--; } } if (s < top) { rt_list_append(res, mp_obj_new_str(s, top - s, false)); } return res; }
// lwip.getaddrinfo STATIC mp_obj_t lwip_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { mp_uint_t hlen; const char *host = mp_obj_str_get_data(host_in, &hlen); mp_int_t port = mp_obj_get_int(port_in); getaddrinfo_state_t state; state.status = 0; err_t ret = dns_gethostbyname(host, (ip_addr_t*)&state.ipaddr, lwip_getaddrinfo_cb, &state); switch (ret) { case ERR_OK: // cached state.status = 1; break; case ERR_INPROGRESS: while (state.status == 0) { poll_sockets(); } break; default: state.status = ret; } if (state.status < 0) { // TODO: CPython raises gaierror, we raise with native lwIP negative error // values, to differentiate from normal errno's at least in such way. nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(state.status))); } mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM); tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); tuple->items[4] = netutils_format_inet_addr((uint8_t*)&state.ipaddr, port, NETUTILS_BIG); return mp_obj_new_list(1, (mp_obj_t*)&tuple); }
// lwip.getaddrinfo STATIC mp_obj_t lwip_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { mp_uint_t hlen; const char *host = mp_obj_str_get_data(host_in, &hlen); mp_int_t port = mp_obj_get_int(port_in); ip_addr_t result; lwip_dns_returned = 0; switch (dns_gethostbyname(host, &result, _lwip_dns_incoming, NULL)) { case ERR_OK: { break; } case ERR_INPROGRESS: { while(!lwip_dns_returned) { mp_hal_delay_ms(100); } if (lwip_dns_returned == 2) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOENT))); } break; } default: { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOENT))); } } uint8_t out_ip[NETUTILS_IPV4ADDR_BUFSIZE]; memcpy(out_ip, lwip_dns_result, 4); mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM); tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_BIG); return mp_obj_new_list(1, (mp_obj_t*)&tuple); }
STATIC mp_obj_t mod_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { // TODO: Implement 5th and 6th args const char *host = mp_obj_str_get_str(args[0]); const char *serv = NULL; struct addrinfo hints; char buf[6]; memset(&hints, 0, sizeof(hints)); // getaddrinfo accepts port in string notation, so however // it may seem stupid, we need to convert int to str if (MP_OBJ_IS_SMALL_INT(args[1])) { unsigned port = (unsigned short)MP_OBJ_SMALL_INT_VALUE(args[1]); snprintf(buf, sizeof(buf), "%u", port); serv = buf; hints.ai_flags = AI_NUMERICSERV; #ifdef __UCLIBC_MAJOR__ #if __UCLIBC_MAJOR__ == 0 && (__UCLIBC_MINOR__ < 9 || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ <= 32)) // "warning" requires -Wno-cpp which is a relatively new gcc option, so we choose not to use it. //#warning Working around uClibc bug with numeric service name // Older versions og uClibc have bugs when numeric ports in service // arg require also hints.ai_socktype (or hints.ai_protocol) != 0 // This actually was fixed in 0.9.32.1, but uClibc doesn't allow to // test for that. // http://git.uclibc.org/uClibc/commit/libc/inet/getaddrinfo.c?id=bc3be18145e4d5 // Note that this is crude workaround, precluding UDP socket addresses // to be returned. TODO: set only if not set by Python args. hints.ai_socktype = SOCK_STREAM; #endif #endif } else { serv = mp_obj_str_get_str(args[1]); } if (n_args > 2) { hints.ai_family = MP_OBJ_SMALL_INT_VALUE(args[2]); if (n_args > 3) { hints.ai_socktype = MP_OBJ_SMALL_INT_VALUE(args[3]); } } struct addrinfo *addr_list; int res = getaddrinfo(host, serv, &hints, &addr_list); if (res != 0) { // CPython: socket.gaierror nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[addrinfo error %d]", res)); } assert(addr_list); mp_obj_t list = mp_obj_new_list(0, NULL); for (struct addrinfo *addr = addr_list; addr; addr = addr->ai_next) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(addr->ai_family); t->items[1] = MP_OBJ_NEW_SMALL_INT(addr->ai_socktype); t->items[2] = MP_OBJ_NEW_SMALL_INT(addr->ai_protocol); // "canonname will be a string representing the canonical name of the host // if AI_CANONNAME is part of the flags argument; else canonname will be empty." ?? if (addr->ai_canonname) { t->items[3] = MP_OBJ_NEW_QSTR(qstr_from_str(addr->ai_canonname)); } else { t->items[3] = mp_const_none; } t->items[4] = mp_obj_new_bytearray(addr->ai_addrlen, addr->ai_addr); mp_obj_list_append(list, MP_OBJ_FROM_PTR(t)); } freeaddrinfo(addr_list); return list; }
STATIC mp_obj_t esp_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { // TODO support additional args beyond the first two struct addrinfo *res = NULL; _socket_getaddrinfo2(args[0], args[1], &res); mp_obj_t ret_list = mp_obj_new_list(0, NULL); for (struct addrinfo *resi = res; resi; resi = resi->ai_next) { mp_obj_t addrinfo_objs[5] = { mp_obj_new_int(resi->ai_family), mp_obj_new_int(resi->ai_socktype), mp_obj_new_int(resi->ai_protocol), mp_obj_new_str(resi->ai_canonname, strlen(resi->ai_canonname)), mp_const_none }; if (resi->ai_family == AF_INET) { struct sockaddr_in *addr = (struct sockaddr_in *)resi->ai_addr; // This looks odd, but it's really just a u32_t ip4_addr_t ip4_addr = { .addr = addr->sin_addr.s_addr }; char buf[16]; ip4addr_ntoa_r(&ip4_addr, buf, sizeof(buf)); mp_obj_t inaddr_objs[2] = { mp_obj_new_str(buf, strlen(buf)), mp_obj_new_int(ntohs(addr->sin_port)) }; addrinfo_objs[4] = mp_obj_new_tuple(2, inaddr_objs); } mp_obj_list_append(ret_list, mp_obj_new_tuple(5, addrinfo_objs)); } if (res) lwip_freeaddrinfo(res); return ret_list; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_socket_getaddrinfo_obj, 2, 6, esp_socket_getaddrinfo); STATIC mp_obj_t esp_socket_initialize() { static int initialized = 0; if (!initialized) { ESP_LOGI("modsocket", "Initializing"); tcpip_adapter_init(); initialized = 1; } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_socket_initialize_obj, esp_socket_initialize); STATIC const mp_map_elem_t mp_module_socket_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usocket) }, { MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&esp_socket_initialize_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&get_socket_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_socket_getaddrinfo_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(AF_INET) }, { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET6), MP_OBJ_NEW_SMALL_INT(AF_INET6) }, { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(SOCK_STREAM) }, { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(SOCK_DGRAM) }, { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_RAW), MP_OBJ_NEW_SMALL_INT(SOCK_RAW) }, { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(IPPROTO_TCP) }, { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(IPPROTO_UDP) }, { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IP), MP_OBJ_NEW_SMALL_INT(IPPROTO_IP) }, { MP_OBJ_NEW_QSTR(MP_QSTR_SOL_SOCKET), MP_OBJ_NEW_SMALL_INT(SOL_SOCKET) }, { MP_OBJ_NEW_QSTR(MP_QSTR_SO_REUSEADDR), MP_OBJ_NEW_SMALL_INT(SO_REUSEADDR) }, { MP_OBJ_NEW_QSTR(MP_QSTR_IP_ADD_MEMBERSHIP), MP_OBJ_NEW_SMALL_INT(IP_ADD_MEMBERSHIP) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_socket_globals, mp_module_socket_globals_table); const mp_obj_module_t mp_module_usocket = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_socket_globals, };
// This function implements a simple non-recursive JSON parser. // // The JSON specification is at http://www.ietf.org/rfc/rfc4627.txt // The parser here will parse any valid JSON and return the correct // corresponding Python object. It allows through a superset of JSON, since // it treats commas and colons as "whitespace", and doesn't care if // brackets/braces are correctly paired. It will raise a ValueError if the // input is outside it's specs. // // Most of the work is parsing the primitives (null, false, true, numbers, // strings). It does 1 pass over the input string and so is easily extended to // being able to parse from a non-seekable stream. It tries to be fast and // small in code size, while not using more RAM than necessary. STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { mp_uint_t len; const char *s = mp_obj_str_get_data(obj, &len); const char *top = s + len; vstr_t vstr; vstr_init(&vstr, 8); mp_obj_list_t stack; // we use a list as a simple stack for nested JSON stack.len = 0; stack.items = NULL; mp_obj_t stack_top = MP_OBJ_NULL; mp_obj_type_t *stack_top_type = NULL; mp_obj_t stack_key = MP_OBJ_NULL; for (;;) { cont: if (s == top) { break; } mp_obj_t next = MP_OBJ_NULL; bool enter = false; switch (*s) { case ',': case ':': case ' ': case '\t': case '\n': case '\r': s += 1; goto cont; case 'n': if (s + 3 < top && s[1] == 'u' && s[2] == 'l' && s[3] == 'l') { s += 4; next = mp_const_none; } else { goto fail; } break; case 'f': if (s + 4 < top && s[1] == 'a' && s[2] == 'l' && s[3] == 's' && s[4] == 'e') { s += 5; next = mp_const_false; } else { goto fail; } break; case 't': if (s + 3 < top && s[1] == 'r' && s[2] == 'u' && s[3] == 'e') { s += 4; next = mp_const_true; } else { goto fail; } break; case '"': vstr_reset(&vstr); for (s++; s < top && *s != '"';) { byte c = *s; if (c == '\\') { s++; c = *s; switch (c) { case 'b': c = 0x08; break; case 'f': c = 0x0c; break; case 'n': c = 0x0a; break; case 'r': c = 0x0d; break; case 't': c = 0x09; break; case 'u': { if (s + 4 >= top) { goto fail; } mp_uint_t num = 0; for (int i = 0; i < 4; i++) { c = (*++s | 0x20) - '0'; if (c > 9) { c -= ('a' - ('9' + 1)); } num = (num << 4) | c; } vstr_add_char(&vstr, num); goto str_cont; } } } vstr_add_byte(&vstr, c); str_cont: s++; } if (s == top) { goto fail; } s++; next = mp_obj_new_str(vstr.buf, vstr.len, false); break; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { bool flt = false; vstr_reset(&vstr); for (; s < top; s++) { if (*s == '.' || *s == 'E' || *s == 'e') { flt = true; } else if (*s == '-' || unichar_isdigit(*s)) { // pass } else { break; } vstr_add_byte(&vstr, *s); } if (flt) { next = mp_parse_num_decimal(vstr.buf, vstr.len, false, false, NULL); } else { next = mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL); } break; } case '[': next = mp_obj_new_list(0, NULL); enter = true; s += 1; break; case '{': next = mp_obj_new_dict(0); enter = true; s += 1; break; case '}': case ']': { s += 1; if (stack_top == MP_OBJ_NULL) { // no object at all goto fail; } if (stack.len == 0) { // finished; compound object goto success; } stack.len -= 1; stack_top = stack.items[stack.len]; stack_top_type = mp_obj_get_type(stack_top); goto cont; } default: goto fail; } if (stack_top == MP_OBJ_NULL) { stack_top = next; stack_top_type = mp_obj_get_type(stack_top); if (!enter) { // finished; single primitive only goto success; } } else { // append to list or dict if (stack_top_type == &mp_type_list) { mp_obj_list_append(stack_top, next); } else { if (stack_key == MP_OBJ_NULL) { stack_key = next; if (enter) { goto fail; } } else { mp_obj_dict_store(stack_top, stack_key, next); stack_key = MP_OBJ_NULL; } } if (enter) { if (stack.items == NULL) { mp_obj_list_init(&stack, 1); stack.items[0] = stack_top; } else { mp_obj_list_append(MP_OBJ_FROM_PTR(&stack), stack_top); } stack_top = next; stack_top_type = mp_obj_get_type(stack_top); } } } success: // eat trailing whitespace while (s < top && unichar_isspace(*s)) { s++; } if (s < top) { // unexpected chars goto fail; } if (stack_top == MP_OBJ_NULL || stack.len != 0) { // not exactly 1 object goto fail; } vstr_clear(&vstr); return stack_top; fail: nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "syntax error in JSON")); }
STATIC mp_obj_t os_listdir(uint n_args, const mp_obj_t *args) { const mp_obj_type_t *local_str_type = &mp_type_str; const char *path; if (n_args == 1) { if (mp_obj_get_type(args[0]) == &mp_type_bytes) { local_str_type = &mp_type_bytes; } path = mp_obj_str_get_str(args[0]); } else { path = "0:"; } FRESULT res; FILINFO fno; DIR dir; #if _USE_LFN fno.lfname = lfn; fno.lfsize = sizeof lfn; #endif res = f_opendir(&dir, path); /* Open the directory */ if (res != FR_OK) { // TODO should be mp_type_FileNotFoundError nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path)); } mp_obj_t dir_list = mp_obj_new_list(0, NULL); uint path_len = strlen(path); if (path[path_len - 1] == '/') { path_len--; } for (;;) { res = f_readdir(&dir, &fno); /* Read a directory item */ if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ if (fno.fname[0] == '.' && fno.fname[1] == 0) continue; /* Ignore . entry */ if (fno.fname[0] == '.' && fno.fname[1] == '.' && fno.fname[2] == 0) continue; /* Ignore .. entry */ #if _USE_LFN char *fn = *fno.lfname ? fno.lfname : fno.fname; #else char *fn = fno.fname; #endif if (fno.fattrib & AM_DIR) { /* It is a directory */ } else { /* It is a file. */ } // make a string object for this entry byte *data; uint fn_len = strlen(fn); mp_obj_t entry_o = mp_obj_str_builder_start(local_str_type, path_len + 1 + fn_len, &data); memcpy(data, path, path_len); data[path_len] = '/'; memcpy(data + path_len + 1, fn, fn_len); // add the entry to the list mp_obj_list_append(dir_list, mp_obj_str_builder_end(entry_o)); } f_closedir(&dir); return dir_list; }
/// \function select(rlist, wlist, xlist[, timeout]) STATIC mp_obj_t select_select(uint n_args, const mp_obj_t *args) { // get array data from tuple/list arguments mp_uint_t rwx_len[3]; mp_obj_t *r_array, *w_array, *x_array; mp_obj_get_array(args[0], &rwx_len[0], &r_array); mp_obj_get_array(args[1], &rwx_len[1], &w_array); mp_obj_get_array(args[2], &rwx_len[2], &x_array); // get timeout mp_uint_t timeout = -1; if (n_args == 4) { if (args[3] != mp_const_none) { #if MICROPY_PY_BUILTINS_FLOAT float timeout_f = mp_obj_get_float(args[3]); if (timeout_f >= 0) { timeout = (mp_uint_t)(timeout_f * 1000); } #else timeout = mp_obj_get_int(args[3]) * 1000; #endif } } // merge separate lists and get the ioctl function for each object mp_map_t poll_map; mp_map_init(&poll_map, rwx_len[0] + rwx_len[1] + rwx_len[2]); poll_map_add(&poll_map, r_array, rwx_len[0], MP_IOCTL_POLL_RD, true); poll_map_add(&poll_map, w_array, rwx_len[1], MP_IOCTL_POLL_WR, true); poll_map_add(&poll_map, x_array, rwx_len[2], MP_IOCTL_POLL_ERR | MP_IOCTL_POLL_HUP, true); mp_uint_t start_tick = HAL_GetTick(); rwx_len[0] = rwx_len[1] = rwx_len[2] = 0; for (;;) { // poll the objects mp_uint_t n_ready = poll_map_poll(&poll_map, rwx_len); if (n_ready > 0 || (timeout != -1 && HAL_GetTick() - start_tick >= timeout)) { // one or more objects are ready, or we had a timeout mp_obj_t list_array[3]; list_array[0] = mp_obj_new_list(rwx_len[0], NULL); list_array[1] = mp_obj_new_list(rwx_len[1], NULL); list_array[2] = mp_obj_new_list(rwx_len[2], NULL); rwx_len[0] = rwx_len[1] = rwx_len[2] = 0; for (mp_uint_t i = 0; i < poll_map.alloc; ++i) { if (!MP_MAP_SLOT_IS_FILLED(&poll_map, i)) { continue; } poll_obj_t *poll_obj = (poll_obj_t*)poll_map.table[i].value; if (poll_obj->flags_ret & MP_IOCTL_POLL_RD) { ((mp_obj_list_t*)list_array[0])->items[rwx_len[0]++] = poll_obj->obj; } if (poll_obj->flags_ret & MP_IOCTL_POLL_WR) { ((mp_obj_list_t*)list_array[1])->items[rwx_len[1]++] = poll_obj->obj; } if ((poll_obj->flags_ret & ~(MP_IOCTL_POLL_RD | MP_IOCTL_POLL_WR)) != 0) { ((mp_obj_list_t*)list_array[2])->items[rwx_len[2]++] = poll_obj->obj; } } mp_map_deinit(&poll_map); return mp_obj_new_tuple(3, list_array); } __WFI(); } }
mp_obj_t mlx90620_read() { float temp[64]; float max_temp = FLT_MIN; float min_temp = FLT_MAX; image_t img = { .w=4, .h=16, .bpp=1, .pixels=xalloc(16*4) }; // get raw temperatures mlx90620_read_to(temp); // normalize temp readings for (int i=0; i<64; i++) { if (temp[i] > max_temp) { max_temp = temp[i]; } else if (temp[i] < min_temp) { min_temp = temp[i]; } } for (int i=0; i<64; i++) { img.pixels[i] = (uint8_t)(((temp[i]-min_temp)/(max_temp-min_temp))*255.0f); } return py_image_from_struct(&img); } mp_obj_t mlx90620_read_raw() { float *t = m_new(float, 64); mp_obj_t t_list = mp_obj_new_list(0, NULL); // get raw temperatures mlx90620_read_to(t); // normalize temp readings for (int i=0; i<64; i++) { mp_obj_list_append(t_list, mp_obj_new_float(t[i])); } return t_list; } mp_obj_t mlx90620_init() { uint8_t cmd_buf[5]; uint8_t EEPROM_DATA[256]; // Init I2C soft_i2c_init(); // Read EEPROM data cmd_buf[0]=REG_EEPROM_DATA; soft_i2c_write_bytes(MLX_EEPROM_ADDR, cmd_buf, 1, false); soft_i2c_read_bytes(MLX_EEPROM_ADDR, EEPROM_DATA, 256, true); // Write oscillator trimming value uint8_t trim = EEPROM_DATA[OSC_TRIM_OFFSET]; memcpy(cmd_buf, (uint8_t [5]){WRITE_OSC_TRIM, (uint8_t)(trim-0xAA), trim, 0x56, 0x00}, 5); soft_i2c_write_bytes(MLX_SLAVE_ADDR, cmd_buf, sizeof(cmd_buf), true); // Write configuration register uint8_t lsb = 0x0A; //0x09==16Hz uint8_t msb = 0x74; memcpy(cmd_buf, (uint8_t [5]){SET_CONFIG_DATA, (uint8_t)(lsb-0x55), lsb, (uint8_t)(msb-0x55), msb}, 5); soft_i2c_write_bytes(MLX_SLAVE_ADDR, cmd_buf, sizeof(cmd_buf), true); // Calculate Ta constants v_th = (256 * EEPROM_DATA[VTH_H] + EEPROM_DATA[VTH_L]); k_t1 = (256 * EEPROM_DATA[KT1_H] + EEPROM_DATA[KT1_L]) / 1024.0f; k_t2 = (256 * EEPROM_DATA[KT2_H] + EEPROM_DATA[KT2_L]) / 1048576.0f; emissivity = ((unsigned int)256 * EEPROM_DATA[CAL_EMIS_H] + EEPROM_DATA[CAL_EMIS_L]) / 32768.0f; k_t1_sq = k_t1 * k_t1; a_cp = (int8_t)EEPROM_DATA[CAL_ACP]; b_cp = (int8_t)EEPROM_DATA[CAL_BCP]; tgc = (int8_t)EEPROM_DATA[CAL_TGC]; b_i_scale = EEPROM_DATA[CAL_BI_SCALE]; // Hack for (int i=0; i<8; i++) { EEPROM_DATA[i]=EEPROM_DATA[i+8]; EEPROM_DATA[i+64]=EEPROM_DATA[i+8+64]; } for (int i=0; i<64; i++) { // Read pixel offsets a_ij[i] = (int8_t)EEPROM_DATA[i]; // Read slope coefficients b_ij[i] = (int8_t)EEPROM_DATA[i+4]; } return mp_const_true; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mlx90620_init_obj, mlx90620_init); STATIC MP_DEFINE_CONST_FUN_OBJ_0(mlx90620_read_obj, mlx90620_read); STATIC MP_DEFINE_CONST_FUN_OBJ_0(mlx90620_read_raw_obj, mlx90620_read_raw); static const mp_map_elem_t globals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_mlx) }, //{ MP_OBJ_NEW_QSTR(MP_QSTR_HZ_8), MP_OBJ_NEW_SMALL_INT(MLX_HZ_8)}, //{ MP_OBJ_NEW_QSTR(MP_QSTR_HZ_16), MP_OBJ_NEW_SMALL_INT(MLX_HZ_16)}, //{ MP_OBJ_NEW_QSTR(MP_QSTR_HZ_32), MP_OBJ_NEW_SMALL_INT(MLX_HZ_32)}, //{ MP_OBJ_NEW_QSTR(MP_QSTR_HZ_64), MP_OBJ_NEW_SMALL_INT(MLX_HZ_64)}, { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&mlx90620_init_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mlx90620_read_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_read_raw), (mp_obj_t)&mlx90620_read_raw_obj }, }; STATIC MP_DEFINE_CONST_DICT(globals_dict, globals_dict_table); static const mp_obj_module_t mlx_module = { .base = { &mp_type_module }, .name = MP_QSTR_mlx, .globals = (mp_obj_t)&globals_dict, }; const mp_obj_module_t *py_mlx90620_init() { return &mlx_module; }
STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) { const mp_stream_p_t *stream_p = mp_get_stream_raise(stream_obj, MP_STREAM_OP_READ); ujson_stream_t s = {stream_obj, stream_p->read, 0, 0}; vstr_t vstr; vstr_init(&vstr, 8); mp_obj_list_t stack; // we use a list as a simple stack for nested JSON stack.len = 0; stack.items = NULL; mp_obj_t stack_top = MP_OBJ_NULL; mp_obj_type_t *stack_top_type = NULL; mp_obj_t stack_key = MP_OBJ_NULL; S_NEXT(s); for (;;) { cont: if (S_END(s)) { break; } mp_obj_t next = MP_OBJ_NULL; bool enter = false; byte cur = S_CUR(s); S_NEXT(s); switch (cur) { case ',': case ':': case ' ': case '\t': case '\n': case '\r': goto cont; case 'n': if (S_CUR(s) == 'u' && S_NEXT(s) == 'l' && S_NEXT(s) == 'l') { S_NEXT(s); next = mp_const_none; } else { goto fail; } break; case 'f': if (S_CUR(s) == 'a' && S_NEXT(s) == 'l' && S_NEXT(s) == 's' && S_NEXT(s) == 'e') { S_NEXT(s); next = mp_const_false; } else { goto fail; } break; case 't': if (S_CUR(s) == 'r' && S_NEXT(s) == 'u' && S_NEXT(s) == 'e') { S_NEXT(s); next = mp_const_true; } else { goto fail; } break; case '"': vstr_reset(&vstr); for (; !S_END(s) && S_CUR(s) != '"';) { byte c = S_CUR(s); if (c == '\\') { c = S_NEXT(s); switch (c) { case 'b': c = 0x08; break; case 'f': c = 0x0c; break; case 'n': c = 0x0a; break; case 'r': c = 0x0d; break; case 't': c = 0x09; break; case 'u': { mp_uint_t num = 0; for (int i = 0; i < 4; i++) { c = (S_NEXT(s) | 0x20) - '0'; if (c > 9) { c -= ('a' - ('9' + 1)); } num = (num << 4) | c; } vstr_add_char(&vstr, num); goto str_cont; } } } vstr_add_byte(&vstr, c); str_cont: S_NEXT(s); } if (S_END(s)) { goto fail; } S_NEXT(s); next = mp_obj_new_str(vstr.buf, vstr.len, false); break; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { bool flt = false; vstr_reset(&vstr); for (;;) { vstr_add_byte(&vstr, cur); cur = S_CUR(s); if (cur == '.' || cur == 'E' || cur == 'e') { flt = true; } else if (cur == '-' || unichar_isdigit(cur)) { // pass } else { break; } S_NEXT(s); } if (flt) { next = mp_parse_num_decimal(vstr.buf, vstr.len, false, false, NULL); } else { next = mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL); } break; } case '[': next = mp_obj_new_list(0, NULL); enter = true; break; case '{': next = mp_obj_new_dict(0); enter = true; break; case '}': case ']': { if (stack_top == MP_OBJ_NULL) { // no object at all goto fail; } if (stack.len == 0) { // finished; compound object goto success; } stack.len -= 1; stack_top = stack.items[stack.len]; stack_top_type = mp_obj_get_type(stack_top); goto cont; } default: goto fail; } if (stack_top == MP_OBJ_NULL) { stack_top = next; stack_top_type = mp_obj_get_type(stack_top); if (!enter) { // finished; single primitive only goto success; } } else { // append to list or dict if (stack_top_type == &mp_type_list) { mp_obj_list_append(stack_top, next); } else { if (stack_key == MP_OBJ_NULL) { stack_key = next; if (enter) { goto fail; } } else { mp_obj_dict_store(stack_top, stack_key, next); stack_key = MP_OBJ_NULL; } } if (enter) { if (stack.items == NULL) { mp_obj_list_init(&stack, 1); stack.items[0] = stack_top; } else { mp_obj_list_append(MP_OBJ_FROM_PTR(&stack), stack_top); } stack_top = next; stack_top_type = mp_obj_get_type(stack_top); } } } success: // eat trailing whitespace while (unichar_isspace(S_CUR(s))) { S_NEXT(s); } if (!S_END(s)) { // unexpected chars goto fail; } if (stack_top == MP_OBJ_NULL || stack.len != 0) { // not exactly 1 object goto fail; } vstr_clear(&vstr); return stack_top; fail: nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "syntax error in JSON")); }
static py_var_t* py_create_var (py_handle_t* py, const char* name, size_t dim, uint32_t flags) { py_var_t* v; mp_obj_t obj; size_t i; size_t size; void** data; v = malloc(sizeof(py_var_t)); if (v == NULL) goto on_error_0; py->vars[py->nvar] = v; ++py->nvar; v->name = qstr_from_str(name); v->flags = flags; v->dim = dim; v->items = malloc(dim * sizeof(mp_obj_t)); if (v->items == NULL) goto on_error_1; if (v->flags & PY_FLAG_INT) { for (i = 0; i != dim; ++i) v->items[i] = MP_OBJ_NEW_SMALL_INT(0); } else { for (i = 0; i != dim; ++i) v->items[i] = mp_obj_new_float(0.0); } /* store default values so that no crash due to undefined variable */ if (v->flags & PY_FLAG_ARRAY) { v->index = MP_OBJ_NEW_SMALL_INT(0); v->list = mp_obj_new_list((mp_uint_t)v->dim, v->items); obj = v->list; } else { obj = v->items[0]; } mp_store_name(v->name, obj); if (v->flags & PY_FLAG_FLOAT) { size = dim * sizeof(mp_float_t); data = (void**)&v->data.f; } else { size = dim * sizeof(mp_int_t); data = (void**)&v->data.i; } *data = malloc(size); if (*data == NULL) goto on_error_2; return v; on_error_2: free(v->items); on_error_1: free(v); on_error_0: return NULL; }
STATIC mp_obj_t list_copy(mp_obj_t self_in) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); mp_obj_list_t *self = self_in; return mp_obj_new_list(self->len, self->items); }
int main(void) { // TODO disable JTAG /* STM32F4xx HAL library initialization: - Configure the Flash prefetch, instruction and Data caches - Configure the Systick to generate an interrupt each 1 msec - Set NVIC Group Priority to 4 - Global MSP (MCU Support Package) initialization */ HAL_Init(); // set the system clock to be HSE SystemClock_Config(); // enable GPIO clocks __GPIOA_CLK_ENABLE(); __GPIOB_CLK_ENABLE(); __GPIOC_CLK_ENABLE(); __GPIOD_CLK_ENABLE(); // enable the CCM RAM __CCMDATARAMEN_CLK_ENABLE(); #if 0 #if defined(NETDUINO_PLUS_2) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; #if MICROPY_HW_HAS_SDCARD // Turn on the power enable for the sdcard (PB1) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET); #endif // Turn on the power for the 5V on the expansion header (PB2) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_WriteBit(GPIOB, GPIO_Pin_2, Bit_SET); } #endif #endif // basic sub-system init pendsv_init(); led_init(); switch_init0(); int first_soft_reset = true; uint reset_mode; soft_reset: // check if user switch held to select the reset mode reset_mode = 1; led_state(1, 0); led_state(2, 1); led_state(3, 0); led_state(4, 0); #if MICROPY_HW_HAS_SWITCH if (switch_get()) { for (uint i = 0; i < 3000; i++) { if (!switch_get()) { break; } HAL_Delay(20); if (i % 30 == 29) { reset_mode = (reset_mode + 1) & 7; led_state(2, reset_mode & 1); led_state(3, reset_mode & 2); led_state(4, reset_mode & 4); } } // flash the selected reset mode for (uint i = 0; i < 6; i++) { led_state(2, 0); led_state(3, 0); led_state(4, 0); HAL_Delay(50); led_state(2, reset_mode & 1); led_state(3, reset_mode & 2); led_state(4, reset_mode & 4); HAL_Delay(50); } HAL_Delay(400); } #endif #if MICROPY_HW_ENABLE_RTC if (first_soft_reset) { rtc_init(); } #endif // more sub-system init #if MICROPY_HW_HAS_SDCARD if (first_soft_reset) { sdcard_init(); } #endif if (first_soft_reset) { storage_init(); } // GC init gc_init(&_heap_start, &_heap_end); // Change #if 0 to #if 1 if you want REPL on USART_6 (or another usart) // as well as on USB VCP #if 0 pyb_usart_global_debug = pyb_Usart(MP_OBJ_NEW_SMALL_INT(PYB_USART_YA), MP_OBJ_NEW_SMALL_INT(115200)); #else pyb_usart_global_debug = NULL; #endif // Micro Python init qstr_init(); mp_init(); mp_obj_t def_path[3]; def_path[0] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_); def_path[1] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_src); def_path[2] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_lib); mp_sys_path = mp_obj_new_list(3, def_path); readline_init(); exti_init(); #if MICROPY_HW_HAS_SWITCH // must come after exti_init switch_init(); #endif #if MICROPY_HW_HAS_LCD // LCD init (just creates class, init hardware by calling LCD()) lcd_init(); #endif pin_map_init(); // local filesystem init { // try to mount the flash FRESULT res = f_mount(&fatfs0, "0:", 1); if (reset_mode == 3 || res == FR_NO_FILESYSTEM) { // no filesystem, or asked to reset it, so create a fresh one // LED on to indicate creation of LFS led_state(PYB_LED_R2, 1); uint32_t start_tick = HAL_GetTick(); res = f_mkfs("0:", 0, 0); if (res == FR_OK) { // success creating fresh LFS } else { __fatal_error("could not create LFS"); } // create src directory res = f_mkdir("0:/src"); // ignore result from mkdir // create empty main.py FIL fp; f_open(&fp, "0:/src/main.py", FA_WRITE | FA_CREATE_ALWAYS); UINT n; f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n); // TODO check we could write n bytes f_close(&fp); // keep LED on for at least 200ms sys_tick_wait_at_least(start_tick, 200); led_state(PYB_LED_R2, 0); } else if (res == FR_OK) { // mount sucessful } else { __fatal_error("could not access LFS"); } } // make sure we have a /boot.py { FILINFO fno; #if _USE_LFN fno.lfname = NULL; fno.lfsize = 0; #endif FRESULT res = f_stat("0:/boot.py", &fno); if (res == FR_OK) { if (fno.fattrib & AM_DIR) { // exists as a directory // TODO handle this case // see http://elm-chan.org/fsw/ff/img/app2.c for a "rm -rf" implementation } else { // exists as a file, good! } } else { // doesn't exist, create fresh file // LED on to indicate creation of boot.py led_state(PYB_LED_R2, 1); uint32_t start_tick = HAL_GetTick(); FIL fp; f_open(&fp, "0:/boot.py", FA_WRITE | FA_CREATE_ALWAYS); UINT n; f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n); // TODO check we could write n bytes f_close(&fp); // keep LED on for at least 200ms sys_tick_wait_at_least(start_tick, 200); led_state(PYB_LED_R2, 0); } } // run /boot.py if (reset_mode == 1) { if (!pyexec_file("0:/boot.py")) { flash_error(4); } } // turn boot-up LEDs off led_state(2, 0); led_state(3, 0); led_state(4, 0); #if defined(USE_DEVICE_MODE) usb_storage_medium_t usb_medium = USB_STORAGE_MEDIUM_FLASH; #endif #if MICROPY_HW_HAS_SDCARD // if an SD card is present then mount it on 1:/ if (reset_mode == 1 && sdcard_is_present()) { FRESULT res = f_mount(&fatfs1, "1:", 1); if (res != FR_OK) { printf("[SD] could not mount SD card\n"); } else { if (first_soft_reset) { // use SD card as medium for the USB MSD #if defined(USE_DEVICE_MODE) usb_medium = USB_STORAGE_MEDIUM_SDCARD; #endif } } } #else // Get rid of compiler warning if no SDCARD is configured. (void)first_soft_reset; #endif #if defined(USE_HOST_MODE) // USB host pyb_usb_host_init(); #elif defined(USE_DEVICE_MODE) // USB device if (reset_mode == 1) { usb_device_mode_t usb_mode = USB_DEVICE_MODE_CDC_MSC; if (pyb_config_usb_mode != MP_OBJ_NULL) { if (strcmp(mp_obj_str_get_str(pyb_config_usb_mode), "CDC+HID") == 0) { usb_mode = USB_DEVICE_MODE_CDC_HID; } } pyb_usb_dev_init(usb_mode, usb_medium); } else { pyb_usb_dev_init(USB_DEVICE_MODE_CDC_MSC, usb_medium); } #endif #if MICROPY_HW_ENABLE_RNG // RNG rng_init(); #endif // I2C i2c_init(); #if MICROPY_HW_HAS_MMA7660 // MMA accel: init and reset accel_init(); #endif #if MICROPY_HW_ENABLE_SERVO // servo servo_init(); #endif #if 0 #if MICROPY_HW_ENABLE_TIMER // timer timer_init(); #endif #endif #if MICROPY_HW_ENABLE_DAC // DAC dac_init(); #endif // run main script if (reset_mode == 1) { vstr_t *vstr = vstr_new(); vstr_add_str(vstr, "0:/"); if (pyb_config_source_dir == MP_OBJ_NULL) { vstr_add_str(vstr, "src"); } else { vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_source_dir)); } vstr_add_char(vstr, '/'); if (pyb_config_main == MP_OBJ_NULL) { vstr_add_str(vstr, "main.py"); } else { vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_main)); } if (!pyexec_file(vstr_str(vstr))) { flash_error(3); } vstr_free(vstr); } #if 0 #if MICROPY_HW_HAS_WLAN // wifi pyb_wlan_init(); pyb_wlan_start(); #endif #endif // enter REPL // REPL mode can change, or it can request a soft reset for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { break; } } else { if (pyexec_friendly_repl() != 0) { break; } } } printf("PYB: sync filesystems\n"); storage_flush(); printf("PYB: soft reboot\n"); first_soft_reset = false; goto soft_reset; }