mirror of
https://github.com/micropython/micropython.git
synced 2025-12-30 08:40:14 +01:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ccedf000ed | ||
|
|
429e3f077e | ||
|
|
8768f8ad4b | ||
|
|
e4e52f5370 | ||
|
|
e503512f83 | ||
|
|
bc1488a05f | ||
|
|
b2f19b8d34 | ||
|
|
480a7ce58f | ||
|
|
de3c806965 | ||
|
|
c76af32575 | ||
|
|
b0b0012fd8 | ||
|
|
91bd4e8a23 | ||
|
|
124df6f8d0 | ||
|
|
d7353fe6fe | ||
|
|
627852019b | ||
|
|
c9fc620723 | ||
|
|
e5a3759ff5 | ||
|
|
8becca7c82 | ||
|
|
8456cc017b | ||
|
|
1084b0f9c2 | ||
|
|
fcff4663dd | ||
|
|
8204db6831 | ||
|
|
21dfd207ca | ||
|
|
a64d5d67b5 | ||
|
|
0b13f3e026 | ||
|
|
564963a170 | ||
|
|
d00d8ac95c | ||
|
|
e294bee45b | ||
|
|
e5b1b7348a | ||
|
|
e2f8d98525 | ||
|
|
185cb0d943 | ||
|
|
e7bb0443cd | ||
|
|
dd4f4530ab | ||
|
|
3aa09f5784 | ||
|
|
37378f8a9d | ||
|
|
f5d69794a8 | ||
|
|
e72be1b999 | ||
|
|
5fc42a6c97 | ||
|
|
842210f53a | ||
|
|
e7a478204a | ||
|
|
efa04eafd3 | ||
|
|
d46a822262 | ||
|
|
3be6984b8f | ||
|
|
8d62bbd46a | ||
|
|
3e42570538 |
@@ -13,6 +13,7 @@
|
||||
#define MICROPY_HELPER_LEXER_UNIX (0)
|
||||
#define MICROPY_ENABLE_SOURCE_LINE (0)
|
||||
#define MICROPY_PY_BUILTINS_BYTEARRAY (0)
|
||||
#define MICROPY_PY_BUILTINS_MEMORYVIEW (0)
|
||||
#define MICROPY_PY_BUILTINS_FROZENSET (0)
|
||||
#define MICROPY_PY_BUILTINS_SET (0)
|
||||
#define MICROPY_PY_BUILTINS_SLICE (0)
|
||||
|
||||
@@ -5,6 +5,11 @@ Micro Python documentation and references
|
||||
|
||||
Here you can find documentation for Micro Python and the pyboard.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
quickref.rst
|
||||
|
||||
Software
|
||||
--------
|
||||
|
||||
|
||||
127
docs/quickref.rst
Normal file
127
docs/quickref.rst
Normal file
@@ -0,0 +1,127 @@
|
||||
Quick reference for the pyboard
|
||||
=====================================
|
||||
|
||||
.. image:: http://micropython.org/static/resources/pybv10-pinout.jpg
|
||||
:alt: AMP skin
|
||||
:width: 700px
|
||||
|
||||
General board control
|
||||
---------------------
|
||||
::
|
||||
|
||||
import pyb
|
||||
|
||||
pyb.delay(50) # wait 50 milliseconds
|
||||
pyb.millis() # number of milliseconds since bootup
|
||||
pyb.repl_uart(pyb.UART(1, 9600)) # duplicate REPL on UART(1)
|
||||
pyb.wfi() # pause CPU, waiting for interrupt
|
||||
pyb.freq() # get CPU and bus frequencies
|
||||
pyb.freq(60000000) # set CPU freq to 60MHz
|
||||
pyb.stop() # stop CPU, waiting for external interrupt
|
||||
|
||||
LEDs
|
||||
----
|
||||
::
|
||||
|
||||
from pyb import LED
|
||||
|
||||
led = LED(1) # red led
|
||||
led.toggle()
|
||||
led.on()
|
||||
led.off()
|
||||
|
||||
Pins and GPIO
|
||||
-------------
|
||||
::
|
||||
|
||||
from pyb import Pin
|
||||
|
||||
p_out = Pin('X1', Pin.OUT_PP)
|
||||
p_out.high()
|
||||
p_out.low()
|
||||
|
||||
p_in = Pin('X2', Pin.IN, Pin.PULL_UP)
|
||||
p_in.value() # get value, 0 or 1
|
||||
|
||||
External interrupts
|
||||
-------------------
|
||||
::
|
||||
|
||||
from pyb import Pin, ExtInt
|
||||
|
||||
callback = lambda e: print("intr")
|
||||
ext = ExtInt(Pin('Y1'), ExtInt.IRQ_RISING, Pin.PULL_NONE, callback)
|
||||
|
||||
Timers
|
||||
------
|
||||
::
|
||||
|
||||
from pyb import Timer
|
||||
|
||||
tim = Timer(1, freq=1000)
|
||||
tim.counter() # get counter value
|
||||
tim.freq(0.5) # 0.5 Hz
|
||||
tim.callback(lambda t: pyb.LED(1).toggle())
|
||||
|
||||
PWM (pulse width modulation)
|
||||
----------------------------
|
||||
::
|
||||
|
||||
from pyb import Pin, Timer
|
||||
|
||||
p = Pin('X1') # X1 has TIM2, CH1
|
||||
tim = Timer(2, freq=1000)
|
||||
ch = tim.channel(1, Timer.PWM, pin=p)
|
||||
ch.pulse_width_percent(50)
|
||||
|
||||
ADC (analog to digital conversion)
|
||||
----------------------------------
|
||||
::
|
||||
|
||||
from pyb import Pin, ADC
|
||||
|
||||
adc = ADC(Pin('X19'))
|
||||
adc.read() # read value, 0-4095
|
||||
|
||||
DAC (digital to analog conversion)
|
||||
----------------------------------
|
||||
::
|
||||
|
||||
from pyb import Pin, DAC
|
||||
|
||||
dac = DAC(Pin('X5'))
|
||||
dac.write(120) # output between 0 and 255
|
||||
|
||||
UART (serial bus)
|
||||
-----------------
|
||||
::
|
||||
|
||||
from pyb import UART
|
||||
|
||||
uart = UART(1, 9600)
|
||||
uart.write('hello')
|
||||
uart.read(5) # read up to 5 bytes
|
||||
|
||||
SPI bus
|
||||
-------
|
||||
::
|
||||
|
||||
from pyb import SPI
|
||||
|
||||
spi = SPI(1, SPI.MASTER, baudrate=200000, polarity=1, phase=0)
|
||||
spi.send('hello')
|
||||
spi.recv(5) # receive 5 bytes on the bus
|
||||
spi.send_recv('hello') # send a receive 5 bytes
|
||||
|
||||
I2C bus
|
||||
-------
|
||||
::
|
||||
|
||||
from pyb import I2C
|
||||
|
||||
i2c = I2C(1, I2C.MASTER, baudrate=100000)
|
||||
i2c.scan() # returns list of slave addresses
|
||||
i2c.send('hello', 0x42) # send 5 bytes to slave with address 0x42
|
||||
i2c.recv(5, 0x42) # receive 5 bytes from slave
|
||||
i2c.mem_read(2, 0x42, 0x10) # read 2 bytes from slave 0x42, slave memory 0x10
|
||||
i2c.mem_write('xy', 0x42, 0x10) # write 2 bytes to slave 0x42, slave memory 0x10
|
||||
@@ -19,7 +19,7 @@ while True:
|
||||
if switch():
|
||||
pyb.delay(200) # delay avoids detection of multiple presses
|
||||
blue.on() # blue LED indicates file open
|
||||
log = open('1:/log.csv', 'w') # open file on SD (SD: '1:/', flash: '0/)
|
||||
log = open('/sd/log.csv', 'w') # open file on SD (SD: '/sd/', flash: '/flash/)
|
||||
|
||||
# until switch is pressed again
|
||||
while not switch():
|
||||
|
||||
138
extmod/moduheapq.c
Normal file
138
extmod/moduheapq.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "nlr.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "objlist.h"
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
|
||||
#if MICROPY_PY_UHEAPQ
|
||||
|
||||
// the algorithm here is modelled on CPython's heapq.py
|
||||
|
||||
STATIC mp_obj_list_t *get_heap(mp_obj_t heap_in) {
|
||||
if (!MP_OBJ_IS_TYPE(heap_in, &mp_type_list)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "heap must be a list"));
|
||||
}
|
||||
return heap_in;
|
||||
}
|
||||
|
||||
STATIC void heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) {
|
||||
mp_obj_t item = heap->items[pos];
|
||||
while (pos > start_pos) {
|
||||
mp_uint_t parent_pos = (pos - 1) >> 1;
|
||||
mp_obj_t parent = heap->items[parent_pos];
|
||||
if (mp_binary_op(MP_BINARY_OP_LESS, item, parent) == mp_const_true) {
|
||||
heap->items[pos] = parent;
|
||||
pos = parent_pos;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
heap->items[pos] = item;
|
||||
}
|
||||
|
||||
STATIC void heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) {
|
||||
mp_uint_t start_pos = pos;
|
||||
mp_uint_t end_pos = heap->len;
|
||||
mp_obj_t item = heap->items[pos];
|
||||
for (mp_uint_t child_pos = 2 * pos + 1; child_pos < end_pos; child_pos = 2 * pos + 1) {
|
||||
// choose right child if it's <= left child
|
||||
if (child_pos + 1 < end_pos && mp_binary_op(MP_BINARY_OP_LESS, heap->items[child_pos], heap->items[child_pos + 1]) == mp_const_false) {
|
||||
child_pos += 1;
|
||||
}
|
||||
// bubble up the smaller child
|
||||
heap->items[pos] = heap->items[child_pos];
|
||||
pos = child_pos;
|
||||
}
|
||||
heap->items[pos] = item;
|
||||
heap_siftdown(heap, start_pos, pos);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mod_uheapq_heappush(mp_obj_t heap_in, mp_obj_t item) {
|
||||
mp_obj_list_t *heap = get_heap(heap_in);
|
||||
mp_obj_list_append(heap, item);
|
||||
heap_siftdown(heap, 0, heap->len - 1);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_uheapq_heappush_obj, mod_uheapq_heappush);
|
||||
|
||||
STATIC mp_obj_t mod_uheapq_heappop(mp_obj_t heap_in) {
|
||||
mp_obj_list_t *heap = get_heap(heap_in);
|
||||
if (heap->len == 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap"));
|
||||
}
|
||||
mp_obj_t item = heap->items[0];
|
||||
heap->len -= 1;
|
||||
heap->items[0] = heap->items[heap->len];
|
||||
heap->items[heap->len] = MP_OBJ_NULL; // so we don't retain a pointer
|
||||
if (heap->len) {
|
||||
heap_siftup(heap, 0);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heappop_obj, mod_uheapq_heappop);
|
||||
|
||||
STATIC mp_obj_t mod_uheapq_heapify(mp_obj_t heap_in) {
|
||||
mp_obj_list_t *heap = get_heap(heap_in);
|
||||
for (mp_uint_t i = heap->len / 2; i > 0;) {
|
||||
heap_siftup(heap, --i);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heapify_obj, mod_uheapq_heapify);
|
||||
|
||||
STATIC const mp_map_elem_t mp_module_uheapq_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uheapq) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_heappush), (mp_obj_t)&mod_uheapq_heappush_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_heappop), (mp_obj_t)&mod_uheapq_heappop_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_heapify), (mp_obj_t)&mod_uheapq_heapify_obj },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_uheapq_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_uheapq_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_uheapq_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_uheapq_globals_table,
|
||||
},
|
||||
};
|
||||
|
||||
const mp_obj_module_t mp_module_uheapq = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_uheapq,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_uheapq_globals,
|
||||
};
|
||||
|
||||
#endif //MICROPY_PY_UHEAPQ
|
||||
20
py/bc.c
20
py/bc.c
@@ -93,7 +93,6 @@ void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t
|
||||
// usage for the common case of positional only args.
|
||||
mp_obj_fun_bc_t *self = self_in;
|
||||
mp_uint_t n_state = code_state->n_state;
|
||||
const byte *ip = code_state->ip;
|
||||
|
||||
code_state->code_info = self->bytecode;
|
||||
code_state->sp = &code_state->state[0] - 1;
|
||||
@@ -153,13 +152,21 @@ void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t
|
||||
*var_pos_kw_args = dict;
|
||||
}
|
||||
|
||||
// get pointer to arg_names array at start of bytecode prelude
|
||||
const mp_obj_t *arg_names;
|
||||
{
|
||||
const byte *code_info = code_state->code_info;
|
||||
mp_uint_t code_info_size = mp_decode_uint(&code_info);
|
||||
arg_names = (const mp_obj_t*)(code_state->code_info + code_info_size);
|
||||
}
|
||||
|
||||
for (mp_uint_t i = 0; i < n_kw; i++) {
|
||||
qstr arg_name = MP_OBJ_QSTR_VALUE(kwargs[2 * i]);
|
||||
mp_obj_t wanted_arg_name = kwargs[2 * i];
|
||||
for (mp_uint_t j = 0; j < self->n_pos_args + self->n_kwonly_args; j++) {
|
||||
if (arg_name == self->args[j]) {
|
||||
if (wanted_arg_name == arg_names[j]) {
|
||||
if (code_state->state[n_state - 1 - j] != MP_OBJ_NULL) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"function got multiple values for argument '%s'", qstr_str(arg_name)));
|
||||
"function got multiple values for argument '%s'", qstr_str(MP_OBJ_QSTR_VALUE(wanted_arg_name))));
|
||||
}
|
||||
code_state->state[n_state - 1 - j] = kwargs[2 * i + 1];
|
||||
goto continue2;
|
||||
@@ -202,13 +209,13 @@ continue2:;
|
||||
if (code_state->state[n_state - 1 - self->n_pos_args - i] == MP_OBJ_NULL) {
|
||||
mp_map_elem_t *elem = NULL;
|
||||
if (self->has_def_kw_args) {
|
||||
elem = mp_map_lookup(&((mp_obj_dict_t*)self->extra_args[self->n_def_args])->map, MP_OBJ_NEW_QSTR(self->args[self->n_pos_args + i]), MP_MAP_LOOKUP);
|
||||
elem = mp_map_lookup(&((mp_obj_dict_t*)self->extra_args[self->n_def_args])->map, arg_names[self->n_pos_args + i], MP_MAP_LOOKUP);
|
||||
}
|
||||
if (elem != NULL) {
|
||||
code_state->state[n_state - 1 - self->n_pos_args - i] = elem->value;
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"function missing required keyword argument '%s'", qstr_str(self->args[self->n_pos_args + i])));
|
||||
"function missing required keyword argument '%s'", qstr_str(MP_OBJ_QSTR_VALUE(arg_names[self->n_pos_args + i]))));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,6 +232,7 @@ continue2:;
|
||||
}
|
||||
|
||||
// bytecode prelude: initialise closed over variables
|
||||
const byte *ip = code_state->ip;
|
||||
for (mp_uint_t n_local = *ip++; n_local > 0; n_local--) {
|
||||
mp_uint_t local_num = *ip++;
|
||||
code_state->state[n_state - 1 - local_num] = mp_obj_new_cell(code_state->state[n_state - 1 - local_num]);
|
||||
|
||||
2
py/bc.h
2
py/bc.h
@@ -53,7 +53,7 @@ mp_uint_t mp_decode_uint(const byte **ptr);
|
||||
|
||||
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc);
|
||||
void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
|
||||
void mp_bytecode_print(const void *descr, const byte *code, mp_uint_t len);
|
||||
void mp_bytecode_print(const void *descr, mp_uint_t n_total_args, const byte *code, mp_uint_t len);
|
||||
void mp_bytecode_print2(const byte *code, mp_uint_t len);
|
||||
|
||||
// Helper macros to access pointer with least significant bit holding a flag
|
||||
|
||||
152
py/bc0.h
152
py/bc0.h
@@ -31,92 +31,90 @@
|
||||
#define MP_BC_LOAD_CONST_NONE (0x11)
|
||||
#define MP_BC_LOAD_CONST_TRUE (0x12)
|
||||
#define MP_BC_LOAD_CONST_ELLIPSIS (0x13)
|
||||
#define MP_BC_LOAD_CONST_SMALL_INT (0x14) // 24-bit, in excess
|
||||
#define MP_BC_LOAD_CONST_SMALL_INT (0x14) // signed var-int
|
||||
#define MP_BC_LOAD_CONST_INT (0x15) // qstr
|
||||
#define MP_BC_LOAD_CONST_DEC (0x16) // qstr
|
||||
#define MP_BC_LOAD_CONST_BYTES (0x18) // qstr
|
||||
#define MP_BC_LOAD_CONST_STRING (0x19) // qstr
|
||||
#define MP_BC_LOAD_NULL (0x1a)
|
||||
#define MP_BC_LOAD_CONST_BYTES (0x17) // qstr
|
||||
#define MP_BC_LOAD_CONST_STRING (0x18) // qstr
|
||||
#define MP_BC_LOAD_NULL (0x19)
|
||||
|
||||
#define MP_BC_LOAD_FAST_0 (0x20)
|
||||
#define MP_BC_LOAD_FAST_1 (0x21)
|
||||
#define MP_BC_LOAD_FAST_2 (0x22)
|
||||
#define MP_BC_LOAD_FAST_N (0x23) // uint
|
||||
#define MP_BC_LOAD_DEREF (0x25) // uint
|
||||
#define MP_BC_LOAD_NAME (0x26) // qstr
|
||||
#define MP_BC_LOAD_GLOBAL (0x27) // qstr
|
||||
#define MP_BC_LOAD_ATTR (0x28) // qstr
|
||||
#define MP_BC_LOAD_METHOD (0x29) // qstr
|
||||
#define MP_BC_LOAD_BUILD_CLASS (0x2a)
|
||||
#define MP_BC_LOAD_SUBSCR (0x2b)
|
||||
#define MP_BC_LOAD_FAST_N (0x1a) // uint
|
||||
#define MP_BC_LOAD_DEREF (0x1b) // uint
|
||||
#define MP_BC_LOAD_NAME (0x1c) // qstr
|
||||
#define MP_BC_LOAD_GLOBAL (0x1d) // qstr
|
||||
#define MP_BC_LOAD_ATTR (0x1e) // qstr
|
||||
#define MP_BC_LOAD_METHOD (0x1f) // qstr
|
||||
#define MP_BC_LOAD_BUILD_CLASS (0x20)
|
||||
#define MP_BC_LOAD_SUBSCR (0x21)
|
||||
|
||||
#define MP_BC_STORE_FAST_0 (0x30)
|
||||
#define MP_BC_STORE_FAST_1 (0x31)
|
||||
#define MP_BC_STORE_FAST_2 (0x32)
|
||||
#define MP_BC_STORE_FAST_N (0x33) // uint
|
||||
#define MP_BC_STORE_DEREF (0x34) // uint
|
||||
#define MP_BC_STORE_NAME (0x35) // qstr
|
||||
#define MP_BC_STORE_GLOBAL (0x36) // qstr
|
||||
#define MP_BC_STORE_ATTR (0x37) // qstr
|
||||
#define MP_BC_STORE_SUBSCR (0x38)
|
||||
#define MP_BC_STORE_FAST_N (0x22) // uint
|
||||
#define MP_BC_STORE_DEREF (0x23) // uint
|
||||
#define MP_BC_STORE_NAME (0x24) // qstr
|
||||
#define MP_BC_STORE_GLOBAL (0x25) // qstr
|
||||
#define MP_BC_STORE_ATTR (0x26) // qstr
|
||||
#define MP_BC_STORE_SUBSCR (0x27)
|
||||
|
||||
#define MP_BC_DELETE_FAST (0x39) // uint
|
||||
#define MP_BC_DELETE_DEREF (0x3a) // uint
|
||||
#define MP_BC_DELETE_NAME (0x3b) // qstr
|
||||
#define MP_BC_DELETE_GLOBAL (0x3c) // qstr
|
||||
#define MP_BC_DELETE_FAST (0x28) // uint
|
||||
#define MP_BC_DELETE_DEREF (0x29) // uint
|
||||
#define MP_BC_DELETE_NAME (0x2a) // qstr
|
||||
#define MP_BC_DELETE_GLOBAL (0x2b) // qstr
|
||||
|
||||
#define MP_BC_DUP_TOP (0x40)
|
||||
#define MP_BC_DUP_TOP_TWO (0x41)
|
||||
#define MP_BC_POP_TOP (0x42)
|
||||
#define MP_BC_ROT_TWO (0x43)
|
||||
#define MP_BC_ROT_THREE (0x44)
|
||||
#define MP_BC_DUP_TOP (0x30)
|
||||
#define MP_BC_DUP_TOP_TWO (0x31)
|
||||
#define MP_BC_POP_TOP (0x32)
|
||||
#define MP_BC_ROT_TWO (0x33)
|
||||
#define MP_BC_ROT_THREE (0x34)
|
||||
|
||||
#define MP_BC_JUMP (0x45) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_POP_JUMP_IF_TRUE (0x46) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_POP_JUMP_IF_FALSE (0x47) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_JUMP_IF_TRUE_OR_POP (0x48) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_JUMP_IF_FALSE_OR_POP (0x49) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_SETUP_WITH (0x4d) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_WITH_CLEANUP (0x4e)
|
||||
#define MP_BC_SETUP_EXCEPT (0x4f) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_SETUP_FINALLY (0x50) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_END_FINALLY (0x51)
|
||||
#define MP_BC_GET_ITER (0x52)
|
||||
#define MP_BC_FOR_ITER (0x53) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_POP_BLOCK (0x54)
|
||||
#define MP_BC_POP_EXCEPT (0x55)
|
||||
#define MP_BC_UNWIND_JUMP (0x56) // rel byte code offset, 16-bit signed, in excess; then a byte
|
||||
#define MP_BC_JUMP (0x35) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_POP_JUMP_IF_TRUE (0x36) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_POP_JUMP_IF_FALSE (0x37) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_JUMP_IF_TRUE_OR_POP (0x38) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_JUMP_IF_FALSE_OR_POP (0x39) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_SETUP_WITH (0x3d) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_WITH_CLEANUP (0x3e)
|
||||
#define MP_BC_SETUP_EXCEPT (0x3f) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_SETUP_FINALLY (0x40) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_END_FINALLY (0x41)
|
||||
#define MP_BC_GET_ITER (0x42)
|
||||
#define MP_BC_FOR_ITER (0x43) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_POP_BLOCK (0x44)
|
||||
#define MP_BC_POP_EXCEPT (0x45)
|
||||
#define MP_BC_UNWIND_JUMP (0x46) // rel byte code offset, 16-bit signed, in excess; then a byte
|
||||
|
||||
#define MP_BC_NOT (0x60)
|
||||
#define MP_BC_UNARY_OP (0x61) // byte
|
||||
#define MP_BC_BINARY_OP (0x62) // byte
|
||||
#define MP_BC_NOT (0x47)
|
||||
|
||||
#define MP_BC_BUILD_TUPLE (0x70) // uint
|
||||
#define MP_BC_BUILD_LIST (0x71) // uint
|
||||
#define MP_BC_LIST_APPEND (0x72) // uint
|
||||
#define MP_BC_BUILD_MAP (0x73) // uint
|
||||
#define MP_BC_STORE_MAP (0x74)
|
||||
#define MP_BC_MAP_ADD (0x75) // uint
|
||||
#define MP_BC_BUILD_SET (0x76) // uint
|
||||
#define MP_BC_SET_ADD (0x77) // uint
|
||||
#define MP_BC_BUILD_SLICE (0x78) // uint
|
||||
#define MP_BC_UNPACK_SEQUENCE (0x79) // uint
|
||||
#define MP_BC_UNPACK_EX (0x7a) // uint
|
||||
#define MP_BC_BUILD_TUPLE (0x50) // uint
|
||||
#define MP_BC_BUILD_LIST (0x51) // uint
|
||||
#define MP_BC_LIST_APPEND (0x52) // uint
|
||||
#define MP_BC_BUILD_MAP (0x53) // uint
|
||||
#define MP_BC_STORE_MAP (0x54)
|
||||
#define MP_BC_MAP_ADD (0x55) // uint
|
||||
#define MP_BC_BUILD_SET (0x56) // uint
|
||||
#define MP_BC_SET_ADD (0x57) // uint
|
||||
#define MP_BC_BUILD_SLICE (0x58) // uint
|
||||
#define MP_BC_UNPACK_SEQUENCE (0x59) // uint
|
||||
#define MP_BC_UNPACK_EX (0x5a) // uint
|
||||
|
||||
#define MP_BC_RETURN_VALUE (0x80)
|
||||
#define MP_BC_RAISE_VARARGS (0x81) // byte
|
||||
#define MP_BC_YIELD_VALUE (0x82)
|
||||
#define MP_BC_YIELD_FROM (0x83)
|
||||
#define MP_BC_RETURN_VALUE (0x5b)
|
||||
#define MP_BC_RAISE_VARARGS (0x5c) // byte
|
||||
#define MP_BC_YIELD_VALUE (0x5d)
|
||||
#define MP_BC_YIELD_FROM (0x5e)
|
||||
|
||||
#define MP_BC_MAKE_FUNCTION (0x90) // uint
|
||||
#define MP_BC_MAKE_FUNCTION_DEFARGS (0x91) // uint
|
||||
#define MP_BC_MAKE_CLOSURE (0x92) // uint
|
||||
#define MP_BC_MAKE_CLOSURE_DEFARGS (0x93) // uint
|
||||
#define MP_BC_CALL_FUNCTION (0x94) // uint
|
||||
#define MP_BC_CALL_FUNCTION_VAR_KW (0x95) // uint
|
||||
#define MP_BC_CALL_METHOD (0x96) // uint
|
||||
#define MP_BC_CALL_METHOD_VAR_KW (0x97) // uint
|
||||
#define MP_BC_MAKE_FUNCTION (0x60) // uint
|
||||
#define MP_BC_MAKE_FUNCTION_DEFARGS (0x61) // uint
|
||||
#define MP_BC_MAKE_CLOSURE (0x62) // uint
|
||||
#define MP_BC_MAKE_CLOSURE_DEFARGS (0x63) // uint
|
||||
#define MP_BC_CALL_FUNCTION (0x64) // uint
|
||||
#define MP_BC_CALL_FUNCTION_VAR_KW (0x65) // uint
|
||||
#define MP_BC_CALL_METHOD (0x66) // uint
|
||||
#define MP_BC_CALL_METHOD_VAR_KW (0x67) // uint
|
||||
|
||||
#define MP_BC_IMPORT_NAME (0xe0) // qstr
|
||||
#define MP_BC_IMPORT_FROM (0xe1) // qstr
|
||||
#define MP_BC_IMPORT_STAR (0xe2)
|
||||
#define MP_BC_IMPORT_NAME (0x68) // qstr
|
||||
#define MP_BC_IMPORT_FROM (0x69) // qstr
|
||||
#define MP_BC_IMPORT_STAR (0x6a)
|
||||
|
||||
#define MP_BC_LOAD_CONST_SMALL_INT_MULTI (0x70) // + N(64)
|
||||
#define MP_BC_LOAD_FAST_MULTI (0xb0) // + N(16)
|
||||
#define MP_BC_STORE_FAST_MULTI (0xc0) // + N(16)
|
||||
#define MP_BC_UNARY_OP_MULTI (0xd0) // + op(5)
|
||||
#define MP_BC_BINARY_OP_MULTI (0xd5) // + op(35)
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "objstr.h"
|
||||
#include "smallint.h"
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
#include "builtin.h"
|
||||
@@ -253,8 +254,8 @@ STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero"));
|
||||
}
|
||||
mp_obj_t args[2];
|
||||
args[0] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
|
||||
args[1] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
|
||||
args[0] = MP_OBJ_NEW_SMALL_INT(mp_small_int_floor_divide(i1, i2));
|
||||
args[1] = MP_OBJ_NEW_SMALL_INT(mp_small_int_modulo(i1, i2));
|
||||
return mp_obj_new_tuple(2, args);
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
} else if (MP_OBJ_IS_TYPE(o1_in, &mp_type_float) || MP_OBJ_IS_TYPE(o2_in, &mp_type_float)) {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
mp_obj_t mp_builtin___import__(mp_uint_t n_args, mp_obj_t *args);
|
||||
mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args);
|
||||
mp_obj_t mp_builtin_open(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin___build_class___obj);
|
||||
@@ -35,6 +35,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_all_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_any_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_bin_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_callable_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_compile_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_chr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_dir_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_divmod_obj);
|
||||
@@ -91,3 +92,4 @@ extern const mp_obj_module_t mp_module_uctypes;
|
||||
extern const mp_obj_module_t mp_module_uzlib;
|
||||
extern const mp_obj_module_t mp_module_ujson;
|
||||
extern const mp_obj_module_t mp_module_ure;
|
||||
extern const mp_obj_module_t mp_module_uheapq;
|
||||
|
||||
@@ -34,19 +34,87 @@
|
||||
#include "lexerunix.h"
|
||||
#include "parse.h"
|
||||
#include "obj.h"
|
||||
#include "objfun.h"
|
||||
#include "parsehelper.h"
|
||||
#include "compile.h"
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
#include "builtin.h"
|
||||
|
||||
STATIC mp_obj_t eval_exec_helper(mp_uint_t n_args, const mp_obj_t *args, mp_parse_input_kind_t parse_input_kind) {
|
||||
#if MICROPY_PY_BUILTINS_COMPILE
|
||||
|
||||
typedef struct _mp_obj_code_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t module_fun;
|
||||
} mp_obj_code_t;
|
||||
|
||||
STATIC const mp_obj_type_t mp_type_code = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_code,
|
||||
};
|
||||
|
||||
STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_t globals, mp_obj_t locals) {
|
||||
// save context and set new context
|
||||
mp_obj_dict_t *old_globals = mp_globals_get();
|
||||
mp_obj_dict_t *old_locals = mp_locals_get();
|
||||
mp_globals_set(globals);
|
||||
mp_locals_set(locals);
|
||||
|
||||
// a bit of a hack: fun_bc will re-set globals, so need to make sure it's
|
||||
// the correct one
|
||||
if (MP_OBJ_IS_TYPE(self->module_fun, &mp_type_fun_bc)) {
|
||||
mp_obj_fun_bc_t *fun_bc = self->module_fun;
|
||||
fun_bc->globals = globals;
|
||||
}
|
||||
|
||||
// execute code
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
mp_obj_t ret = mp_call_function_0(self->module_fun);
|
||||
nlr_pop();
|
||||
mp_globals_set(old_globals);
|
||||
mp_locals_set(old_locals);
|
||||
return ret;
|
||||
} else {
|
||||
// exception; restore context and re-raise same exception
|
||||
mp_globals_set(old_globals);
|
||||
mp_locals_set(old_locals);
|
||||
nlr_raise(nlr.ret_val);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mp_builtin_compile(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
// get the source
|
||||
mp_uint_t str_len;
|
||||
const char *str = mp_obj_str_get_data(args[0], &str_len);
|
||||
|
||||
// create the lexer
|
||||
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, str, str_len, 0);
|
||||
// get the filename
|
||||
qstr filename = mp_obj_str_get_qstr(args[1]);
|
||||
|
||||
// create the lexer
|
||||
mp_lexer_t *lex = mp_lexer_new_from_str_len(filename, str, str_len, 0);
|
||||
|
||||
// get the compile mode
|
||||
qstr mode = mp_obj_str_get_qstr(args[2]);
|
||||
mp_parse_input_kind_t parse_input_kind;
|
||||
switch (mode) {
|
||||
case MP_QSTR_single: parse_input_kind = MP_PARSE_SINGLE_INPUT; break;
|
||||
case MP_QSTR_exec: parse_input_kind = MP_PARSE_FILE_INPUT; break;
|
||||
case MP_QSTR_eval: parse_input_kind = MP_PARSE_EVAL_INPUT; break;
|
||||
default:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad compile mode"));
|
||||
}
|
||||
|
||||
mp_obj_code_t *code = m_new_obj(mp_obj_code_t);
|
||||
code->base.type = &mp_type_code;
|
||||
code->module_fun = mp_parse_compile_execute(lex, parse_input_kind, NULL, NULL);
|
||||
return code;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_compile_obj, 3, 6, mp_builtin_compile);
|
||||
|
||||
#endif // MICROPY_PY_BUILTINS_COMPILE
|
||||
|
||||
STATIC mp_obj_t eval_exec_helper(mp_uint_t n_args, const mp_obj_t *args, mp_parse_input_kind_t parse_input_kind) {
|
||||
// work out the context
|
||||
mp_obj_dict_t *globals = mp_globals_get();
|
||||
mp_obj_dict_t *locals = mp_locals_get();
|
||||
@@ -59,6 +127,18 @@ STATIC mp_obj_t eval_exec_helper(mp_uint_t n_args, const mp_obj_t *args, mp_pars
|
||||
}
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_COMPILE
|
||||
if (MP_OBJ_IS_TYPE(args[0], &mp_type_code)) {
|
||||
return code_execute(args[0], globals, locals);
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_uint_t str_len;
|
||||
const char *str = mp_obj_str_get_data(args[0], &str_len);
|
||||
|
||||
// create the lexer
|
||||
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, str, str_len, 0);
|
||||
|
||||
return mp_parse_compile_execute(lex, parse_input_kind, globals, locals);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,12 @@
|
||||
|
||||
#define PATH_SEP_CHAR '/'
|
||||
|
||||
bool mp_obj_is_package(mp_obj_t module) {
|
||||
mp_obj_t dest[2];
|
||||
mp_load_method_maybe(module, MP_QSTR___path__, dest);
|
||||
return dest[0] != MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) {
|
||||
//printf("stat %s\n", vstr_str(path));
|
||||
mp_import_stat_t stat = mp_import_stat(vstr_str(path));
|
||||
@@ -122,7 +128,7 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
|
||||
mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mod_globals, mod_globals);
|
||||
}
|
||||
|
||||
mp_obj_t mp_builtin___import__(mp_uint_t n_args, mp_obj_t *args) {
|
||||
mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
#if DEBUG_PRINT
|
||||
DEBUG_printf("__import__:\n");
|
||||
for (mp_uint_t i = 0; i < n_args; i++) {
|
||||
@@ -280,6 +286,14 @@ mp_obj_t mp_builtin___import__(mp_uint_t n_args, mp_obj_t *args) {
|
||||
|
||||
module_obj = mp_obj_new_module(mod_name);
|
||||
|
||||
// if args[3] (fromtuple) has magic value False, set up
|
||||
// this module for command-line "-m" option (set module's
|
||||
// name to __main__ instead of real name).
|
||||
if (i == mod_len && fromtuple == mp_const_false) {
|
||||
mp_obj_module_t *o = module_obj;
|
||||
mp_obj_dict_store(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
|
||||
}
|
||||
|
||||
if (stat == MP_IMPORT_STAT_DIR) {
|
||||
DEBUG_printf("%s is dir\n", vstr_str(&path));
|
||||
// https://docs.python.org/3/reference/import.html
|
||||
|
||||
@@ -61,6 +61,9 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_int), (mp_obj_t)&mp_type_int },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_list), (mp_obj_t)&mp_type_list },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_map), (mp_obj_t)&mp_type_map },
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_memoryview), (mp_obj_t)&mp_type_memoryview },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_object), (mp_obj_t)&mp_type_object },
|
||||
#if MICROPY_PY_BUILTINS_PROPERTY
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_property), (mp_obj_t)&mp_type_property },
|
||||
@@ -88,6 +91,9 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&mp_builtin_any_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bin), (mp_obj_t)&mp_builtin_bin_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_callable), (mp_obj_t)&mp_builtin_callable_obj },
|
||||
#if MICROPY_PY_BUILTINS_COMPILE
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_compile), (mp_obj_t)&mp_builtin_compile_obj },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_chr), (mp_obj_t)&mp_builtin_chr_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_dir), (mp_obj_t)&mp_builtin_dir_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_divmod), (mp_obj_t)&mp_builtin_divmod_obj },
|
||||
@@ -136,7 +142,6 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_RuntimeError), (mp_obj_t)&mp_type_RuntimeError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_StopIteration), (mp_obj_t)&mp_type_StopIteration },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SyntaxError), (mp_obj_t)&mp_type_SyntaxError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SystemError), (mp_obj_t)&mp_type_SystemError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SystemExit), (mp_obj_t)&mp_type_SystemExit },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_TypeError), (mp_obj_t)&mp_type_TypeError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ValueError), (mp_obj_t)&mp_type_ValueError },
|
||||
@@ -212,6 +217,9 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = {
|
||||
#if MICROPY_PY_URE
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ure), (mp_obj_t)&mp_module_ure },
|
||||
#endif
|
||||
#if MICROPY_PY_UHEAPQ
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_uheapq), (mp_obj_t)&mp_module_uheapq },
|
||||
#endif
|
||||
|
||||
// extra builtin modules as defined by a port
|
||||
MICROPY_PORT_BUILTIN_MODULES
|
||||
|
||||
54
py/emitbc.c
54
py/emitbc.c
@@ -218,6 +218,13 @@ STATIC void emit_write_bytecode_byte_uint(emit_t* emit, byte b, mp_uint_t val) {
|
||||
emit_write_uint(emit, emit_get_cur_to_write_bytecode, val);
|
||||
}
|
||||
|
||||
STATIC void emit_write_bytecode_prealigned_ptr(emit_t* emit, void *ptr) {
|
||||
mp_uint_t *c = (mp_uint_t*)emit_get_cur_to_write_bytecode(emit, sizeof(mp_uint_t));
|
||||
// Verify thar c is already uint-aligned
|
||||
assert(c == MP_ALIGN(c, sizeof(mp_uint_t)));
|
||||
*c = (mp_uint_t)ptr;
|
||||
}
|
||||
|
||||
// aligns the pointer so it is friendly to GC
|
||||
STATIC void emit_write_bytecode_byte_ptr(emit_t* emit, byte b, void *ptr) {
|
||||
emit_write_bytecode_byte(emit, b);
|
||||
@@ -294,7 +301,16 @@ STATIC void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
|
||||
emit_write_code_info_qstr(emit, scope->simple_name);
|
||||
emit_write_code_info_qstr(emit, scope->source_file);
|
||||
|
||||
// bytecode prelude: local state size and exception stack size; 16 bit uints for now
|
||||
// bytecode prelude: argument names (needed to resolve positional args passed as keywords)
|
||||
// we store them as full word-sized objects for efficient access in mp_setup_code_state
|
||||
// this is the start of the prelude and is guaranteed to be aligned on a word boundary
|
||||
{
|
||||
for (int i = 0; i < scope->num_pos_args + scope->num_kwonly_args; i++) {
|
||||
emit_write_bytecode_prealigned_ptr(emit, MP_OBJ_NEW_QSTR(scope->id_info[i].qst));
|
||||
}
|
||||
}
|
||||
|
||||
// bytecode prelude: local state size and exception stack size
|
||||
{
|
||||
mp_uint_t n_state = scope->num_locals + scope->stack_size;
|
||||
if (n_state == 0) {
|
||||
@@ -358,13 +374,9 @@ STATIC void emit_bc_end_pass(emit_t *emit) {
|
||||
emit->code_base = m_new0(byte, emit->code_info_size + emit->bytecode_size);
|
||||
|
||||
} else if (emit->pass == MP_PASS_EMIT) {
|
||||
qstr *arg_names = m_new(qstr, emit->scope->num_pos_args + emit->scope->num_kwonly_args);
|
||||
for (int i = 0; i < emit->scope->num_pos_args + emit->scope->num_kwonly_args; i++) {
|
||||
arg_names[i] = emit->scope->id_info[i].qst;
|
||||
}
|
||||
mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base,
|
||||
emit->code_info_size + emit->bytecode_size,
|
||||
emit->scope->num_pos_args, emit->scope->num_kwonly_args, arg_names,
|
||||
emit->scope->num_pos_args, emit->scope->num_kwonly_args,
|
||||
emit->scope->scope_flags);
|
||||
}
|
||||
}
|
||||
@@ -457,7 +469,11 @@ STATIC void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
|
||||
|
||||
STATIC void emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg) {
|
||||
emit_bc_pre(emit, 1);
|
||||
emit_write_bytecode_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
|
||||
if (-16 <= arg && arg <= 47) {
|
||||
emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_SMALL_INT_MULTI + 16 + arg);
|
||||
} else {
|
||||
emit_write_bytecode_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void emit_bc_load_const_int(emit_t *emit, qstr qst) {
|
||||
@@ -487,11 +503,10 @@ STATIC void emit_bc_load_null(emit_t *emit) {
|
||||
STATIC void emit_bc_load_fast(emit_t *emit, qstr qst, mp_uint_t id_flags, mp_uint_t local_num) {
|
||||
assert(local_num >= 0);
|
||||
emit_bc_pre(emit, 1);
|
||||
switch (local_num) {
|
||||
case 0: emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_0); break;
|
||||
case 1: emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_1); break;
|
||||
case 2: emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_2); break;
|
||||
default: emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_FAST_N, local_num); break;
|
||||
if (local_num <= 15) {
|
||||
emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_MULTI + local_num);
|
||||
} else {
|
||||
emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_FAST_N, local_num);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,11 +548,10 @@ STATIC void emit_bc_load_subscr(emit_t *emit) {
|
||||
STATIC void emit_bc_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
|
||||
assert(local_num >= 0);
|
||||
emit_bc_pre(emit, -1);
|
||||
switch (local_num) {
|
||||
case 0: emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_0); break;
|
||||
case 1: emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_1); break;
|
||||
case 2: emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_2); break;
|
||||
default: emit_write_bytecode_byte_uint(emit, MP_BC_STORE_FAST_N, local_num); break;
|
||||
if (local_num <= 15) {
|
||||
emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_MULTI + local_num);
|
||||
} else {
|
||||
emit_write_bytecode_byte_uint(emit, MP_BC_STORE_FAST_N, local_num);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -712,12 +726,12 @@ STATIC void emit_bc_pop_except(emit_t *emit) {
|
||||
STATIC void emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) {
|
||||
if (op == MP_UNARY_OP_NOT) {
|
||||
emit_bc_pre(emit, 0);
|
||||
emit_write_bytecode_byte_byte(emit, MP_BC_UNARY_OP, MP_UNARY_OP_BOOL);
|
||||
emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_BOOL);
|
||||
emit_bc_pre(emit, 0);
|
||||
emit_write_bytecode_byte(emit, MP_BC_NOT);
|
||||
} else {
|
||||
emit_bc_pre(emit, 0);
|
||||
emit_write_bytecode_byte_byte(emit, MP_BC_UNARY_OP, op);
|
||||
emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + op);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -731,7 +745,7 @@ STATIC void emit_bc_binary_op(emit_t *emit, mp_binary_op_t op) {
|
||||
op = MP_BINARY_OP_IS;
|
||||
}
|
||||
emit_bc_pre(emit, -1);
|
||||
emit_write_bytecode_byte_byte(emit, MP_BC_BINARY_OP, op);
|
||||
emit_write_bytecode_byte(emit, MP_BC_BINARY_OP_MULTI + op);
|
||||
if (invert) {
|
||||
emit_bc_pre(emit, 0);
|
||||
emit_write_bytecode_byte(emit, MP_BC_NOT);
|
||||
|
||||
@@ -55,33 +55,20 @@ mp_raw_code_t *mp_emit_glue_new_raw_code(void) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, byte *code, mp_uint_t len, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, qstr *arg_names, mp_uint_t scope_flags) {
|
||||
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, byte *code, mp_uint_t len, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_uint_t scope_flags) {
|
||||
rc->kind = MP_CODE_BYTECODE;
|
||||
rc->scope_flags = scope_flags;
|
||||
rc->n_pos_args = n_pos_args;
|
||||
rc->n_kwonly_args = n_kwonly_args;
|
||||
rc->arg_names = arg_names;
|
||||
rc->u_byte.code = code;
|
||||
rc->u_byte.len = len;
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
DEBUG_printf("assign byte code: code=%p len=" UINT_FMT " n_pos_args=" UINT_FMT " n_kwonly_args=" UINT_FMT " flags=%x\n", code, len, n_pos_args, n_kwonly_args, (uint)scope_flags);
|
||||
DEBUG_printf(" arg names:");
|
||||
for (int i = 0; i < n_pos_args + n_kwonly_args; i++) {
|
||||
DEBUG_printf(" %s", qstr_str(arg_names[i]));
|
||||
}
|
||||
DEBUG_printf("\n");
|
||||
#endif
|
||||
#if MICROPY_DEBUG_PRINTERS
|
||||
if (mp_verbose_flag > 0) {
|
||||
for (mp_uint_t i = 0; i < len; i++) {
|
||||
if (i > 0 && i % 16 == 0) {
|
||||
printf("\n");
|
||||
}
|
||||
printf(" %02x", code[i]);
|
||||
}
|
||||
printf("\n");
|
||||
mp_bytecode_print(rc, code, len);
|
||||
if (mp_verbose_flag >= 2) {
|
||||
mp_bytecode_print(rc, n_pos_args + n_kwonly_args, code, len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -128,7 +115,7 @@ mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp
|
||||
mp_obj_t fun;
|
||||
switch (rc->kind) {
|
||||
case MP_CODE_BYTECODE:
|
||||
fun = mp_obj_new_fun_bc(rc->scope_flags, rc->arg_names, rc->n_pos_args, rc->n_kwonly_args, def_args, def_kw_args, rc->u_byte.code);
|
||||
fun = mp_obj_new_fun_bc(rc->scope_flags, rc->n_pos_args, rc->n_kwonly_args, def_args, def_kw_args, rc->u_byte.code);
|
||||
break;
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
case MP_CODE_NATIVE_PY:
|
||||
|
||||
@@ -35,12 +35,11 @@ typedef enum {
|
||||
MP_CODE_NATIVE_ASM,
|
||||
} mp_raw_code_kind_t;
|
||||
|
||||
typedef struct _mp_code_t {
|
||||
typedef struct _mp_raw_code_t {
|
||||
mp_raw_code_kind_t kind : 3;
|
||||
mp_uint_t scope_flags : 7;
|
||||
mp_uint_t n_pos_args : 11;
|
||||
mp_uint_t n_kwonly_args : 11;
|
||||
qstr *arg_names;
|
||||
union {
|
||||
struct {
|
||||
byte *code;
|
||||
@@ -55,7 +54,7 @@ typedef struct _mp_code_t {
|
||||
|
||||
mp_raw_code_t *mp_emit_glue_new_raw_code(void);
|
||||
|
||||
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, byte *code, mp_uint_t len, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, qstr *arg_names, mp_uint_t scope_flags);
|
||||
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, byte *code, mp_uint_t len, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_uint_t scope_flags);
|
||||
void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, mp_uint_t n_args, mp_uint_t type_sig);
|
||||
|
||||
mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args);
|
||||
|
||||
45
py/gc.c
45
py/gc.c
@@ -484,11 +484,15 @@ void gc_free(void *ptr_in) {
|
||||
#if EXTENSIVE_HEAP_PROFILING
|
||||
gc_dump_alloc_table();
|
||||
#endif
|
||||
} else {
|
||||
assert(!"bad free");
|
||||
}
|
||||
} else if (ptr_in != NULL) {
|
||||
assert(!"bad free");
|
||||
}
|
||||
}
|
||||
|
||||
mp_uint_t gc_nbytes(void *ptr_in) {
|
||||
mp_uint_t gc_nbytes(const void *ptr_in) {
|
||||
mp_uint_t ptr = (mp_uint_t)ptr_in;
|
||||
|
||||
if (VERIFY_PTR(ptr)) {
|
||||
@@ -546,6 +550,12 @@ void *gc_realloc(void *ptr_in, mp_uint_t n_bytes) {
|
||||
return gc_alloc(n_bytes, false);
|
||||
}
|
||||
|
||||
// check for pure free
|
||||
if (n_bytes == 0) {
|
||||
gc_free(ptr_in);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mp_uint_t ptr = (mp_uint_t)ptr_in;
|
||||
|
||||
// sanity check the ptr
|
||||
@@ -671,31 +681,32 @@ void gc_dump_alloc_table(void) {
|
||||
for (mp_uint_t bl = 0; bl < gc_alloc_table_byte_len * BLOCKS_PER_ATB; bl++) {
|
||||
if (bl % DUMP_BYTES_PER_LINE == 0) {
|
||||
// a new line of blocks
|
||||
#if EXTENSIVE_HEAP_PROFILING
|
||||
{
|
||||
// check if this line contains only free blocks
|
||||
bool only_free_blocks = true;
|
||||
for (mp_uint_t bl2 = bl; bl2 < gc_alloc_table_byte_len * BLOCKS_PER_ATB && bl2 < bl + DUMP_BYTES_PER_LINE; bl2++) {
|
||||
if (ATB_GET_KIND(bl2) != AT_FREE) {
|
||||
|
||||
only_free_blocks = false;
|
||||
mp_uint_t bl2 = bl;
|
||||
while (bl2 < gc_alloc_table_byte_len * BLOCKS_PER_ATB && ATB_GET_KIND(bl2) == AT_FREE) {
|
||||
bl2++;
|
||||
}
|
||||
if (bl2 - bl >= 2 * DUMP_BYTES_PER_LINE) {
|
||||
// there are at least 2 lines containing only free blocks, so abbreviate their printing
|
||||
printf("\n (" UINT_FMT " lines all free)", (bl2 - bl) / DUMP_BYTES_PER_LINE);
|
||||
bl = bl2 & (~(DUMP_BYTES_PER_LINE - 1));
|
||||
if (bl >= gc_alloc_table_byte_len * BLOCKS_PER_ATB) {
|
||||
// got to end of heap
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (only_free_blocks) {
|
||||
// line contains only free blocks, so skip printing it
|
||||
bl += DUMP_BYTES_PER_LINE - 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// print header for new line of blocks
|
||||
printf("\n%04x: ", (uint)bl);
|
||||
#if EXTENSIVE_HEAP_PROFILING
|
||||
printf("\n%05x: ", (uint)(bl * BYTES_PER_BLOCK) & 0xfffff);
|
||||
#else
|
||||
printf("\n%05x: ", (uint)PTR_FROM_BLOCK(bl) & 0xfffff);
|
||||
#endif
|
||||
}
|
||||
int c = ' ';
|
||||
switch (ATB_GET_KIND(bl)) {
|
||||
case AT_FREE: c = '.'; break;
|
||||
case AT_HEAD: c = 'h'; break;
|
||||
/* this prints out if the object is reachable from BSS or STACK (for unix only)
|
||||
case AT_HEAD: {
|
||||
extern char __bss_start, _end;
|
||||
@@ -724,7 +735,7 @@ void gc_dump_alloc_table(void) {
|
||||
break;
|
||||
}
|
||||
*/
|
||||
/* this prints the uPy object type of the head block
|
||||
/* this prints the uPy object type of the head block */
|
||||
case AT_HEAD: {
|
||||
mp_uint_t *ptr = gc_pool_start + bl * WORDS_PER_BLOCK;
|
||||
if (*ptr == (mp_uint_t)&mp_type_tuple) { c = 'T'; }
|
||||
@@ -732,10 +743,10 @@ void gc_dump_alloc_table(void) {
|
||||
else if (*ptr == (mp_uint_t)&mp_type_dict) { c = 'D'; }
|
||||
else if (*ptr == (mp_uint_t)&mp_type_float) { c = 'F'; }
|
||||
else if (*ptr == (mp_uint_t)&mp_type_fun_bc) { c = 'B'; }
|
||||
else if (*ptr == (mp_uint_t)&mp_type_module) { c = 'M'; }
|
||||
else { c = 'h'; }
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case AT_TAIL: c = 't'; break;
|
||||
case AT_MARK: c = 'm'; break;
|
||||
}
|
||||
|
||||
2
py/gc.h
2
py/gc.h
@@ -40,7 +40,7 @@ void gc_collect_end(void);
|
||||
|
||||
void *gc_alloc(mp_uint_t n_bytes, bool has_finaliser);
|
||||
void gc_free(void *ptr);
|
||||
mp_uint_t gc_nbytes(void *ptr);
|
||||
mp_uint_t gc_nbytes(const void *ptr);
|
||||
void *gc_realloc(void *ptr, mp_uint_t n_bytes);
|
||||
|
||||
typedef struct _gc_info_t {
|
||||
|
||||
42
py/malloc.c
42
py/malloc.c
@@ -63,11 +63,8 @@ STATIC size_t peak_bytes_allocated = 0;
|
||||
#endif // MICROPY_ENABLE_GC
|
||||
|
||||
void *m_malloc(size_t num_bytes) {
|
||||
if (num_bytes == 0) {
|
||||
return NULL;
|
||||
}
|
||||
void *ptr = malloc(num_bytes);
|
||||
if (ptr == NULL) {
|
||||
if (ptr == NULL && num_bytes != 0) {
|
||||
return m_malloc_fail(num_bytes);
|
||||
}
|
||||
#if MICROPY_MEM_STATS
|
||||
@@ -81,9 +78,6 @@ void *m_malloc(size_t num_bytes) {
|
||||
|
||||
void *m_malloc_maybe(size_t num_bytes) {
|
||||
void *ptr = malloc(num_bytes);
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#if MICROPY_MEM_STATS
|
||||
total_bytes_allocated += num_bytes;
|
||||
current_bytes_allocated += num_bytes;
|
||||
@@ -95,11 +89,8 @@ void *m_malloc_maybe(size_t num_bytes) {
|
||||
|
||||
#if MICROPY_ENABLE_FINALISER
|
||||
void *m_malloc_with_finaliser(size_t num_bytes) {
|
||||
if (num_bytes == 0) {
|
||||
return NULL;
|
||||
}
|
||||
void *ptr = malloc_with_finaliser(num_bytes);
|
||||
if (ptr == NULL) {
|
||||
if (ptr == NULL && num_bytes != 0) {
|
||||
return m_malloc_fail(num_bytes);
|
||||
}
|
||||
#if MICROPY_MEM_STATS
|
||||
@@ -114,19 +105,16 @@ void *m_malloc_with_finaliser(size_t num_bytes) {
|
||||
|
||||
void *m_malloc0(size_t num_bytes) {
|
||||
void *ptr = m_malloc(num_bytes);
|
||||
if (ptr != NULL) {
|
||||
memset(ptr, 0, num_bytes);
|
||||
if (ptr == NULL && num_bytes != 0) {
|
||||
return m_malloc_fail(num_bytes);
|
||||
}
|
||||
memset(ptr, 0, num_bytes);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes) {
|
||||
if (new_num_bytes == 0) {
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
void *new_ptr = realloc(ptr, new_num_bytes);
|
||||
if (new_ptr == NULL) {
|
||||
if (new_ptr == NULL && new_num_bytes != 0) {
|
||||
return m_malloc_fail(new_num_bytes);
|
||||
}
|
||||
#if MICROPY_MEM_STATS
|
||||
@@ -146,28 +134,26 @@ void *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes) {
|
||||
|
||||
void *m_realloc_maybe(void *ptr, size_t old_num_bytes, size_t new_num_bytes) {
|
||||
void *new_ptr = realloc(ptr, new_num_bytes);
|
||||
if (new_ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#if MICROPY_MEM_STATS
|
||||
// At first thought, "Total bytes allocated" should only grow,
|
||||
// after all, it's *total*. But consider for example 2K block
|
||||
// shrunk to 1K and then grown to 2K again. It's still 2K
|
||||
// allocated total. If we process only positive increments,
|
||||
// we'll count 3K.
|
||||
size_t diff = new_num_bytes - old_num_bytes;
|
||||
total_bytes_allocated += diff;
|
||||
current_bytes_allocated += diff;
|
||||
UPDATE_PEAK();
|
||||
// Also, don't count failed reallocs.
|
||||
if (!(new_ptr == NULL && new_num_bytes != 0)) {
|
||||
size_t diff = new_num_bytes - old_num_bytes;
|
||||
total_bytes_allocated += diff;
|
||||
current_bytes_allocated += diff;
|
||||
UPDATE_PEAK();
|
||||
}
|
||||
#endif
|
||||
DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
void m_free(void *ptr, size_t num_bytes) {
|
||||
if (ptr != NULL) {
|
||||
free(ptr);
|
||||
}
|
||||
free(ptr);
|
||||
#if MICROPY_MEM_STATS
|
||||
current_bytes_allocated -= num_bytes;
|
||||
#endif
|
||||
|
||||
@@ -287,6 +287,11 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
|
||||
#endif
|
||||
|
||||
// Whether to support memoryview object
|
||||
#ifndef MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
#define MICROPY_PY_BUILTINS_MEMORYVIEW (0)
|
||||
#endif
|
||||
|
||||
// Whether to support set object
|
||||
#ifndef MICROPY_PY_BUILTINS_SET
|
||||
#define MICROPY_PY_BUILTINS_SET (1)
|
||||
@@ -307,6 +312,11 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_BUILTINS_PROPERTY (1)
|
||||
#endif
|
||||
|
||||
// Whether to support compile function
|
||||
#ifndef MICROPY_PY_BUILTINS_COMPILE
|
||||
#define MICROPY_PY_BUILTINS_COMPILE (0)
|
||||
#endif
|
||||
|
||||
// Whether to set __file__ for imported modules
|
||||
#ifndef MICROPY_PY___FILE__
|
||||
#define MICROPY_PY___FILE__ (1)
|
||||
@@ -403,6 +413,10 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_URE (0)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_UHEAPQ
|
||||
#define MICROPY_PY_UHEAPQ (0)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Hooks for a port to add builtins */
|
||||
|
||||
|
||||
8
py/obj.h
8
py/obj.h
@@ -292,6 +292,7 @@ extern const mp_obj_type_t mp_type_int;
|
||||
extern const mp_obj_type_t mp_type_str;
|
||||
extern const mp_obj_type_t mp_type_bytes;
|
||||
extern const mp_obj_type_t mp_type_bytearray;
|
||||
extern const mp_obj_type_t mp_type_memoryview;
|
||||
extern const mp_obj_type_t mp_type_float;
|
||||
extern const mp_obj_type_t mp_type_complex;
|
||||
extern const mp_obj_type_t mp_type_tuple;
|
||||
@@ -329,6 +330,7 @@ extern const mp_obj_type_t mp_type_GeneratorExit;
|
||||
extern const mp_obj_type_t mp_type_ImportError;
|
||||
extern const mp_obj_type_t mp_type_IndentationError;
|
||||
extern const mp_obj_type_t mp_type_IndexError;
|
||||
extern const mp_obj_type_t mp_type_KeyboardInterrupt;
|
||||
extern const mp_obj_type_t mp_type_KeyError;
|
||||
extern const mp_obj_type_t mp_type_LookupError;
|
||||
extern const mp_obj_type_t mp_type_MemoryError;
|
||||
@@ -339,7 +341,6 @@ extern const mp_obj_type_t mp_type_OverflowError;
|
||||
extern const mp_obj_type_t mp_type_RuntimeError;
|
||||
extern const mp_obj_type_t mp_type_StopIteration;
|
||||
extern const mp_obj_type_t mp_type_SyntaxError;
|
||||
extern const mp_obj_type_t mp_type_SystemError;
|
||||
extern const mp_obj_type_t mp_type_SystemExit;
|
||||
extern const mp_obj_type_t mp_type_TypeError;
|
||||
extern const mp_obj_type_t mp_type_ValueError;
|
||||
@@ -383,7 +384,7 @@ mp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg);
|
||||
mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, mp_uint_t n_args, const mp_obj_t *args);
|
||||
mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg);
|
||||
mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...); // counts args by number of % symbols in fmt, excluding %%; can only handle void* sizes (ie no float/double!)
|
||||
mp_obj_t mp_obj_new_fun_bc(mp_uint_t scope_flags, qstr *args, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_obj_t def_args, mp_obj_t def_kw_args, const byte *code);
|
||||
mp_obj_t mp_obj_new_fun_bc(mp_uint_t scope_flags, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_obj_t def_args, mp_obj_t def_kw_args, const byte *code);
|
||||
mp_obj_t mp_obj_new_fun_native(mp_uint_t n_args, void *fun_data);
|
||||
mp_obj_t mp_obj_new_fun_viper(mp_uint_t n_args, void *fun_data, mp_uint_t type_sig);
|
||||
mp_obj_t mp_obj_new_fun_asm(mp_uint_t n_args, void *fun_data);
|
||||
@@ -529,7 +530,6 @@ void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item);
|
||||
void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step);
|
||||
|
||||
// array
|
||||
mp_uint_t mp_obj_array_len(mp_obj_t self_in);
|
||||
mp_obj_t mp_obj_new_bytearray_by_ref(mp_uint_t n, void *items);
|
||||
|
||||
// functions
|
||||
@@ -556,6 +556,8 @@ typedef struct _mp_obj_module_t {
|
||||
mp_obj_dict_t *globals;
|
||||
} mp_obj_module_t;
|
||||
mp_obj_dict_t *mp_obj_module_get_globals(mp_obj_t self_in);
|
||||
// check if given module object is a package
|
||||
bool mp_obj_is_package(mp_obj_t module);
|
||||
|
||||
// staticmethod and classmethod types; defined here so we can make const versions
|
||||
// this structure is used for instances of both staticmethod and classmethod
|
||||
|
||||
182
py/objarray.c
182
py/objarray.c
@@ -37,7 +37,28 @@
|
||||
#include "runtime.h"
|
||||
#include "binary.h"
|
||||
|
||||
#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
|
||||
// About memoryview object: We want to reuse as much code as possible from
|
||||
// array, and keep the memoryview object 4 words in size so it fits in 1 GC
|
||||
// block. Also, memoryview must keep a pointer to the base of the buffer so
|
||||
// that the buffer is not GC'd if the original parent object is no longer
|
||||
// around (we are assuming that all memoryview'able objects return a pointer
|
||||
// which points to the start of a GC chunk). Given the above constraints we
|
||||
// do the following:
|
||||
// - typecode high bit is set if the buffer is read-write (else read-only)
|
||||
// - free is the offset in elements to the first item in the memoryview
|
||||
// - len is the length in elements
|
||||
// - items points to the start of the original buffer
|
||||
// Note that we don't handle the case where the original buffer might change
|
||||
// size due to a resize of the original parent object.
|
||||
|
||||
// make (& TYPECODE_MASK) a null operation if memorview not enabled
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
#define TYPECODE_MASK (0x7f)
|
||||
#else
|
||||
#define TYPECODE_MASK (~(mp_uint_t)1)
|
||||
#endif
|
||||
|
||||
typedef struct _mp_obj_array_t {
|
||||
mp_obj_base_t base;
|
||||
@@ -50,13 +71,13 @@ typedef struct _mp_obj_array_t {
|
||||
} mp_obj_array_t;
|
||||
|
||||
STATIC mp_obj_t array_iterator_new(mp_obj_t array_in);
|
||||
STATIC mp_obj_array_t *array_new(char typecode, mp_uint_t n);
|
||||
STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg);
|
||||
STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);
|
||||
|
||||
/******************************************************************************/
|
||||
/* array */
|
||||
// array
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
|
||||
STATIC void array_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
|
||||
mp_obj_array_t *o = o_in;
|
||||
if (o->typecode == BYTEARRAY_TYPECODE) {
|
||||
@@ -77,7 +98,31 @@ STATIC void array_print(void (*print)(void *env, const char *fmt, ...), void *en
|
||||
}
|
||||
print(env, ")");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
|
||||
STATIC mp_obj_array_t *array_new(char typecode, mp_uint_t n) {
|
||||
int typecode_size = mp_binary_get_size('@', typecode, NULL);
|
||||
if (typecode_size <= 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad typecode"));
|
||||
}
|
||||
mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY
|
||||
o->base.type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array;
|
||||
#elif MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
o->base.type = &mp_type_bytearray;
|
||||
#else
|
||||
o->base.type = &mp_type_array;
|
||||
#endif
|
||||
o->typecode = typecode;
|
||||
o->free = 0;
|
||||
o->len = n;
|
||||
o->items = m_malloc(typecode_size * o->len);
|
||||
return o;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
|
||||
STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
|
||||
uint len;
|
||||
// Try to create array of exact len if initializer len is known
|
||||
@@ -103,7 +148,9 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
|
||||
|
||||
return array;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_ARRAY
|
||||
STATIC mp_obj_t array_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, 2, false);
|
||||
|
||||
@@ -119,7 +166,9 @@ STATIC mp_obj_t array_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
|
||||
return array_construct(*typecode, args[1]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
STATIC mp_obj_t bytearray_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
|
||||
@@ -137,6 +186,33 @@ STATIC mp_obj_t bytearray_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
|
||||
return array_construct(BYTEARRAY_TYPECODE, args[0]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
STATIC mp_obj_t memoryview_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
// TODO possibly allow memoryview constructor to take start/stop so that one
|
||||
// can do memoryview(b, 4, 8) instead of memoryview(b)[4:8] (uses less RAM)
|
||||
|
||||
mp_arg_check_num(n_args, n_kw, 1, 1, false);
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
mp_obj_array_t *self = m_new_obj(mp_obj_array_t);
|
||||
self->base.type = type_in;
|
||||
self->typecode = bufinfo.typecode;
|
||||
self->free = 0;
|
||||
self->len = bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL); // element len
|
||||
self->items = bufinfo.buf;
|
||||
|
||||
// test if the object can be written to
|
||||
if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) {
|
||||
self->typecode |= 0x80; // used to indicate writable buffer
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t array_unary_op(mp_uint_t op, mp_obj_t o_in) {
|
||||
mp_obj_array_t *o = o_in;
|
||||
@@ -154,7 +230,7 @@ STATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in)
|
||||
mp_buffer_info_t rhs_bufinfo;
|
||||
array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);
|
||||
if (!mp_get_buffer(rhs_in, &rhs_bufinfo, MP_BUFFER_READ)) {
|
||||
return mp_const_false;
|
||||
return mp_const_false;
|
||||
}
|
||||
return MP_BOOL(mp_seq_cmp_bytes(op, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_bufinfo.len));
|
||||
}
|
||||
@@ -202,21 +278,41 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
|
||||
"only slices with step=1 (aka None) are supported"));
|
||||
}
|
||||
mp_obj_array_t *res = array_new(o->typecode, slice.stop - slice.start);
|
||||
int sz = mp_binary_get_size('@', o->typecode, NULL);
|
||||
mp_obj_array_t *res;
|
||||
int sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
|
||||
assert(sz > 0);
|
||||
byte *p = o->items;
|
||||
memcpy(res->items, p + slice.start * sz, (slice.stop - slice.start) * sz);
|
||||
if (0) {
|
||||
// dummy
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
} else if (o->base.type == &mp_type_memoryview) {
|
||||
res = m_new_obj(mp_obj_array_t);
|
||||
*res = *o;
|
||||
res->free += slice.start;
|
||||
res->len = slice.stop - slice.start;
|
||||
#endif
|
||||
} else {
|
||||
res = array_new(o->typecode, slice.stop - slice.start);
|
||||
memcpy(res->items, o->items + slice.start * sz, (slice.stop - slice.start) * sz);
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
} else {
|
||||
mp_uint_t index = mp_get_index(o->base.type, o->len, index_in, false);
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
if (o->base.type == &mp_type_memoryview) {
|
||||
index += o->free;
|
||||
if (value != MP_OBJ_SENTINEL && (o->typecode & 0x80) == 0) {
|
||||
// store to read-only memoryview
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (value == MP_OBJ_SENTINEL) {
|
||||
// load
|
||||
return mp_binary_get_val_array(o->typecode, o->items, index);
|
||||
return mp_binary_get_val_array(o->typecode & TYPECODE_MASK, o->items, index);
|
||||
} else {
|
||||
// store
|
||||
mp_binary_set_val_array(o->typecode, o->items, index, value);
|
||||
mp_binary_set_val_array(o->typecode & TYPECODE_MASK, o->items, index, value);
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
@@ -225,18 +321,31 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
|
||||
|
||||
STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
|
||||
mp_obj_array_t *o = o_in;
|
||||
int sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
|
||||
bufinfo->buf = o->items;
|
||||
bufinfo->len = o->len * mp_binary_get_size('@', o->typecode, NULL);
|
||||
bufinfo->typecode = o->typecode;
|
||||
bufinfo->len = o->len * sz;
|
||||
bufinfo->typecode = o->typecode & TYPECODE_MASK;
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
if (o->base.type == &mp_type_memoryview) {
|
||||
if ((o->typecode & 0x80) == 0 && (flags & MP_BUFFER_WRITE)) {
|
||||
// read-only memoryview
|
||||
return 1;
|
||||
}
|
||||
bufinfo->buf += (mp_uint_t)o->free * sz;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
|
||||
STATIC const mp_map_elem_t array_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_append), (mp_obj_t)&array_append_obj },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(array_locals_dict, array_locals_dict_table);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_ARRAY
|
||||
const mp_obj_type_t mp_type_array = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_array,
|
||||
@@ -249,7 +358,9 @@ const mp_obj_type_t mp_type_array = {
|
||||
.buffer_p = { .get_buffer = array_get_buffer },
|
||||
.locals_dict = (mp_obj_t)&array_locals_dict,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
const mp_obj_type_t mp_type_bytearray = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_bytearray,
|
||||
@@ -262,25 +373,28 @@ const mp_obj_type_t mp_type_bytearray = {
|
||||
.buffer_p = { .get_buffer = array_get_buffer },
|
||||
.locals_dict = (mp_obj_t)&array_locals_dict,
|
||||
};
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_array_t *array_new(char typecode, mp_uint_t n) {
|
||||
int typecode_size = mp_binary_get_size('@', typecode, NULL);
|
||||
if (typecode_size <= 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad typecode"));
|
||||
}
|
||||
mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
|
||||
o->base.type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array;
|
||||
o->typecode = typecode;
|
||||
o->free = 0;
|
||||
o->len = n;
|
||||
o->items = m_malloc(typecode_size * o->len);
|
||||
return o;
|
||||
}
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
const mp_obj_type_t mp_type_memoryview = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_memoryview,
|
||||
.make_new = memoryview_make_new,
|
||||
.getiter = array_iterator_new,
|
||||
.unary_op = array_unary_op,
|
||||
.binary_op = array_binary_op,
|
||||
.subscr = array_subscr,
|
||||
.buffer_p = { .get_buffer = array_get_buffer },
|
||||
};
|
||||
#endif
|
||||
|
||||
/* unused
|
||||
mp_uint_t mp_obj_array_len(mp_obj_t self_in) {
|
||||
return ((mp_obj_array_t *)self_in)->len;
|
||||
}
|
||||
*/
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
mp_obj_t mp_obj_new_bytearray(mp_uint_t n, void *items) {
|
||||
mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, n);
|
||||
memcpy(o->items, items, n);
|
||||
@@ -290,27 +404,29 @@ mp_obj_t mp_obj_new_bytearray(mp_uint_t n, void *items) {
|
||||
// Create bytearray which references specified memory area
|
||||
mp_obj_t mp_obj_new_bytearray_by_ref(mp_uint_t n, void *items) {
|
||||
mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
|
||||
o->base.type = &mp_type_array;
|
||||
o->base.type = &mp_type_bytearray;
|
||||
o->typecode = BYTEARRAY_TYPECODE;
|
||||
o->free = 0;
|
||||
o->len = n;
|
||||
o->items = items;
|
||||
return o;
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/* array iterator */
|
||||
// array iterator
|
||||
|
||||
typedef struct _mp_obj_array_it_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_array_t *array;
|
||||
mp_uint_t offset;
|
||||
mp_uint_t cur;
|
||||
} mp_obj_array_it_t;
|
||||
|
||||
STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {
|
||||
mp_obj_array_it_t *self = self_in;
|
||||
if (self->cur < self->array->len) {
|
||||
return mp_binary_get_val_array(self->array->typecode, self->array->items, self->cur++);
|
||||
return mp_binary_get_val_array(self->array->typecode & TYPECODE_MASK, self->array->items, self->offset + self->cur++);
|
||||
} else {
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
}
|
||||
@@ -325,11 +441,15 @@ STATIC const mp_obj_type_t array_it_type = {
|
||||
|
||||
STATIC mp_obj_t array_iterator_new(mp_obj_t array_in) {
|
||||
mp_obj_array_t *array = array_in;
|
||||
mp_obj_array_it_t *o = m_new_obj(mp_obj_array_it_t);
|
||||
mp_obj_array_it_t *o = m_new0(mp_obj_array_it_t, 1);
|
||||
o->base.type = &array_it_type;
|
||||
o->array = array;
|
||||
o->cur = 0;
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
if (array->base.type == &mp_type_memoryview) {
|
||||
o->offset = array->free;
|
||||
}
|
||||
#endif
|
||||
return o;
|
||||
}
|
||||
|
||||
#endif // MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
#endif // MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
|
||||
@@ -211,7 +211,7 @@ const mp_obj_type_t mp_type_ ## exc_name = { \
|
||||
// http://docs.python.org/3/library/exceptions.html
|
||||
MP_DEFINE_EXCEPTION_BASE(BaseException)
|
||||
MP_DEFINE_EXCEPTION(SystemExit, BaseException)
|
||||
//MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException)
|
||||
MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException)
|
||||
MP_DEFINE_EXCEPTION(GeneratorExit, BaseException)
|
||||
MP_DEFINE_EXCEPTION(Exception, BaseException)
|
||||
MP_DEFINE_EXCEPTION_BASE(Exception)
|
||||
@@ -268,7 +268,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
|
||||
MP_DEFINE_EXCEPTION_BASE(IndentationError)
|
||||
MP_DEFINE_EXCEPTION(TabError, IndentationError)
|
||||
*/
|
||||
MP_DEFINE_EXCEPTION(SystemError, Exception)
|
||||
//MP_DEFINE_EXCEPTION(SystemError, Exception)
|
||||
MP_DEFINE_EXCEPTION(TypeError, Exception)
|
||||
MP_DEFINE_EXCEPTION(ValueError, Exception)
|
||||
//TODO: Implement UnicodeErrors which take arguments
|
||||
|
||||
@@ -173,7 +173,10 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
|
||||
mp_uint_t code_info_size = mp_decode_uint(&code_info);
|
||||
const byte *ip = self->bytecode + code_info_size;
|
||||
|
||||
// bytecode prelude: state size and exception stack size; 16 bit uints
|
||||
// bytecode prelude: skip arg names
|
||||
ip += (self->n_pos_args + self->n_kwonly_args) * sizeof(mp_obj_t);
|
||||
|
||||
// bytecode prelude: state size and exception stack size
|
||||
mp_uint_t n_state = mp_decode_uint(&ip);
|
||||
mp_uint_t n_exc_stack = mp_decode_uint(&ip);
|
||||
|
||||
@@ -268,7 +271,7 @@ const mp_obj_type_t mp_type_fun_bc = {
|
||||
.binary_op = mp_obj_fun_binary_op,
|
||||
};
|
||||
|
||||
mp_obj_t mp_obj_new_fun_bc(mp_uint_t scope_flags, qstr *args, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_obj_t def_args_in, mp_obj_t def_kw_args, const byte *code) {
|
||||
mp_obj_t mp_obj_new_fun_bc(mp_uint_t scope_flags, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_obj_t def_args_in, mp_obj_t def_kw_args, const byte *code) {
|
||||
mp_uint_t n_def_args = 0;
|
||||
mp_uint_t n_extra_args = 0;
|
||||
mp_obj_tuple_t *def_args = def_args_in;
|
||||
@@ -283,7 +286,6 @@ mp_obj_t mp_obj_new_fun_bc(mp_uint_t scope_flags, qstr *args, mp_uint_t n_pos_ar
|
||||
mp_obj_fun_bc_t *o = m_new_obj_var(mp_obj_fun_bc_t, mp_obj_t, n_extra_args);
|
||||
o->base.type = &mp_type_fun_bc;
|
||||
o->globals = mp_globals_get();
|
||||
o->args = args;
|
||||
o->n_pos_args = n_pos_args;
|
||||
o->n_kwonly_args = n_kwonly_args;
|
||||
o->n_def_args = n_def_args;
|
||||
|
||||
@@ -27,14 +27,13 @@
|
||||
typedef struct _mp_obj_fun_bc_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_dict_t *globals; // the context within which this function was defined
|
||||
mp_uint_t n_pos_args : 16; // number of arguments this function takes
|
||||
mp_uint_t n_kwonly_args : 16; // number of arguments this function takes
|
||||
mp_uint_t n_def_args : 16; // number of default arguments
|
||||
mp_uint_t n_pos_args : 8; // number of arguments this function takes
|
||||
mp_uint_t n_kwonly_args : 8; // number of keyword-only arguments this function takes
|
||||
mp_uint_t n_def_args : 8; // number of default arguments
|
||||
mp_uint_t has_def_kw_args : 1; // set if this function has default keyword args
|
||||
mp_uint_t takes_var_args : 1; // set if this function takes variable args
|
||||
mp_uint_t takes_kw_args : 1; // set if this function takes keyword args
|
||||
const byte *bytecode; // bytecode for the function
|
||||
qstr *args; // argument names (needed to resolve positional args passed as keywords)
|
||||
// the following extra_args array is allocated space to take (in order):
|
||||
// - values of positional default args (if any)
|
||||
// - a single slot for default kw args dict (if it has them)
|
||||
|
||||
@@ -62,6 +62,9 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw
|
||||
mp_uint_t code_info_size = mp_decode_uint(&code_info);
|
||||
const byte *ip = self_fun->bytecode + code_info_size;
|
||||
|
||||
// bytecode prelude: skip arg names
|
||||
ip += (self_fun->n_pos_args + self_fun->n_kwonly_args) * sizeof(mp_obj_t);
|
||||
|
||||
// bytecode prelude: get state size and exception stack size
|
||||
mp_uint_t n_state = mp_decode_uint(&ip);
|
||||
mp_uint_t n_exc_stack = mp_decode_uint(&ip);
|
||||
|
||||
@@ -215,7 +215,7 @@ STATIC mp_obj_t bytes_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
|
||||
mp_int_t len;
|
||||
byte *data;
|
||||
vstr_t *vstr = NULL;
|
||||
mp_obj_t o = NULL;
|
||||
mp_obj_t o = MP_OBJ_NULL;
|
||||
// Try to create array of exact len if initializer len is known
|
||||
mp_obj_t len_in = mp_obj_len_maybe(args[0]);
|
||||
if (len_in == MP_OBJ_NULL) {
|
||||
|
||||
@@ -292,7 +292,7 @@ mp_obj_t instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, c
|
||||
o = new_ret;
|
||||
|
||||
// now call Python class __init__ function with all args
|
||||
init_fn[0] = init_fn[1] = NULL;
|
||||
init_fn[0] = init_fn[1] = MP_OBJ_NULL;
|
||||
lookup.obj = o;
|
||||
lookup.attr = MP_QSTR___init__;
|
||||
lookup.meth_offset = 0;
|
||||
|
||||
22
py/parse.c
22
py/parse.c
@@ -180,17 +180,17 @@ void mp_parse_node_free(mp_parse_node_t pn) {
|
||||
mp_uint_t rule_id = MP_PARSE_NODE_STRUCT_KIND(pns);
|
||||
if (rule_id == RULE_string) {
|
||||
m_del(char, (char*)pns->nodes[0], (mp_uint_t)pns->nodes[1]);
|
||||
return;
|
||||
}
|
||||
bool adjust = ADD_BLANK_NODE(rule_id);
|
||||
if (adjust) {
|
||||
n--;
|
||||
}
|
||||
for (mp_uint_t i = 0; i < n; i++) {
|
||||
mp_parse_node_free(pns->nodes[i]);
|
||||
}
|
||||
if (adjust) {
|
||||
n++;
|
||||
} else {
|
||||
bool adjust = ADD_BLANK_NODE(rule_id);
|
||||
if (adjust) {
|
||||
n--;
|
||||
}
|
||||
for (mp_uint_t i = 0; i < n; i++) {
|
||||
mp_parse_node_free(pns->nodes[i]);
|
||||
}
|
||||
if (adjust) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
m_del_var(mp_parse_node_struct_t, mp_parse_node_t, n, pns);
|
||||
}
|
||||
|
||||
1
py/py.mk
1
py/py.mk
@@ -114,6 +114,7 @@ PY_O_BASENAME = \
|
||||
../extmod/modujson.o \
|
||||
../extmod/modure.o \
|
||||
../extmod/moduzlib.o \
|
||||
../extmod/moduheapq.o \
|
||||
|
||||
# prepend the build destination prefix to the py object files
|
||||
PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME))
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "gc.h"
|
||||
|
||||
// NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings)
|
||||
// ultimately we will replace this with a static hash table of some kind
|
||||
@@ -220,9 +221,17 @@ void qstr_pool_info(mp_uint_t *n_pool, mp_uint_t *n_qstr, mp_uint_t *n_str_data_
|
||||
*n_pool += 1;
|
||||
*n_qstr += pool->len;
|
||||
for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) {
|
||||
#if MICROPY_ENABLE_GC
|
||||
*n_str_data_bytes += gc_nbytes(*q); // this counts actual bytes used in heap
|
||||
#else
|
||||
*n_str_data_bytes += Q_GET_ALLOC(*q);
|
||||
#endif
|
||||
}
|
||||
#if MICROPY_ENABLE_GC
|
||||
*n_total_bytes += gc_nbytes(pool); // this counts actual bytes used in heap
|
||||
#else
|
||||
*n_total_bytes += sizeof(qstr_pool_t) + sizeof(qstr) * pool->alloc;
|
||||
#endif
|
||||
}
|
||||
*n_total_bytes += *n_str_data_bytes;
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ Q(GeneratorExit)
|
||||
Q(ImportError)
|
||||
Q(IndentationError)
|
||||
Q(IndexError)
|
||||
Q(KeyboardInterrupt)
|
||||
Q(KeyError)
|
||||
Q(LookupError)
|
||||
Q(MemoryError)
|
||||
@@ -117,7 +118,6 @@ Q(OSError)
|
||||
Q(OverflowError)
|
||||
Q(RuntimeError)
|
||||
Q(SyntaxError)
|
||||
Q(SystemError)
|
||||
Q(SystemExit)
|
||||
Q(TypeError)
|
||||
Q(UnboundLocalError)
|
||||
@@ -135,11 +135,18 @@ Q(abs)
|
||||
Q(all)
|
||||
Q(any)
|
||||
Q(args)
|
||||
#if MICROPY_PY_ARRAY
|
||||
Q(array)
|
||||
#endif
|
||||
Q(bin)
|
||||
Q({:#b})
|
||||
Q(bool)
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
Q(bytearray)
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
Q(memoryview)
|
||||
#endif
|
||||
Q(bytes)
|
||||
Q(callable)
|
||||
#if MICROPY_PY_STRUCT
|
||||
@@ -207,6 +214,12 @@ Q(value)
|
||||
Q(write)
|
||||
Q(zip)
|
||||
|
||||
#if MICROPY_PY_BUILTINS_COMPILE
|
||||
Q(compile)
|
||||
Q(code)
|
||||
Q(single)
|
||||
#endif
|
||||
|
||||
Q(sep)
|
||||
Q(end)
|
||||
|
||||
@@ -486,3 +499,10 @@ Q(search)
|
||||
Q(group)
|
||||
Q(DEBUG)
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UHEAPQ
|
||||
Q(uheapq)
|
||||
Q(heappush)
|
||||
Q(heappop)
|
||||
Q(heapify)
|
||||
#endif
|
||||
|
||||
18
py/runtime.c
18
py/runtime.c
@@ -62,6 +62,9 @@
|
||||
#define DEBUG_OP_printf(...) (void)0
|
||||
#endif
|
||||
|
||||
// pending exception object (MP_OBJ_NULL if not pending)
|
||||
mp_obj_t mp_pending_exception;
|
||||
|
||||
// locals and globals need to be pointers because they can be the same in outer module scope
|
||||
STATIC mp_obj_dict_t *dict_locals;
|
||||
STATIC mp_obj_dict_t *dict_globals;
|
||||
@@ -79,6 +82,9 @@ void mp_init(void) {
|
||||
qstr_init();
|
||||
mp_stack_ctrl_init();
|
||||
|
||||
// no pending exceptions to start with
|
||||
mp_pending_exception = MP_OBJ_NULL;
|
||||
|
||||
#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
|
||||
mp_init_emergency_exception_buf();
|
||||
#endif
|
||||
@@ -475,8 +481,8 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
}
|
||||
if (type->getiter != NULL) {
|
||||
/* second attempt, walk the iterator */
|
||||
mp_obj_t next = NULL;
|
||||
mp_obj_t iter = mp_getiter(rhs);
|
||||
mp_obj_t next;
|
||||
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
|
||||
if (mp_obj_equal(next, lhs)) {
|
||||
return mp_const_true;
|
||||
@@ -1098,8 +1104,7 @@ import_error:
|
||||
}
|
||||
|
||||
// See if it's a package, then can try FS import
|
||||
mp_load_method_maybe(module, MP_QSTR___path__, dest);
|
||||
if (dest[0] == MP_OBJ_NULL) {
|
||||
if (!mp_obj_is_package(module)) {
|
||||
goto import_error;
|
||||
}
|
||||
|
||||
@@ -1190,6 +1195,13 @@ mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_i
|
||||
nlr_raise(module_fun);
|
||||
}
|
||||
|
||||
// for compile only
|
||||
if (MICROPY_PY_BUILTINS_COMPILE && globals == NULL) {
|
||||
mp_globals_set(old_globals);
|
||||
mp_locals_set(old_locals);
|
||||
return module_fun;
|
||||
}
|
||||
|
||||
// complied successfully, execute it
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
|
||||
@@ -116,6 +116,7 @@ mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type);
|
||||
mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args_kw, const mp_obj_t *args);
|
||||
NORETURN void mp_native_raise(mp_obj_t o);
|
||||
|
||||
extern mp_obj_t mp_pending_exception;
|
||||
extern struct _mp_obj_list_t mp_sys_path_obj;
|
||||
extern struct _mp_obj_list_t mp_sys_argv_obj;
|
||||
#define mp_sys_path ((mp_obj_t)&mp_sys_path_obj)
|
||||
|
||||
78
py/showbc.c
78
py/showbc.c
@@ -57,7 +57,7 @@
|
||||
ip += sizeof(mp_uint_t); \
|
||||
} while (0)
|
||||
|
||||
void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len) {
|
||||
void mp_bytecode_print(const void *descr, mp_uint_t n_total_args, const byte *ip, mp_uint_t len) {
|
||||
const byte *ip_start = ip;
|
||||
|
||||
// get code info size
|
||||
@@ -70,6 +70,24 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len) {
|
||||
printf("File %s, code block '%s' (descriptor: %p, bytecode @%p " UINT_FMT " bytes)\n",
|
||||
qstr_str(source_file), qstr_str(block_name), descr, code_info, len);
|
||||
|
||||
// raw bytecode dump
|
||||
printf("Raw bytecode (code_info_size=" UINT_FMT ", bytecode_size=" UINT_FMT "):\n", code_info_size, len - code_info_size);
|
||||
for (mp_uint_t i = 0; i < len; i++) {
|
||||
if (i > 0 && i % 16 == 0) {
|
||||
printf("\n");
|
||||
}
|
||||
printf(" %02x", ip_start[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// bytecode prelude: arg names (as qstr objects)
|
||||
printf("arg names:");
|
||||
for (int i = 0; i < n_total_args; i++) {
|
||||
printf(" %s", qstr_str(MP_OBJ_QSTR_VALUE(*(mp_obj_t*)ip)));
|
||||
ip += sizeof(mp_obj_t);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// bytecode prelude: state size and exception stack size; 16 bit uints
|
||||
{
|
||||
uint n_state = mp_decode_uint(&ip);
|
||||
@@ -87,15 +105,14 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len) {
|
||||
printf("(INIT_CELL %u)\n", local_num);
|
||||
}
|
||||
len -= ip - ip_start;
|
||||
ip_start = ip;
|
||||
}
|
||||
|
||||
// print out line number info
|
||||
{
|
||||
mp_int_t bc = (code_info + code_info_size) - ip;
|
||||
mp_int_t bc = (ip_start + code_info_size) - ip; // start counting from the prelude
|
||||
mp_uint_t source_line = 1;
|
||||
printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
|
||||
for (const byte* ci = code_info + 12; *ci;) {
|
||||
for (const byte* ci = code_info; *ci;) {
|
||||
if ((ci[0] & 0x80) == 0) {
|
||||
// 0b0LLBBBBB encoding
|
||||
bc += ci[0] & 0x1f;
|
||||
@@ -173,18 +190,6 @@ void mp_bytecode_print2(const byte *ip, mp_uint_t len) {
|
||||
printf("LOAD_NULL");
|
||||
break;
|
||||
|
||||
case MP_BC_LOAD_FAST_0:
|
||||
printf("LOAD_FAST_0");
|
||||
break;
|
||||
|
||||
case MP_BC_LOAD_FAST_1:
|
||||
printf("LOAD_FAST_1");
|
||||
break;
|
||||
|
||||
case MP_BC_LOAD_FAST_2:
|
||||
printf("LOAD_FAST_2");
|
||||
break;
|
||||
|
||||
case MP_BC_LOAD_FAST_N:
|
||||
DECODE_UINT;
|
||||
printf("LOAD_FAST_N " UINT_FMT, unum);
|
||||
@@ -223,18 +228,6 @@ void mp_bytecode_print2(const byte *ip, mp_uint_t len) {
|
||||
printf("LOAD_SUBSCR");
|
||||
break;
|
||||
|
||||
case MP_BC_STORE_FAST_0:
|
||||
printf("STORE_FAST_0");
|
||||
break;
|
||||
|
||||
case MP_BC_STORE_FAST_1:
|
||||
printf("STORE_FAST_1");
|
||||
break;
|
||||
|
||||
case MP_BC_STORE_FAST_2:
|
||||
printf("STORE_FAST_2");
|
||||
break;
|
||||
|
||||
case MP_BC_STORE_FAST_N:
|
||||
DECODE_UINT;
|
||||
printf("STORE_FAST_N " UINT_FMT, unum);
|
||||
@@ -380,16 +373,6 @@ void mp_bytecode_print2(const byte *ip, mp_uint_t len) {
|
||||
printf("NOT");
|
||||
break;
|
||||
|
||||
case MP_BC_UNARY_OP:
|
||||
unum = *ip++;
|
||||
printf("UNARY_OP " UINT_FMT, unum);
|
||||
break;
|
||||
|
||||
case MP_BC_BINARY_OP:
|
||||
unum = *ip++;
|
||||
printf("BINARY_OP " UINT_FMT, unum);
|
||||
break;
|
||||
|
||||
case MP_BC_BUILD_TUPLE:
|
||||
DECODE_UINT;
|
||||
printf("BUILD_TUPLE " UINT_FMT, unum);
|
||||
@@ -517,9 +500,22 @@ void mp_bytecode_print2(const byte *ip, mp_uint_t len) {
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("code %p, byte code 0x%02x not implemented\n", ip, ip[-1]);
|
||||
assert(0);
|
||||
return;
|
||||
if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
|
||||
printf("LOAD_CONST_SMALL_INT " INT_FMT, (mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16);
|
||||
} else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
|
||||
printf("LOAD_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_LOAD_FAST_MULTI);
|
||||
} else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
|
||||
printf("STORE_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_STORE_FAST_MULTI);
|
||||
} else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 5) {
|
||||
printf("UNARY_OP " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_UNARY_OP_MULTI);
|
||||
} else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 35) {
|
||||
printf("BINARY_OP " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_BINARY_OP_MULTI);
|
||||
} else {
|
||||
printf("code %p, byte code 0x%02x not implemented\n", ip, ip[-1]);
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@@ -57,23 +57,23 @@ bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y) {
|
||||
}
|
||||
|
||||
mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor) {
|
||||
mp_int_t lsign = (dividend >= 0) ? 1 :-1;
|
||||
mp_int_t rsign = (divisor >= 0) ? 1 :-1;
|
||||
// Python specs require that mod has same sign as second operand
|
||||
dividend %= divisor;
|
||||
if (lsign != rsign) {
|
||||
if ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) {
|
||||
dividend += divisor;
|
||||
}
|
||||
return dividend;
|
||||
}
|
||||
|
||||
mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom) {
|
||||
mp_int_t lsign = num > 0 ? 1 : -1;
|
||||
mp_int_t rsign = denom > 0 ? 1 : -1;
|
||||
if (lsign == -1) {num *= -1;}
|
||||
if (rsign == -1) {denom *= -1;}
|
||||
if (lsign != rsign){
|
||||
return - ( num + denom - 1) / denom;
|
||||
if (num >= 0) {
|
||||
if (denom < 0) {
|
||||
num += -denom - 1;
|
||||
}
|
||||
} else {
|
||||
return num / denom;
|
||||
if (denom >= 0) {
|
||||
num += -denom + 1;
|
||||
}
|
||||
}
|
||||
return num / denom;
|
||||
}
|
||||
|
||||
33
py/stream.c
33
py/stream.c
@@ -60,7 +60,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in);
|
||||
|
||||
#define STREAM_CONTENT_TYPE(stream) (((stream)->is_text) ? &mp_type_str : &mp_type_bytes)
|
||||
|
||||
STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t stream_read(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0];
|
||||
if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) {
|
||||
// CPython: io.UnsupportedOperation, OSError subclass
|
||||
@@ -215,17 +215,28 @@ STATIC mp_obj_t stream_write_method(mp_obj_t self_in, mp_obj_t arg) {
|
||||
return mp_stream_write(self_in, bufinfo.buf, bufinfo.len);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t stream_readinto(mp_obj_t self_in, mp_obj_t arg) {
|
||||
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in;
|
||||
STATIC mp_obj_t stream_readinto(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0];
|
||||
if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) {
|
||||
// CPython: io.UnsupportedOperation, OSError subclass
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
|
||||
}
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_WRITE);
|
||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
|
||||
|
||||
// CPython extension: if 2nd arg is provided, that's max len to read,
|
||||
// instead of full buffer. Similar to
|
||||
// https://docs.python.org/3/library/socket.html#socket.socket.recv_into
|
||||
mp_uint_t len = bufinfo.len;
|
||||
if (n_args > 2) {
|
||||
len = mp_obj_int_get(args[2]);
|
||||
if (len > bufinfo.len) {
|
||||
len = bufinfo.len;
|
||||
}
|
||||
}
|
||||
|
||||
int error;
|
||||
mp_uint_t out_sz = o->type->stream_p->read(o, bufinfo.buf, bufinfo.len, &error);
|
||||
mp_uint_t out_sz = o->type->stream_p->read(o, bufinfo.buf, len, &error);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
if (is_nonblocking_error(error)) {
|
||||
return mp_const_none;
|
||||
@@ -243,12 +254,12 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
|
||||
}
|
||||
|
||||
int total_size = 0;
|
||||
mp_uint_t total_size = 0;
|
||||
vstr_t *vstr = vstr_new_size(DEFAULT_BUFFER_SIZE);
|
||||
char *p = vstr_str(vstr);
|
||||
int error;
|
||||
int current_read = DEFAULT_BUFFER_SIZE;
|
||||
mp_uint_t current_read = DEFAULT_BUFFER_SIZE;
|
||||
while (true) {
|
||||
int error;
|
||||
mp_uint_t out_sz = o->type->stream_p->read(self_in, p, current_read, &error);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
if (is_nonblocking_error(error)) {
|
||||
@@ -285,7 +296,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
|
||||
}
|
||||
|
||||
// Unbuffered, inefficient implementation of readline() for raw I/O files.
|
||||
STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t stream_unbuffered_readline(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0];
|
||||
if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) {
|
||||
// CPython: io.UnsupportedOperation, OSError subclass
|
||||
@@ -304,13 +315,13 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) {
|
||||
vstr = vstr_new();
|
||||
}
|
||||
|
||||
int error;
|
||||
while (max_size == -1 || max_size-- != 0) {
|
||||
char *p = vstr_add_len(vstr, 1);
|
||||
if (p == NULL) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, "out of memory"));
|
||||
}
|
||||
|
||||
int error;
|
||||
mp_uint_t out_sz = o->type->stream_p->read(o, p, 1, &error);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
if (is_nonblocking_error(error)) {
|
||||
@@ -370,7 +381,7 @@ mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) {
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj, 1, 2, stream_read);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_readinto_obj, stream_readinto);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto_obj, 2, 3, stream_readinto);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_readall_obj, stream_readall);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj, 1, 2, stream_unbuffered_readline);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write_obj, stream_write_method);
|
||||
|
||||
107
py/vm.c
107
py/vm.c
@@ -110,10 +110,12 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
|
||||
code_state->ip = ip; \
|
||||
goto *entry_table[*ip++]; \
|
||||
} while(0)
|
||||
#define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
|
||||
#define ENTRY(op) entry_##op
|
||||
#define ENTRY_DEFAULT entry_default
|
||||
#else
|
||||
#define DISPATCH() break
|
||||
#define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
|
||||
#define ENTRY(op) case op
|
||||
#define ENTRY_DEFAULT default
|
||||
#endif
|
||||
@@ -223,18 +225,6 @@ dispatch_loop:
|
||||
PUSH(MP_OBJ_NULL);
|
||||
DISPATCH();
|
||||
|
||||
ENTRY(MP_BC_LOAD_FAST_0):
|
||||
obj_shared = fastn[0];
|
||||
goto load_check;
|
||||
|
||||
ENTRY(MP_BC_LOAD_FAST_1):
|
||||
obj_shared = fastn[-1];
|
||||
goto load_check;
|
||||
|
||||
ENTRY(MP_BC_LOAD_FAST_2):
|
||||
obj_shared = fastn[-2];
|
||||
goto load_check;
|
||||
|
||||
ENTRY(MP_BC_LOAD_FAST_N):
|
||||
DECODE_UINT;
|
||||
obj_shared = fastn[-unum];
|
||||
@@ -288,18 +278,6 @@ dispatch_loop:
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
ENTRY(MP_BC_STORE_FAST_0):
|
||||
fastn[0] = POP();
|
||||
DISPATCH();
|
||||
|
||||
ENTRY(MP_BC_STORE_FAST_1):
|
||||
fastn[-1] = POP();
|
||||
DISPATCH();
|
||||
|
||||
ENTRY(MP_BC_STORE_FAST_2):
|
||||
fastn[-2] = POP();
|
||||
DISPATCH();
|
||||
|
||||
ENTRY(MP_BC_STORE_FAST_N):
|
||||
DECODE_UINT;
|
||||
fastn[-unum] = POP();
|
||||
@@ -396,21 +374,21 @@ dispatch_loop:
|
||||
ENTRY(MP_BC_JUMP):
|
||||
DECODE_SLABEL;
|
||||
ip += unum;
|
||||
DISPATCH();
|
||||
DISPATCH_WITH_PEND_EXC_CHECK();
|
||||
|
||||
ENTRY(MP_BC_POP_JUMP_IF_TRUE):
|
||||
DECODE_SLABEL;
|
||||
if (mp_obj_is_true(POP())) {
|
||||
ip += unum;
|
||||
}
|
||||
DISPATCH();
|
||||
DISPATCH_WITH_PEND_EXC_CHECK();
|
||||
|
||||
ENTRY(MP_BC_POP_JUMP_IF_FALSE):
|
||||
DECODE_SLABEL;
|
||||
if (!mp_obj_is_true(POP())) {
|
||||
ip += unum;
|
||||
}
|
||||
DISPATCH();
|
||||
DISPATCH_WITH_PEND_EXC_CHECK();
|
||||
|
||||
ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP):
|
||||
DECODE_SLABEL;
|
||||
@@ -419,7 +397,7 @@ dispatch_loop:
|
||||
} else {
|
||||
sp--;
|
||||
}
|
||||
DISPATCH();
|
||||
DISPATCH_WITH_PEND_EXC_CHECK();
|
||||
|
||||
ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP):
|
||||
DECODE_SLABEL;
|
||||
@@ -428,7 +406,7 @@ dispatch_loop:
|
||||
} else {
|
||||
ip += unum;
|
||||
}
|
||||
DISPATCH();
|
||||
DISPATCH_WITH_PEND_EXC_CHECK();
|
||||
|
||||
ENTRY(MP_BC_SETUP_WITH): {
|
||||
mp_obj_t obj = TOP();
|
||||
@@ -526,7 +504,7 @@ unwind_jump:
|
||||
if (unum != 0) {
|
||||
sp--;
|
||||
}
|
||||
DISPATCH();
|
||||
DISPATCH_WITH_PEND_EXC_CHECK();
|
||||
|
||||
// matched against: POP_BLOCK or POP_EXCEPT (anything else?)
|
||||
ENTRY(MP_BC_SETUP_EXCEPT):
|
||||
@@ -606,19 +584,6 @@ unwind_jump:
|
||||
}
|
||||
DISPATCH();
|
||||
|
||||
ENTRY(MP_BC_UNARY_OP):
|
||||
unum = *ip++;
|
||||
SET_TOP(mp_unary_op(unum, TOP()));
|
||||
DISPATCH();
|
||||
|
||||
ENTRY(MP_BC_BINARY_OP): {
|
||||
unum = *ip++;
|
||||
mp_obj_t rhs = POP();
|
||||
mp_obj_t lhs = TOP();
|
||||
SET_TOP(mp_binary_op(unum, lhs, rhs));
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
ENTRY(MP_BC_BUILD_TUPLE):
|
||||
DECODE_UINT;
|
||||
sp -= unum - 1;
|
||||
@@ -890,7 +855,53 @@ yield:
|
||||
mp_import_all(POP());
|
||||
DISPATCH();
|
||||
|
||||
ENTRY_DEFAULT: {
|
||||
#if MICROPY_OPT_COMPUTED_GOTO
|
||||
ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
|
||||
PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
|
||||
DISPATCH();
|
||||
|
||||
ENTRY(MP_BC_LOAD_FAST_MULTI):
|
||||
obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
|
||||
goto load_check;
|
||||
|
||||
ENTRY(MP_BC_STORE_FAST_MULTI):
|
||||
fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
|
||||
DISPATCH();
|
||||
|
||||
ENTRY(MP_BC_UNARY_OP_MULTI):
|
||||
SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
|
||||
DISPATCH();
|
||||
|
||||
ENTRY(MP_BC_BINARY_OP_MULTI): {
|
||||
mp_obj_t rhs = POP();
|
||||
mp_obj_t lhs = TOP();
|
||||
SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
ENTRY_DEFAULT:
|
||||
#else
|
||||
ENTRY_DEFAULT:
|
||||
if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
|
||||
PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
|
||||
DISPATCH();
|
||||
} else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
|
||||
obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
|
||||
goto load_check;
|
||||
} else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
|
||||
fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
|
||||
DISPATCH();
|
||||
} else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 5) {
|
||||
SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
|
||||
DISPATCH();
|
||||
} else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 35) {
|
||||
mp_obj_t rhs = POP();
|
||||
mp_obj_t lhs = TOP();
|
||||
SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
|
||||
DISPATCH();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
|
||||
nlr_pop();
|
||||
fastn[0] = obj;
|
||||
@@ -900,6 +911,14 @@ yield:
|
||||
#if !MICROPY_OPT_COMPUTED_GOTO
|
||||
} // switch
|
||||
#endif
|
||||
|
||||
pending_exception_check:
|
||||
if (mp_pending_exception != MP_OBJ_NULL) {
|
||||
mp_obj_t obj = mp_pending_exception;
|
||||
mp_pending_exception = MP_OBJ_NULL;
|
||||
RAISE(obj);
|
||||
}
|
||||
|
||||
} // for loop
|
||||
|
||||
} else {
|
||||
|
||||
@@ -41,9 +41,6 @@ static void* entry_table[256] = {
|
||||
[MP_BC_LOAD_CONST_BYTES] = &&entry_MP_BC_LOAD_CONST_BYTES,
|
||||
[MP_BC_LOAD_CONST_STRING] = &&entry_MP_BC_LOAD_CONST_STRING,
|
||||
[MP_BC_LOAD_NULL] = &&entry_MP_BC_LOAD_NULL,
|
||||
[MP_BC_LOAD_FAST_0] = &&entry_MP_BC_LOAD_FAST_0,
|
||||
[MP_BC_LOAD_FAST_1] = &&entry_MP_BC_LOAD_FAST_1,
|
||||
[MP_BC_LOAD_FAST_2] = &&entry_MP_BC_LOAD_FAST_2,
|
||||
[MP_BC_LOAD_FAST_N] = &&entry_MP_BC_LOAD_FAST_N,
|
||||
[MP_BC_LOAD_DEREF] = &&entry_MP_BC_LOAD_DEREF,
|
||||
[MP_BC_LOAD_NAME] = &&entry_MP_BC_LOAD_NAME,
|
||||
@@ -52,9 +49,6 @@ static void* entry_table[256] = {
|
||||
[MP_BC_LOAD_METHOD] = &&entry_MP_BC_LOAD_METHOD,
|
||||
[MP_BC_LOAD_BUILD_CLASS] = &&entry_MP_BC_LOAD_BUILD_CLASS,
|
||||
[MP_BC_LOAD_SUBSCR] = &&entry_MP_BC_LOAD_SUBSCR,
|
||||
[MP_BC_STORE_FAST_0] = &&entry_MP_BC_STORE_FAST_0,
|
||||
[MP_BC_STORE_FAST_1] = &&entry_MP_BC_STORE_FAST_1,
|
||||
[MP_BC_STORE_FAST_2] = &&entry_MP_BC_STORE_FAST_2,
|
||||
[MP_BC_STORE_FAST_N] = &&entry_MP_BC_STORE_FAST_N,
|
||||
[MP_BC_STORE_DEREF] = &&entry_MP_BC_STORE_DEREF,
|
||||
[MP_BC_STORE_NAME] = &&entry_MP_BC_STORE_NAME,
|
||||
@@ -86,8 +80,6 @@ static void* entry_table[256] = {
|
||||
[MP_BC_POP_BLOCK] = &&entry_MP_BC_POP_BLOCK,
|
||||
[MP_BC_POP_EXCEPT] = &&entry_MP_BC_POP_EXCEPT,
|
||||
[MP_BC_NOT] = &&entry_MP_BC_NOT,
|
||||
[MP_BC_UNARY_OP] = &&entry_MP_BC_UNARY_OP,
|
||||
[MP_BC_BINARY_OP] = &&entry_MP_BC_BINARY_OP,
|
||||
[MP_BC_BUILD_TUPLE] = &&entry_MP_BC_BUILD_TUPLE,
|
||||
[MP_BC_BUILD_LIST] = &&entry_MP_BC_BUILD_LIST,
|
||||
[MP_BC_LIST_APPEND] = &&entry_MP_BC_LIST_APPEND,
|
||||
@@ -114,6 +106,11 @@ static void* entry_table[256] = {
|
||||
[MP_BC_IMPORT_NAME] = &&entry_MP_BC_IMPORT_NAME,
|
||||
[MP_BC_IMPORT_FROM] = &&entry_MP_BC_IMPORT_FROM,
|
||||
[MP_BC_IMPORT_STAR] = &&entry_MP_BC_IMPORT_STAR,
|
||||
[MP_BC_LOAD_CONST_SMALL_INT_MULTI ... MP_BC_LOAD_CONST_SMALL_INT_MULTI + 63] = &&entry_MP_BC_LOAD_CONST_SMALL_INT_MULTI,
|
||||
[MP_BC_LOAD_FAST_MULTI ... MP_BC_LOAD_FAST_MULTI + 15] = &&entry_MP_BC_LOAD_FAST_MULTI,
|
||||
[MP_BC_STORE_FAST_MULTI ... MP_BC_STORE_FAST_MULTI + 15] = &&entry_MP_BC_STORE_FAST_MULTI,
|
||||
[MP_BC_UNARY_OP_MULTI ... MP_BC_UNARY_OP_MULTI + 4] = &&entry_MP_BC_UNARY_OP_MULTI,
|
||||
[MP_BC_BINARY_OP_MULTI ... MP_BC_BINARY_OP_MULTI + 34] = &&entry_MP_BC_BINARY_OP_MULTI,
|
||||
};
|
||||
|
||||
#if __clang__
|
||||
|
||||
@@ -24,6 +24,8 @@ USBDEV_DIR=usbdev
|
||||
FATFS_DIR=fatfs
|
||||
DFU=../tools/dfu.py
|
||||
# may need to prefix dfu-util with sudo
|
||||
USE_PYDFU ?= 0
|
||||
PYDFU = ../tools/pydfu.py
|
||||
DFU_UTIL ?= dfu-util
|
||||
DEVICE=0483:df11
|
||||
|
||||
@@ -78,6 +80,7 @@ SRC_C = \
|
||||
usbd_desc_cdc_msc.c \
|
||||
usbd_cdc_interface.c \
|
||||
usbd_msc_storage.c \
|
||||
mphal.c \
|
||||
irq.c \
|
||||
pendsv.c \
|
||||
systick.c \
|
||||
@@ -249,7 +252,11 @@ all: $(BUILD)/firmware.dfu $(BUILD)/firmware.hex
|
||||
|
||||
deploy: $(BUILD)/firmware.dfu
|
||||
$(ECHO) "Writing $< to the board"
|
||||
ifeq ($(USE_PYDFU),1)
|
||||
$(Q)$(PYTHON) $(PYDFU) -u $<
|
||||
else
|
||||
$(Q)$(DFU_UTIL) -a 0 -d $(DEVICE) -D $<
|
||||
endif
|
||||
|
||||
$(BUILD)/firmware.dfu: $(BUILD)/firmware.elf
|
||||
$(ECHO) "Create $@"
|
||||
|
||||
@@ -44,3 +44,4 @@ LED_GREEN,PA14
|
||||
LED_YELLOW,PA15
|
||||
SW,PB3
|
||||
SD,PA8
|
||||
MMA_INT,PB2
|
||||
|
||||
|
@@ -1,11 +1,11 @@
|
||||
Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,
|
||||
,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11,I2C1/2/3,SPI1/SPI2/I2S2/I2S2ext,SPI3/I2Sext/I2S3,USART1/2/3/I2S3ext,UART4/5/USART6,CAN1/CAN2/TIM12/13/14,OTG_FS/OTG_HS,ETH,FSMC/SDIO/OTG_FS,DCMI,,,ADC
|
||||
PortA,PA0,,TIM2_CH1_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,ETH_MII_CRS,,,,EVENTOUT,ADC123_IN0
|
||||
PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,ETH_MII_CRS,,,,EVENTOUT,ADC123_IN0
|
||||
PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,,,ETH_MII_RX_CLK/ETH_RMII__REF_CLK,,,,EVENTOUT,ADC123_IN1
|
||||
PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,ETH_MDIO,,,,EVENTOUT,ADC123_IN2
|
||||
PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,,EVENTOUT,ADC123_IN3
|
||||
PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,,EVENTOUT,ADC12_IN4
|
||||
PortA,PA5,,TIM2_CH1_ETR,,TIM8_CH1N,,SPI1_SCK,,,,,OTG_HS_ULPI_CK,,,,,EVENTOUT,ADC12_IN5
|
||||
PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK,,,,,OTG_HS_ULPI_CK,,,,,EVENTOUT,ADC12_IN5
|
||||
PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCK,,EVENTOUT,ADC12_IN6
|
||||
PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,,,,EVENTOUT,ADC12_IN7
|
||||
PortA,PA8,MCO1,TIM1_CH1,,,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,,EVENTOUT,
|
||||
|
||||
|
@@ -29,8 +29,6 @@
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm32f4xx_hal.h"
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
@@ -41,6 +39,7 @@
|
||||
#include "bufhelper.h"
|
||||
#include "can.h"
|
||||
#include "pybioctl.h"
|
||||
#include MICROPY_HAL_H
|
||||
|
||||
#if MICROPY_HW_ENABLE_CAN
|
||||
|
||||
@@ -334,8 +333,7 @@ STATIC mp_obj_t pyb_can_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
|
||||
HAL_StatusTypeDef status = HAL_CAN_Transmit(&self->can, args[2].u_int);
|
||||
|
||||
if (status != HAL_OK) {
|
||||
// TODO really need a HardwareError object, or something
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_CAN_Transmit failed with code %d", status));
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
@@ -367,8 +365,7 @@ STATIC mp_obj_t pyb_can_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
|
||||
HAL_StatusTypeDef status = HAL_CAN_Receive(&self->can, args[0].u_int, args[1].u_int);
|
||||
|
||||
if (status != HAL_OK) {
|
||||
// TODO really need a HardwareError object, or something
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_CAN_Receive failed with code %d", status));
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
|
||||
// return the received data
|
||||
|
||||
23
stmhal/dac.c
23
stmhal/dac.c
@@ -39,6 +39,8 @@
|
||||
#include "runtime.h"
|
||||
#include "timer.h"
|
||||
#include "dac.h"
|
||||
#include "pin.h"
|
||||
#include "genhdr/pins.h"
|
||||
|
||||
/// \moduleref pyb
|
||||
/// \class DAC - digital to analog conversion
|
||||
@@ -107,18 +109,33 @@ typedef struct _pyb_dac_obj_t {
|
||||
// create the dac object
|
||||
// currently support either DAC1 on X5 (id = 1) or DAC2 on X6 (id = 2)
|
||||
|
||||
/// \classmethod \constructor(id)
|
||||
/// \classmethod \constructor(port)
|
||||
/// Construct a new DAC object.
|
||||
///
|
||||
/// `id` can be 1 or 2: DAC 1 is on pin X5 and DAC 2 is on pin X6.
|
||||
/// `port` can be a pin object, or an integer (1 or 2).
|
||||
/// DAC(1) is on pin X5 and DAC(2) is on pin X6.
|
||||
STATIC mp_obj_t pyb_dac_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 1, 1, false);
|
||||
|
||||
// get pin/channel to output on
|
||||
mp_int_t dac_id;
|
||||
if (MP_OBJ_IS_INT(args[0])) {
|
||||
dac_id = mp_obj_get_int(args[0]);
|
||||
} else {
|
||||
const pin_obj_t *pin = pin_find(args[0]);
|
||||
if (pin == &pin_A4) {
|
||||
dac_id = 1;
|
||||
} else if (pin == &pin_A5) {
|
||||
dac_id = 2;
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s does not have DAC capabilities", qstr_str(pin->name)));
|
||||
}
|
||||
}
|
||||
|
||||
pyb_dac_obj_t *dac = m_new_obj(pyb_dac_obj_t);
|
||||
dac->base.type = &pyb_dac_type;
|
||||
|
||||
mp_int_t dac_id = mp_obj_get_int(args[0]);
|
||||
uint32_t pin;
|
||||
if (dac_id == 1) {
|
||||
pin = GPIO_PIN_4;
|
||||
|
||||
17
stmhal/i2c.c
17
stmhal/i2c.c
@@ -27,8 +27,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stm32f4xx_hal.h"
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
@@ -39,6 +37,7 @@
|
||||
#include "genhdr/pins.h"
|
||||
#include "bufhelper.h"
|
||||
#include "i2c.h"
|
||||
#include MICROPY_HAL_H
|
||||
|
||||
/// \moduleref pyb
|
||||
/// \class I2C - a two-wire serial protocol
|
||||
@@ -148,7 +147,7 @@ void i2c_init(I2C_HandleTypeDef *i2c) {
|
||||
// init error
|
||||
// TODO should raise an exception, but this function is not necessarily going to be
|
||||
// called via Python, so may not be properly wrapped in an NLR handler
|
||||
printf("HardwareError: HAL_I2C_Init failed\n");
|
||||
printf("OSError: HAL_I2C_Init failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -390,8 +389,7 @@ STATIC mp_obj_t pyb_i2c_send(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *k
|
||||
}
|
||||
|
||||
if (status != HAL_OK) {
|
||||
// TODO really need a HardwareError object, or something
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_xxx_Transmit failed with code %d", status));
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
@@ -440,8 +438,7 @@ STATIC mp_obj_t pyb_i2c_recv(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *k
|
||||
}
|
||||
|
||||
if (status != HAL_OK) {
|
||||
// TODO really need a HardwareError object, or something
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_xxx_Receive failed with code %d", status));
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
|
||||
// return the received data
|
||||
@@ -501,8 +498,7 @@ STATIC mp_obj_t pyb_i2c_mem_read(mp_uint_t n_args, const mp_obj_t *args, mp_map_
|
||||
HAL_StatusTypeDef status = HAL_I2C_Mem_Read(self->i2c, i2c_addr, mem_addr, mem_addr_size, bufinfo.buf, bufinfo.len, vals[3].u_int);
|
||||
|
||||
if (status != HAL_OK) {
|
||||
// TODO really need a HardwareError object, or something
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Mem_Read failed with code %d", status));
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
|
||||
// return the read data
|
||||
@@ -554,8 +550,7 @@ STATIC mp_obj_t pyb_i2c_mem_write(mp_uint_t n_args, const mp_obj_t *args, mp_map
|
||||
HAL_StatusTypeDef status = HAL_I2C_Mem_Write(self->i2c, i2c_addr, mem_addr, mem_addr_size, bufinfo.buf, bufinfo.len, vals[3].u_int);
|
||||
|
||||
if (status != HAL_OK) {
|
||||
// TODO really need a HardwareError object, or something
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Mem_Write failed with code %d", status));
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
|
||||
@@ -137,17 +137,17 @@ STATIC mp_obj_t pyb_usb_mode(mp_obj_t usb_mode) {
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_mode_obj, pyb_usb_mode);
|
||||
|
||||
static const char fresh_boot_py[] =
|
||||
"# boot.py -- run on boot-up\n"
|
||||
"# can run arbitrary Python, but best to keep it minimal\n"
|
||||
"\n"
|
||||
"import pyb\n"
|
||||
"#pyb.main('main.py') # main script to run after this one\n"
|
||||
"#pyb.usb_mode('CDC+MSC') # act as a serial and a storage device\n"
|
||||
"#pyb.usb_mode('CDC+HID') # act as a serial device and a mouse\n"
|
||||
"# boot.py -- run on boot-up\r\n"
|
||||
"# can run arbitrary Python, but best to keep it minimal\r\n"
|
||||
"\r\n"
|
||||
"import pyb\r\n"
|
||||
"#pyb.main('main.py') # main script to run after this one\r\n"
|
||||
"#pyb.usb_mode('CDC+MSC') # act as a serial and a storage device\r\n"
|
||||
"#pyb.usb_mode('CDC+HID') # act as a serial device and a mouse\r\n"
|
||||
;
|
||||
|
||||
static const char fresh_main_py[] =
|
||||
"# main.py -- put your code here!\n"
|
||||
"# main.py -- put your code here!\r\n"
|
||||
;
|
||||
|
||||
static const char fresh_pybcdc_inf[] =
|
||||
@@ -458,7 +458,11 @@ soft_reset:
|
||||
const char *boot_py = "boot.py";
|
||||
FRESULT res = f_stat(boot_py, NULL);
|
||||
if (res == FR_OK) {
|
||||
if (!pyexec_file(boot_py)) {
|
||||
int ret = pyexec_file(boot_py);
|
||||
if (ret & PYEXEC_FORCED_EXIT) {
|
||||
goto soft_reset_exit;
|
||||
}
|
||||
if (!ret) {
|
||||
flash_error(4);
|
||||
}
|
||||
}
|
||||
@@ -517,7 +521,11 @@ soft_reset:
|
||||
}
|
||||
FRESULT res = f_stat(main_py, NULL);
|
||||
if (res == FR_OK) {
|
||||
if (!pyexec_file(main_py)) {
|
||||
int ret = pyexec_file(main_py);
|
||||
if (ret & PYEXEC_FORCED_EXIT) {
|
||||
goto soft_reset_exit;
|
||||
}
|
||||
if (!ret) {
|
||||
flash_error(3);
|
||||
}
|
||||
}
|
||||
@@ -537,6 +545,8 @@ soft_reset:
|
||||
}
|
||||
}
|
||||
|
||||
soft_reset_exit:
|
||||
|
||||
// soft reset
|
||||
|
||||
printf("PYB: sync filesystems\n");
|
||||
|
||||
@@ -365,57 +365,57 @@ STATIC void cc3k_socket_print(void (*print)(void *env, const char *fmt, ...), vo
|
||||
printf("<CC3k.socket fd=%d>", self->fd);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t cc3k_socket_send(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
|
||||
STATIC mp_obj_t cc3k_socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
|
||||
cc3k_socket_obj_t *self = self_in;
|
||||
|
||||
if (cc3k_get_fd_closed_state(self->fd)) {
|
||||
CC3000_EXPORT(closesocket)(self->fd);
|
||||
*errcode = EPIPE;
|
||||
return 0;
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EPIPE)));
|
||||
}
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
// CC3K does not handle fragmentation, and will overflow,
|
||||
// split the packet into smaller ones and send them out.
|
||||
int bytes = 0;
|
||||
while (bytes < size) {
|
||||
int n = MIN((size-bytes), MAX_TX_PACKET);
|
||||
n = CC3000_EXPORT(send)(self->fd, buf+bytes, n, 0);
|
||||
mp_int_t bytes = 0;
|
||||
while (bytes < bufinfo.len) {
|
||||
int n = MIN((bufinfo.len - bytes), MAX_TX_PACKET);
|
||||
n = CC3000_EXPORT(send)(self->fd, bufinfo.buf + bytes, n, 0);
|
||||
if (n <= 0) {
|
||||
bytes = n;
|
||||
*errcode = CC3000_EXPORT(errno);
|
||||
break;
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(CC3000_EXPORT(errno))));
|
||||
}
|
||||
bytes += n;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
return MP_OBJ_NEW_SMALL_INT(bytes);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cc3k_socket_send_obj, cc3k_socket_send);
|
||||
|
||||
STATIC mp_uint_t cc3k_socket_recv(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
STATIC mp_obj_t cc3k_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
|
||||
cc3k_socket_obj_t *self = self_in;
|
||||
|
||||
if (cc3k_get_fd_closed_state(self->fd)) {
|
||||
CC3000_EXPORT(closesocket)(self->fd);
|
||||
return 0;
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EPIPE)));
|
||||
}
|
||||
|
||||
// recv MAX_RX_PACKET
|
||||
int bytes = 0;
|
||||
while (bytes < size) {
|
||||
int n = MIN((size-bytes), MAX_RX_PACKET);
|
||||
n = CC3000_EXPORT(recv)(self->fd, buf+bytes, n, 0);
|
||||
if (n == 0) {
|
||||
break;
|
||||
} else if (n < 0) {
|
||||
bytes = n;
|
||||
*errcode = CC3000_EXPORT(errno);
|
||||
break;
|
||||
}
|
||||
bytes += n;
|
||||
}
|
||||
// recv upto MAX_RX_PACKET
|
||||
mp_int_t len = mp_obj_get_int(len_in);
|
||||
len = MIN(len, MAX_RX_PACKET);
|
||||
|
||||
return bytes;
|
||||
byte *buf;
|
||||
mp_obj_t ret_obj = mp_obj_str_builder_start(&mp_type_bytes, len, &buf);
|
||||
len = CC3000_EXPORT(recv)(self->fd, buf, len, 0);
|
||||
if (len == 0) {
|
||||
return mp_const_empty_bytes;
|
||||
} else if (len < 0) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(CC3000_EXPORT(errno))));
|
||||
} else {
|
||||
return mp_obj_str_builder_end_with_len(ret_obj, len);
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cc3k_socket_recv_obj, cc3k_socket_recv);
|
||||
|
||||
STATIC mp_obj_t cc3k_socket_bind(mp_obj_t self_in, mp_obj_t addr_obj) {
|
||||
cc3k_socket_obj_t *self = self_in;
|
||||
@@ -565,9 +565,8 @@ STATIC mp_obj_t cc3k_socket_close(mp_obj_t self_in) {
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_socket_close_obj, cc3k_socket_close);
|
||||
|
||||
STATIC const mp_map_elem_t cc3k_socket_locals_dict_table[] = {
|
||||
// TODO read/write/send/recv distinctions
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&mp_stream_write_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&mp_stream_read_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&cc3k_socket_send_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&cc3k_socket_recv_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&cc3k_socket_bind_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&cc3k_socket_listen_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&cc3k_socket_accept_obj },
|
||||
@@ -644,8 +643,6 @@ mp_uint_t cc3k_ioctl(mp_obj_t self_in, mp_uint_t request, int *errcode, ...) {
|
||||
}
|
||||
|
||||
STATIC const mp_stream_p_t cc3k_socket_stream_p = {
|
||||
.read = cc3k_socket_recv,
|
||||
.write = cc3k_socket_send,
|
||||
.ioctl = cc3k_ioctl,
|
||||
.is_text = false,
|
||||
};
|
||||
|
||||
@@ -88,6 +88,15 @@ STATIC NORETURN mp_obj_t pyb_bootloader(void) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_bootloader_obj, pyb_bootloader);
|
||||
|
||||
/// \function hard_reset()
|
||||
/// Resets the pyboard in a manner similar to pushing the external RESET
|
||||
/// button.
|
||||
STATIC mp_obj_t pyb_hard_reset(void) {
|
||||
NVIC_SystemReset();
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_hard_reset_obj, pyb_hard_reset);
|
||||
|
||||
/// \function info([dump_alloc_table])
|
||||
/// Print out lots of information about the board.
|
||||
STATIC mp_obj_t pyb_info(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
@@ -443,6 +452,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bootloader), (mp_obj_t)&pyb_bootloader_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_hard_reset), (mp_obj_t)&pyb_hard_reset_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_info_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_unique_id), (mp_obj_t)&pyb_unique_id_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&pyb_freq_obj },
|
||||
|
||||
@@ -415,12 +415,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(wiznet5k_socket_send_obj, wiznet5k_socket_send)
|
||||
STATIC mp_obj_t wiznet5k_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
|
||||
wiznet5k_socket_obj_t *self = self_in;
|
||||
mp_int_t len = mp_obj_get_int(len_in);
|
||||
uint8_t *buf = m_new(uint8_t, len);
|
||||
byte *buf;
|
||||
mp_obj_t ret_obj = mp_obj_str_builder_start(&mp_type_bytes, len, &buf);
|
||||
mp_int_t ret = WIZCHIP_EXPORT(recv)(self->sn, buf, len);
|
||||
check_sock_return_value(ret);
|
||||
mp_obj_t ret_buf = mp_obj_new_bytes(buf, ret);
|
||||
m_del(uint8_t, buf, len);
|
||||
return ret_buf;
|
||||
return mp_obj_str_builder_end_with_len(ret_obj, len);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(wiznet5k_socket_recv_obj, wiznet5k_socket_recv);
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#define MICROPY_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
|
||||
#define MICROPY_MODULE_WEAK_LINKS (1)
|
||||
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
|
||||
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
|
||||
#define MICROPY_PY_BUILTINS_FROZENSET (1)
|
||||
#define MICROPY_PY_SYS_EXIT (1)
|
||||
#define MICROPY_PY_SYS_STDFILES (1)
|
||||
@@ -60,6 +61,7 @@
|
||||
#define MICROPY_PY_UZLIB (1)
|
||||
#define MICROPY_PY_UJSON (1)
|
||||
#define MICROPY_PY_URE (1)
|
||||
#define MICROPY_PY_UHEAPQ (1)
|
||||
|
||||
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
|
||||
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0)
|
||||
|
||||
20
stmhal/mphal.c
Normal file
20
stmhal/mphal.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "mphal.h"
|
||||
|
||||
// this table converts from HAL_StatusTypeDef to POSIX errno
|
||||
const byte mp_hal_status_to_errno_table[4] = {
|
||||
[HAL_OK] = 0,
|
||||
[HAL_ERROR] = EIO,
|
||||
[HAL_BUSY] = EBUSY,
|
||||
[HAL_TIMEOUT] = ETIMEDOUT,
|
||||
};
|
||||
|
||||
NORETURN void mp_hal_raise(HAL_StatusTypeDef status) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, (mp_obj_t)(mp_uint_t)mp_hal_status_to_errno_table[status]));
|
||||
}
|
||||
@@ -6,3 +6,7 @@
|
||||
#define GPIO_set_pin(gpio, pin_mask) (((gpio)->BSRRL) = (pin_mask))
|
||||
#define GPIO_clear_pin(gpio, pin_mask) (((gpio)->BSRRH) = (pin_mask))
|
||||
#define GPIO_read_output_pin(gpio, pin) (((gpio)->ODR >> (pin)) & 1)
|
||||
|
||||
extern const byte mp_hal_status_to_errno_table[4];
|
||||
|
||||
NORETURN void mp_hal_raise(HAL_StatusTypeDef status);
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "runtime.h"
|
||||
#include "pendsv.h"
|
||||
|
||||
static void *pendsv_object = NULL;
|
||||
@@ -40,12 +41,22 @@ void pendsv_init(void) {
|
||||
HAL_NVIC_SetPriority(PendSV_IRQn, 0xf, 0xf);
|
||||
}
|
||||
|
||||
// call this function to raise a pending exception during an interrupt
|
||||
// it will wait until all interrupts are finished then raise the given
|
||||
// exception object using nlr_jump in the context of the top-level thread
|
||||
// Call this function to raise a pending exception during an interrupt.
|
||||
// It will first try to raise the exception "softly" by setting the
|
||||
// mp_pending_exception variable and hoping that the VM will notice it.
|
||||
// If this function is called a second time (ie with the mp_pending_exception
|
||||
// variable already set) then it will force the exception by using the hardware
|
||||
// PENDSV feature. This will wait until all interrupts are finished then raise
|
||||
// the given exception object using nlr_jump in the context of the top-level
|
||||
// thread.
|
||||
void pendsv_nlr_jump(void *o) {
|
||||
pendsv_object = o;
|
||||
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
|
||||
if (mp_pending_exception == MP_OBJ_NULL) {
|
||||
mp_pending_exception = o;
|
||||
} else {
|
||||
mp_pending_exception = MP_OBJ_NULL;
|
||||
pendsv_object = o;
|
||||
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
|
||||
}
|
||||
}
|
||||
|
||||
// since we play tricks with the stack, the compiler must not generate a
|
||||
|
||||
@@ -54,48 +54,77 @@
|
||||
pyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
|
||||
STATIC bool repl_display_debugging_info = 0;
|
||||
|
||||
#define EXEC_FLAG_PRINT_EOF (1)
|
||||
#define EXEC_FLAG_ALLOW_DEBUGGING (2)
|
||||
#define EXEC_FLAG_IS_REPL (4)
|
||||
|
||||
// parses, compiles and executes the code in the lexer
|
||||
// frees the lexer before returning
|
||||
bool parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) {
|
||||
// EXEC_FLAG_PRINT_EOF prints 2 EOF chars: 1 after normal output, 1 after exception output
|
||||
// EXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after executing the code
|
||||
// EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile)
|
||||
STATIC int parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, int exec_flags) {
|
||||
int ret = 0;
|
||||
|
||||
mp_parse_error_kind_t parse_error_kind;
|
||||
mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_error_kind);
|
||||
qstr source_name = mp_lexer_source_name(lex);
|
||||
|
||||
// check for parse error
|
||||
if (pn == MP_PARSE_NODE_NULL) {
|
||||
// parse error
|
||||
if (exec_flags & EXEC_FLAG_PRINT_EOF) {
|
||||
stdout_tx_strn("\x04", 1);
|
||||
}
|
||||
mp_parse_show_exception(lex, parse_error_kind);
|
||||
mp_lexer_free(lex);
|
||||
return false;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
mp_lexer_free(lex);
|
||||
|
||||
mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, is_repl);
|
||||
mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, exec_flags & EXEC_FLAG_IS_REPL);
|
||||
|
||||
// check for compile error
|
||||
if (mp_obj_is_exception_instance(module_fun)) {
|
||||
if (exec_flags & EXEC_FLAG_PRINT_EOF) {
|
||||
stdout_tx_strn("\x04", 1);
|
||||
}
|
||||
mp_obj_print_exception(module_fun);
|
||||
return false;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
// execute code
|
||||
nlr_buf_t nlr;
|
||||
bool ret;
|
||||
uint32_t start = HAL_GetTick();
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
usb_vcp_set_interrupt_char(VCP_CHAR_CTRL_C); // allow ctrl-C to interrupt us
|
||||
mp_call_function_0(module_fun);
|
||||
usb_vcp_set_interrupt_char(VCP_CHAR_NONE); // disable interrupt
|
||||
nlr_pop();
|
||||
ret = true;
|
||||
ret = 1;
|
||||
if (exec_flags & EXEC_FLAG_PRINT_EOF) {
|
||||
stdout_tx_strn("\x04", 1);
|
||||
}
|
||||
} else {
|
||||
// uncaught exception
|
||||
// FIXME it could be that an interrupt happens just before we disable it here
|
||||
usb_vcp_set_interrupt_char(VCP_CHAR_NONE); // disable interrupt
|
||||
mp_obj_print_exception((mp_obj_t)nlr.ret_val);
|
||||
ret = false;
|
||||
// print EOF after normal output
|
||||
if (exec_flags & EXEC_FLAG_PRINT_EOF) {
|
||||
stdout_tx_strn("\x04", 1);
|
||||
}
|
||||
// check for SystemExit
|
||||
if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_SystemExit)) {
|
||||
// at the moment, the value of SystemExit is unused
|
||||
ret = PYEXEC_FORCED_EXIT;
|
||||
} else {
|
||||
mp_obj_print_exception((mp_obj_t)nlr.ret_val);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// display debugging info if wanted
|
||||
if (is_repl && repl_display_debugging_info) {
|
||||
if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) {
|
||||
uint32_t ticks = HAL_GetTick() - start; // TODO implement a function that does this properly
|
||||
printf("took %lu ms\n", ticks);
|
||||
gc_collect();
|
||||
@@ -117,6 +146,11 @@ bool parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bo
|
||||
}
|
||||
}
|
||||
|
||||
finish:
|
||||
if (exec_flags & EXEC_FLAG_PRINT_EOF) {
|
||||
stdout_tx_strn("\x04", 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -160,18 +194,18 @@ raw_repl_reset:
|
||||
// exit for a soft reset
|
||||
stdout_tx_str("\r\n");
|
||||
vstr_clear(&line);
|
||||
return 1;
|
||||
return PYEXEC_FORCED_EXIT;
|
||||
}
|
||||
|
||||
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line.buf, line.len, 0);
|
||||
if (lex == NULL) {
|
||||
printf("MemoryError\n");
|
||||
printf("\x04MemoryError\n\x04");
|
||||
} else {
|
||||
parse_compile_execute(lex, MP_PARSE_FILE_INPUT, false);
|
||||
int ret = parse_compile_execute(lex, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF);
|
||||
if (ret & PYEXEC_FORCED_EXIT) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// indicate end of output with EOF character
|
||||
stdout_tx_str("\004");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,6 +242,7 @@ friendly_repl_reset:
|
||||
*/
|
||||
|
||||
for (;;) {
|
||||
input_restart:
|
||||
vstr_reset(&line);
|
||||
int ret = readline(&line, ">>> ");
|
||||
|
||||
@@ -229,7 +264,7 @@ friendly_repl_reset:
|
||||
// exit for a soft reset
|
||||
stdout_tx_str("\r\n");
|
||||
vstr_clear(&line);
|
||||
return 1;
|
||||
return PYEXEC_FORCED_EXIT;
|
||||
} else if (vstr_len(&line) == 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -237,7 +272,11 @@ friendly_repl_reset:
|
||||
while (mp_repl_continue_with_input(vstr_str(&line))) {
|
||||
vstr_add_char(&line, '\n');
|
||||
int ret = readline(&line, "... ");
|
||||
if (ret == VCP_CHAR_CTRL_D) {
|
||||
if (ret == VCP_CHAR_CTRL_C) {
|
||||
// cancel everything
|
||||
stdout_tx_str("\r\n");
|
||||
goto input_restart;
|
||||
} else if (ret == VCP_CHAR_CTRL_D) {
|
||||
// stop entering compound statement
|
||||
break;
|
||||
}
|
||||
@@ -247,12 +286,15 @@ friendly_repl_reset:
|
||||
if (lex == NULL) {
|
||||
printf("MemoryError\n");
|
||||
} else {
|
||||
parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT, true);
|
||||
int ret = parse_compile_execute(lex, MP_PARSE_SINGLE_INPUT, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL);
|
||||
if (ret & PYEXEC_FORCED_EXIT) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool pyexec_file(const char *filename) {
|
||||
int pyexec_file(const char *filename) {
|
||||
mp_lexer_t *lex = mp_lexer_new_from_file(filename);
|
||||
|
||||
if (lex == NULL) {
|
||||
@@ -260,7 +302,7 @@ bool pyexec_file(const char *filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parse_compile_execute(lex, MP_PARSE_FILE_INPUT, false);
|
||||
return parse_compile_execute(lex, MP_PARSE_FILE_INPUT, 0);
|
||||
}
|
||||
|
||||
mp_obj_t pyb_set_repl_info(mp_obj_t o_value) {
|
||||
|
||||
@@ -31,8 +31,10 @@ typedef enum {
|
||||
|
||||
extern pyexec_mode_kind_t pyexec_mode_kind;
|
||||
|
||||
#define PYEXEC_FORCED_EXIT (0x100)
|
||||
|
||||
int pyexec_raw_repl(void);
|
||||
int pyexec_friendly_repl(void);
|
||||
bool pyexec_file(const char *filename);
|
||||
int pyexec_file(const char *filename);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(pyb_set_repl_info_obj);
|
||||
|
||||
@@ -30,6 +30,7 @@ Q(help)
|
||||
Q(pyb)
|
||||
Q(unique_id)
|
||||
Q(bootloader)
|
||||
Q(hard_reset)
|
||||
Q(info)
|
||||
Q(sd_test)
|
||||
Q(present)
|
||||
|
||||
@@ -86,6 +86,9 @@ int readline(vstr_t *line, const char *prompt) {
|
||||
} else if (c == VCP_CHAR_CTRL_A) {
|
||||
// CTRL-A with non-empty line is go-to-start-of-line
|
||||
goto home_key;
|
||||
} else if (c == VCP_CHAR_CTRL_C) {
|
||||
// CTRL-C with non-empty line is cancel
|
||||
return c;
|
||||
} else if (c == VCP_CHAR_CTRL_E) {
|
||||
// CTRL-E is go-to-end-of-line
|
||||
goto end_key;
|
||||
|
||||
29
stmhal/spi.c
29
stmhal/spi.c
@@ -27,8 +27,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stm32f4xx_hal.h"
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
@@ -39,6 +37,7 @@
|
||||
#include "genhdr/pins.h"
|
||||
#include "bufhelper.h"
|
||||
#include "spi.h"
|
||||
#include MICROPY_HAL_H
|
||||
|
||||
/// \moduleref pyb
|
||||
/// \class SPI - a master-driven serial protocol
|
||||
@@ -50,11 +49,12 @@
|
||||
/// parameters to init the SPI bus:
|
||||
///
|
||||
/// from pyb import SPI
|
||||
/// spi = SPI(1, SPI.MASTER, baudrate=600000, polarity=1, phase=1, crc=0x7)
|
||||
/// spi = SPI(1, SPI.MASTER, baudrate=600000, polarity=1, phase=0, crc=0x7)
|
||||
///
|
||||
/// Only required parameter is mode, SPI.MASTER or SPI.SLAVE. Polarity can be
|
||||
/// 0 or 1, and is the level the idle clock line sits at. Phase can be 1 or 2
|
||||
/// for number of edges. Crc can be None for no CRC, or a polynomial specifier.
|
||||
/// 0 or 1, and is the level the idle clock line sits at. Phase can be 0 or 1
|
||||
/// to sample data on the first or second clock edge respectively. Crc can be
|
||||
/// None for no CRC, or a polynomial specifier.
|
||||
///
|
||||
/// Additional method for SPI:
|
||||
///
|
||||
@@ -140,7 +140,7 @@ void spi_init(SPI_HandleTypeDef *spi, bool enable_nss_pin) {
|
||||
// init error
|
||||
// TODO should raise an exception, but this function is not necessarily going to be
|
||||
// called via Python, so may not be properly wrapped in an NLR handler
|
||||
printf("HardwareError: HAL_SPI_Init failed\n");
|
||||
printf("OSError: HAL_SPI_Init failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -224,7 +224,7 @@ STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void *
|
||||
} else {
|
||||
print(env, "SPI(%u, SPI.SLAVE", spi_num);
|
||||
}
|
||||
print(env, ", polarity=%u, phase=%u, bits=%u", self->spi->Init.CLKPolarity == SPI_POLARITY_LOW ? 0 : 1, self->spi->Init.CLKPhase == SPI_PHASE_1EDGE ? 1 : 2, self->spi->Init.DataSize == SPI_DATASIZE_8BIT ? 8 : 16);
|
||||
print(env, ", polarity=%u, phase=%u, bits=%u", self->spi->Init.CLKPolarity == SPI_POLARITY_LOW ? 0 : 1, self->spi->Init.CLKPhase == SPI_PHASE_1EDGE ? 0 : 1, self->spi->Init.DataSize == SPI_DATASIZE_8BIT ? 8 : 16);
|
||||
if (self->spi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLED) {
|
||||
print(env, ", crc=0x%x", self->spi->Init.CRCPolynomial);
|
||||
}
|
||||
@@ -232,7 +232,7 @@ STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void *
|
||||
}
|
||||
}
|
||||
|
||||
/// \method init(mode, baudrate=328125, *, polarity=1, phase=1, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
|
||||
/// \method init(mode, baudrate=328125, *, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
|
||||
///
|
||||
/// Initialise the SPI bus with the given parameters:
|
||||
///
|
||||
@@ -242,7 +242,7 @@ STATIC const mp_arg_t pyb_spi_init_args[] = {
|
||||
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 328125} },
|
||||
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_dir, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_DIRECTION_2LINES} },
|
||||
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
|
||||
{ MP_QSTR_nss, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_NSS_SOFT} },
|
||||
@@ -282,7 +282,7 @@ STATIC mp_obj_t pyb_spi_init_helper(const pyb_spi_obj_t *self, mp_uint_t n_args,
|
||||
else { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; }
|
||||
|
||||
init->CLKPolarity = vals[2].u_int == 0 ? SPI_POLARITY_LOW : SPI_POLARITY_HIGH;
|
||||
init->CLKPhase = vals[3].u_int == 1 ? SPI_PHASE_1EDGE : SPI_PHASE_2EDGE;
|
||||
init->CLKPhase = vals[3].u_int == 0 ? SPI_PHASE_1EDGE : SPI_PHASE_2EDGE;
|
||||
init->Direction = vals[4].u_int;
|
||||
init->DataSize = (vals[5].u_int == 16) ? SPI_DATASIZE_16BIT : SPI_DATASIZE_8BIT;
|
||||
init->NSS = vals[6].u_int;
|
||||
@@ -387,8 +387,7 @@ STATIC mp_obj_t pyb_spi_send(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *k
|
||||
HAL_StatusTypeDef status = HAL_SPI_Transmit(self->spi, bufinfo.buf, bufinfo.len, vals[1].u_int);
|
||||
|
||||
if (status != HAL_OK) {
|
||||
// TODO really need a HardwareError object, or something
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_SPI_Transmit failed with code %d", status));
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
@@ -428,8 +427,7 @@ STATIC mp_obj_t pyb_spi_recv(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *k
|
||||
HAL_StatusTypeDef status = HAL_SPI_Receive(self->spi, bufinfo.buf, bufinfo.len, vals[1].u_int);
|
||||
|
||||
if (status != HAL_OK) {
|
||||
// TODO really need a HardwareError object, or something
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_SPI_Receive failed with code %d", status));
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
|
||||
// return the received data
|
||||
@@ -503,8 +501,7 @@ STATIC mp_obj_t pyb_spi_send_recv(mp_uint_t n_args, const mp_obj_t *args, mp_map
|
||||
HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(self->spi, bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len, vals[2].u_int);
|
||||
|
||||
if (status != HAL_OK) {
|
||||
// TODO really need a HardwareError object, or something
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_SPI_TransmitReceive failed with code %d", status));
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
|
||||
// return the received data
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm32f4xx_hal.h"
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
@@ -40,6 +38,7 @@
|
||||
#include "stream.h"
|
||||
#include "uart.h"
|
||||
#include "pybioctl.h"
|
||||
#include MICROPY_HAL_H
|
||||
|
||||
/// \moduleref pyb
|
||||
/// \class UART - duplex serial communication bus
|
||||
@@ -94,14 +93,6 @@ struct _pyb_uart_obj_t {
|
||||
byte *read_buf; // byte or uint16_t, depending on char size
|
||||
};
|
||||
|
||||
// this table converts from HAL_StatusTypeDef to POSIX errno
|
||||
STATIC const byte hal_status_to_errno_table[4] = {
|
||||
[HAL_OK] = 0,
|
||||
[HAL_ERROR] = EIO,
|
||||
[HAL_BUSY] = EBUSY,
|
||||
[HAL_TIMEOUT] = ETIMEDOUT,
|
||||
};
|
||||
|
||||
// pointers to all UART objects (if they have been created)
|
||||
STATIC pyb_uart_obj_t *pyb_uart_obj_all[6];
|
||||
|
||||
@@ -563,7 +554,7 @@ STATIC mp_obj_t pyb_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) {
|
||||
HAL_StatusTypeDef status = HAL_UART_Transmit(&self->uart, (uint8_t*)&data, 1, self->timeout);
|
||||
|
||||
if (status != HAL_OK) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, (mp_obj_t)(mp_uint_t)hal_status_to_errno_table[status]));
|
||||
mp_hal_raise(status);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
@@ -584,53 +575,6 @@ STATIC mp_obj_t pyb_uart_readchar(mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar);
|
||||
|
||||
/// \method readinto(buf, len=-1)
|
||||
///
|
||||
/// Read data on the bus:
|
||||
///
|
||||
/// - `buf` is a mutable buffer which will be filled with read characters.
|
||||
/// - `len` is the maximum number of characters to read; if negative, uses len(buf).
|
||||
///
|
||||
/// Return value: number of characters stored in buf.
|
||||
STATIC mp_obj_t pyb_uart_readinto(mp_uint_t n_args, const mp_obj_t *pos_args) {
|
||||
pyb_uart_obj_t *self = pos_args[0];
|
||||
|
||||
// get the buffer to read into
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(pos_args[1], &bufinfo, MP_BUFFER_WRITE);
|
||||
bufinfo.len >>= self->char_width;
|
||||
|
||||
// adjust the length, if given
|
||||
if (n_args == 3) {
|
||||
mp_int_t len = mp_obj_get_int(pos_args[2]);
|
||||
if (len >= 0 && len < bufinfo.len) {
|
||||
bufinfo.len = len;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure we want at least 1 char, and wait for it to become available
|
||||
if (bufinfo.len == 0 || !uart_rx_wait(self, self->timeout)) {
|
||||
return MP_OBJ_NEW_SMALL_INT(0);
|
||||
}
|
||||
|
||||
// read the chars
|
||||
byte *buf = bufinfo.buf;
|
||||
for (;;) {
|
||||
int data = uart_rx_char(self);
|
||||
if (self->char_width == CHAR_WIDTH_9BIT) {
|
||||
*(uint16_t*)buf = data;
|
||||
buf += 2;
|
||||
} else {
|
||||
*buf++ = data;
|
||||
}
|
||||
if (--bufinfo.len == 0 || !uart_rx_wait(self, self->timeout_char)) {
|
||||
// return the number of chars read
|
||||
return mp_obj_new_int((buf - (byte*)bufinfo.buf) >> self->char_width);
|
||||
}
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(pyb_uart_readinto_obj, 2, pyb_uart_readinto);
|
||||
|
||||
STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
|
||||
// instance methods
|
||||
|
||||
@@ -644,12 +588,13 @@ STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
|
||||
/// \method readline()
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
|
||||
/// \method readinto(buf[, nbytes])
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
|
||||
/// \method write(buf)
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_writechar), (mp_obj_t)&pyb_uart_writechar_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readchar), (mp_obj_t)&pyb_uart_readchar_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&pyb_uart_readinto_obj },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);
|
||||
@@ -713,7 +658,7 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t
|
||||
// return number of bytes written
|
||||
return size;
|
||||
} else {
|
||||
*errcode = hal_status_to_errno_table[status];
|
||||
*errcode = mp_hal_status_to_errno_table[status];
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ STATIC mp_obj_t mp_const_vcp_interrupt = MP_OBJ_NULL;
|
||||
|
||||
void pyb_usb_init0(void) {
|
||||
// create an exception object for interrupting by VCP
|
||||
mp_const_vcp_interrupt = mp_obj_new_exception_msg(&mp_type_OSError, "VCPInterrupt");
|
||||
mp_const_vcp_interrupt = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
|
||||
USBD_CDC_SetInterrupt(VCP_CHAR_NONE, mp_const_vcp_interrupt);
|
||||
}
|
||||
|
||||
@@ -58,10 +58,14 @@ void pyb_usb_dev_init(usb_device_mode_t mode, usb_storage_medium_t medium) {
|
||||
#ifdef USE_DEVICE_MODE
|
||||
if (!dev_is_enabled) {
|
||||
// only init USB once in the device's power-lifetime
|
||||
// Windows needs a different PID to distinguish different device
|
||||
// configurations, so we set it here depending on mode.
|
||||
if (mode == USB_DEVICE_MODE_CDC_MSC) {
|
||||
USBD_SelectMode(USBD_MODE_CDC_MSC);
|
||||
USBD_SetPID(0x9800);
|
||||
} else {
|
||||
USBD_SelectMode(USBD_MODE_CDC_HID);
|
||||
USBD_SetPID(0x9801);
|
||||
}
|
||||
USBD_Init(&hUSBDDevice, (USBD_DescriptorsTypeDef*)&VCP_Desc, 0);
|
||||
USBD_RegisterClass(&hUSBDDevice, &USBD_CDC_MSC_HID);
|
||||
|
||||
@@ -364,6 +364,8 @@ static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) {
|
||||
for (; src < buf_top; src++) {
|
||||
if (*src == user_interrupt_char) {
|
||||
char_found = true;
|
||||
// raise exception when interrupts are finished
|
||||
pendsv_nlr_jump(user_interrupt_data);
|
||||
} else {
|
||||
if (char_found) {
|
||||
*dest = *src;
|
||||
@@ -372,12 +374,6 @@ static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) {
|
||||
}
|
||||
}
|
||||
|
||||
if (char_found) {
|
||||
// raise exception when interrupts are finished
|
||||
user_interrupt_char = VCP_CHAR_NONE;
|
||||
pendsv_nlr_jump(user_interrupt_data);
|
||||
}
|
||||
|
||||
// length of remaining characters
|
||||
delta_len = dest - Buf;
|
||||
}
|
||||
|
||||
@@ -25,3 +25,5 @@
|
||||
*/
|
||||
|
||||
extern const USBD_DescriptorsTypeDef VCP_Desc;
|
||||
|
||||
void USBD_SetPID(uint16_t pid);
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
@@ -29,14 +29,10 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_desc.h"
|
||||
#include "usbd_conf.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
// So we don't clash with existing ST boards, we use the unofficial FOSS VID.
|
||||
// This needs a proper solution.
|
||||
#define USBD_VID 0xf055
|
||||
@@ -52,199 +48,144 @@
|
||||
#define USBD_CONFIGURATION_FS_STRING "VCP Config"
|
||||
#define USBD_INTERFACE_FS_STRING "VCP Interface"
|
||||
|
||||
/*
|
||||
#define USBD_VID 0x0483
|
||||
#define USBD_PID 0x5740
|
||||
#define USBD_LANGID_STRING 0x409
|
||||
#define USBD_MANUFACTURER_STRING "STMicroelectronics"
|
||||
#define USBD_PRODUCT_HS_STRING "STM32 Virtual ComPort in HS Mode"
|
||||
#define USBD_SERIALNUMBER_HS_STRING "00000000001A"
|
||||
#define USBD_PRODUCT_FS_STRING "STM32 Virtual ComPort in FS Mode"
|
||||
#define USBD_SERIALNUMBER_FS_STRING "00000000001B"
|
||||
#define USBD_CONFIGURATION_HS_STRING "VCP Config"
|
||||
#define USBD_INTERFACE_HS_STRING "VCP Interface"
|
||||
#define USBD_CONFIGURATION_FS_STRING "VCP Config"
|
||||
#define USBD_INTERFACE_FS_STRING "VCP Interface"
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
uint8_t *USBD_VCP_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
uint8_t *USBD_VCP_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
uint8_t *USBD_VCP_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
uint8_t *USBD_VCP_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
uint8_t *USBD_VCP_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
uint8_t *USBD_VCP_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
uint8_t *USBD_VCP_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
|
||||
#ifdef USB_SUPPORT_USER_STRING_DESC
|
||||
uint8_t *USBD_VCP_USRStringDesc (USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length);
|
||||
#endif /* USB_SUPPORT_USER_STRING_DESC */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
const USBD_DescriptorsTypeDef VCP_Desc = {
|
||||
USBD_VCP_DeviceDescriptor,
|
||||
USBD_VCP_LangIDStrDescriptor,
|
||||
USBD_VCP_ManufacturerStrDescriptor,
|
||||
USBD_VCP_ProductStrDescriptor,
|
||||
USBD_VCP_SerialStrDescriptor,
|
||||
USBD_VCP_ConfigStrDescriptor,
|
||||
USBD_VCP_InterfaceStrDescriptor,
|
||||
};
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
// USB Standard Device Descriptor
|
||||
__ALIGN_BEGIN static uint8_t hUSBDDeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
|
||||
0x12, /* bLength */
|
||||
USB_DESC_TYPE_DEVICE, /* bDescriptorType */
|
||||
0x00, /* bcdUSB */
|
||||
0x02,
|
||||
0x00, /* bDeviceClass */
|
||||
0x00, /* bDeviceSubClass */
|
||||
0x00, /* bDeviceProtocol */
|
||||
USB_MAX_EP0_SIZE, /* bMaxPacketSize */
|
||||
LOBYTE(USBD_VID), /* idVendor */
|
||||
HIBYTE(USBD_VID), /* idVendor */
|
||||
LOBYTE(USBD_PID), /* idVendor */
|
||||
HIBYTE(USBD_PID), /* idVendor */
|
||||
0x00, /* bcdDevice rel. 2.00 */
|
||||
0x02,
|
||||
USBD_IDX_MFC_STR, /* Index of manufacturer string */
|
||||
USBD_IDX_PRODUCT_STR, /* Index of product string */
|
||||
USBD_IDX_SERIAL_STR, /* Index of serial number string */
|
||||
USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
|
||||
}; /* USB_DeviceDescriptor */
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
__ALIGN_BEGIN static uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
|
||||
USB_LEN_LANGID_STR_DESC,
|
||||
USB_DESC_TYPE_STRING,
|
||||
LOBYTE(USBD_LANGID_STRING),
|
||||
HIBYTE(USBD_LANGID_STRING),
|
||||
0x12, // bLength
|
||||
USB_DESC_TYPE_DEVICE, // bDescriptorType
|
||||
0x00, // bcdUSB
|
||||
0x02,
|
||||
0x00, // bDeviceClass
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
USB_MAX_EP0_SIZE, // bMaxPacketSize
|
||||
LOBYTE(USBD_VID), // idVendor
|
||||
HIBYTE(USBD_VID), // idVendor
|
||||
LOBYTE(USBD_PID), // idVendor
|
||||
HIBYTE(USBD_PID), // idVendor
|
||||
0x00, // bcdDevice rel. 2.00
|
||||
0x02,
|
||||
USBD_IDX_MFC_STR, // Index of manufacturer string
|
||||
USBD_IDX_PRODUCT_STR, // Index of product string
|
||||
USBD_IDX_SERIAL_STR, // Index of serial number string
|
||||
USBD_MAX_NUM_CONFIGURATION // bNumConfigurations
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN static uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
|
||||
USB_LEN_LANGID_STR_DESC,
|
||||
USB_DESC_TYPE_STRING,
|
||||
LOBYTE(USBD_LANGID_STRING),
|
||||
HIBYTE(USBD_LANGID_STRING),
|
||||
};
|
||||
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
__ALIGN_BEGIN static uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
// set the PID
|
||||
void USBD_SetPID(uint16_t pid) {
|
||||
hUSBDDeviceDesc[10] = LOBYTE(pid);
|
||||
hUSBDDeviceDesc[11] = HIBYTE(pid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the device descriptor.
|
||||
* @brief Returns the device descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_VCP_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
*length = sizeof(hUSBDDeviceDesc);
|
||||
return hUSBDDeviceDesc;
|
||||
STATIC uint8_t *USBD_VCP_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) {
|
||||
*length = sizeof(hUSBDDeviceDesc);
|
||||
return hUSBDDeviceDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the LangID string descriptor.
|
||||
* @brief Returns the LangID string descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_VCP_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
*length = sizeof(USBD_LangIDDesc);
|
||||
return USBD_LangIDDesc;
|
||||
STATIC uint8_t *USBD_VCP_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) {
|
||||
*length = sizeof(USBD_LangIDDesc);
|
||||
return USBD_LangIDDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the product string descriptor.
|
||||
* @brief Returns the product string descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_VCP_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
if(speed == 0)
|
||||
{
|
||||
USBD_GetString((uint8_t *)USBD_PRODUCT_HS_STRING, USBD_StrDesc, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_GetString((uint8_t *)USBD_PRODUCT_FS_STRING, USBD_StrDesc, length);
|
||||
}
|
||||
return USBD_StrDesc;
|
||||
STATIC uint8_t *USBD_VCP_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) {
|
||||
if(speed == 0) {
|
||||
USBD_GetString((uint8_t *)USBD_PRODUCT_HS_STRING, USBD_StrDesc, length);
|
||||
} else {
|
||||
USBD_GetString((uint8_t *)USBD_PRODUCT_FS_STRING, USBD_StrDesc, length);
|
||||
}
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the manufacturer string descriptor.
|
||||
* @brief Returns the manufacturer string descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_VCP_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
STATIC uint8_t *USBD_VCP_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) {
|
||||
USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the serial number string descriptor.
|
||||
* @brief Returns the serial number string descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_VCP_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
if(speed == USBD_SPEED_HIGH)
|
||||
{
|
||||
USBD_GetString((uint8_t *)USBD_SERIALNUMBER_HS_STRING, USBD_StrDesc, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_GetString((uint8_t *)USBD_SERIALNUMBER_FS_STRING, USBD_StrDesc, length);
|
||||
}
|
||||
return USBD_StrDesc;
|
||||
STATIC uint8_t *USBD_VCP_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) {
|
||||
if(speed == USBD_SPEED_HIGH) {
|
||||
USBD_GetString((uint8_t *)USBD_SERIALNUMBER_HS_STRING, USBD_StrDesc, length);
|
||||
} else {
|
||||
USBD_GetString((uint8_t *)USBD_SERIALNUMBER_FS_STRING, USBD_StrDesc, length);
|
||||
}
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the configuration string descriptor.
|
||||
* @brief Returns the configuration string descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_VCP_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
if(speed == USBD_SPEED_HIGH)
|
||||
{
|
||||
USBD_GetString((uint8_t *)USBD_CONFIGURATION_HS_STRING, USBD_StrDesc, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_GetString((uint8_t *)USBD_CONFIGURATION_FS_STRING, USBD_StrDesc, length);
|
||||
}
|
||||
return USBD_StrDesc;
|
||||
STATIC uint8_t *USBD_VCP_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) {
|
||||
if(speed == USBD_SPEED_HIGH) {
|
||||
USBD_GetString((uint8_t *)USBD_CONFIGURATION_HS_STRING, USBD_StrDesc, length);
|
||||
} else {
|
||||
USBD_GetString((uint8_t *)USBD_CONFIGURATION_FS_STRING, USBD_StrDesc, length);
|
||||
}
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the interface string descriptor.
|
||||
* @brief Returns the interface string descriptor.
|
||||
* @param speed: Current device speed
|
||||
* @param length: Pointer to data length variable
|
||||
* @retval Pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t *USBD_VCP_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
|
||||
{
|
||||
if(speed == 0)
|
||||
{
|
||||
USBD_GetString((uint8_t *)USBD_INTERFACE_HS_STRING, USBD_StrDesc, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_GetString((uint8_t *)USBD_INTERFACE_FS_STRING, USBD_StrDesc, length);
|
||||
}
|
||||
return USBD_StrDesc;
|
||||
STATIC uint8_t *USBD_VCP_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) {
|
||||
if(speed == 0) {
|
||||
USBD_GetString((uint8_t *)USBD_INTERFACE_HS_STRING, USBD_StrDesc, length);
|
||||
} else {
|
||||
USBD_GetString((uint8_t *)USBD_INTERFACE_FS_STRING, USBD_StrDesc, length);
|
||||
}
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
const USBD_DescriptorsTypeDef VCP_Desc = {
|
||||
USBD_VCP_DeviceDescriptor,
|
||||
USBD_VCP_LangIDStrDescriptor,
|
||||
USBD_VCP_ManufacturerStrDescriptor,
|
||||
USBD_VCP_ProductStrDescriptor,
|
||||
USBD_VCP_SerialStrDescriptor,
|
||||
USBD_VCP_ConfigStrDescriptor,
|
||||
USBD_VCP_InterfaceStrDescriptor,
|
||||
};
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
|
||||
@@ -92,9 +92,9 @@ __ALIGN_BEGIN static uint8_t USBD_CDC_MSC_CfgDesc[USB_CDC_MSC_CONFIG_DESC_SIZ] _
|
||||
USB_DESC_TYPE_ASSOCIATION, // bDescriptorType: IAD
|
||||
CDC_IFACE_NUM, // bFirstInterface: first interface for this association
|
||||
0x02, // bInterfaceCount: nummber of interfaces for this association
|
||||
0x00, // bFunctionClass: ?
|
||||
0x00, // bFunctionSubClass: ?
|
||||
0x00, // bFunctionProtocol: ?
|
||||
0x02, // bFunctionClass: Communication Interface Class
|
||||
0x02, // bFunctionSubClass: Abstract Control Model
|
||||
0x01, // bFunctionProtocol: Common AT commands
|
||||
0x00, // iFunction: index of string for this function
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -229,9 +229,9 @@ __ALIGN_BEGIN static uint8_t USBD_CDC_HID_CfgDesc[USB_CDC_HID_CONFIG_DESC_SIZ] _
|
||||
USB_DESC_TYPE_ASSOCIATION, // bDescriptorType: IAD
|
||||
CDC_IFACE_NUM, // bFirstInterface: first interface for this association
|
||||
0x02, // bInterfaceCount: nummber of interfaces for this association
|
||||
0x00, // bFunctionClass: ?
|
||||
0x00, // bFunctionSubClass: ?
|
||||
0x00, // bFunctionProtocol: ?
|
||||
0x02, // bFunctionClass: Communication Interface Class
|
||||
0x02, // bFunctionSubClass: Abstract Control Model
|
||||
0x01, // bFunctionProtocol: Common AT commands
|
||||
0x00, // iFunction: index of string for this function
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -324,7 +324,7 @@ __ALIGN_BEGIN static uint8_t USBD_CDC_HID_CfgDesc[USB_CDC_HID_CONFIG_DESC_SIZ] _
|
||||
0x01, // bNumEndpoints
|
||||
0x03, // bInterfaceClass: HID Class
|
||||
0x01, // bInterfaceSubClass: 1=BOOT, 0=no boot
|
||||
0x01, // nInterfaceProtocol: 0=none, 1=keyboard, 2=mouse
|
||||
0x02, // nInterfaceProtocol: 0=none, 1=keyboard, 2=mouse
|
||||
0x00, // iInterface:
|
||||
|
||||
// HID descriptor
|
||||
|
||||
29
tests/basics/builtin_compile.py
Normal file
29
tests/basics/builtin_compile.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# test compile builtin
|
||||
|
||||
def have_compile():
|
||||
try:
|
||||
compile
|
||||
return True
|
||||
except NameError:
|
||||
return False
|
||||
|
||||
# global variable for compiled code to access
|
||||
x = 1
|
||||
|
||||
def test():
|
||||
c = compile("print(x)", "file", "exec")
|
||||
|
||||
try:
|
||||
exec(c)
|
||||
except NameError:
|
||||
print("NameError")
|
||||
|
||||
exec(c)
|
||||
|
||||
exec(c, {"x":2})
|
||||
exec(c, {}, {"x":3})
|
||||
|
||||
if have_compile():
|
||||
test()
|
||||
else:
|
||||
print("SKIP")
|
||||
@@ -298,15 +298,15 @@ except SyntaxError:
|
||||
#except SyntaxWarning:
|
||||
# print("Caught SyntaxWarning")
|
||||
|
||||
try:
|
||||
raise SystemError
|
||||
except Exception:
|
||||
print("Caught SystemError via Exception")
|
||||
#try:
|
||||
# raise SystemError
|
||||
#except Exception:
|
||||
# print("Caught SystemError via Exception")
|
||||
|
||||
try:
|
||||
raise SystemError
|
||||
except SystemError:
|
||||
print("Caught SystemError")
|
||||
#try:
|
||||
# raise SystemError
|
||||
#except SystemError:
|
||||
# print("Caught SystemError")
|
||||
|
||||
#try:
|
||||
# raise TabError
|
||||
|
||||
21
tests/basics/int_divmod.py
Normal file
21
tests/basics/int_divmod.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# test integer floor division and modulo
|
||||
|
||||
# test all combination of +/-/0 cases
|
||||
for i in range(-2, 3):
|
||||
for j in range(-4, 5):
|
||||
if j != 0:
|
||||
print(i, j, i // j, i % j, divmod(i, j))
|
||||
|
||||
# this tests compiler constant folding
|
||||
print(123 // 7, 123 % 7)
|
||||
print(-123 // 7, -123 % 7)
|
||||
print(123 // -7, 123 % -7)
|
||||
print(-123 // -7, -123 % -7)
|
||||
|
||||
# this tests bignum modulo
|
||||
a = 987654321987987987987987987987
|
||||
b = 19
|
||||
print(a % b)
|
||||
print(a % -b)
|
||||
print(-a % b)
|
||||
print(-a % -b)
|
||||
34
tests/basics/memoryview1.py
Normal file
34
tests/basics/memoryview1.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# test memoryview
|
||||
|
||||
# test reading from bytes
|
||||
b = b'1234'
|
||||
m = memoryview(b)
|
||||
print(len(m))
|
||||
print(m[0], m[1], m[-1])
|
||||
print(list(m))
|
||||
|
||||
# test writing to bytes
|
||||
try:
|
||||
m[0] = 1
|
||||
except TypeError:
|
||||
print("TypeError")
|
||||
|
||||
# test writing to bytearray
|
||||
b = bytearray(b)
|
||||
m = memoryview(b)
|
||||
m[0] = 1
|
||||
print(b)
|
||||
print(list(m))
|
||||
|
||||
# test slice
|
||||
m = memoryview(b'1234')
|
||||
print(list(m[1:]))
|
||||
print(list(m[1:-1]))
|
||||
|
||||
import array
|
||||
a = array.array('i', [1, 2, 3, 4])
|
||||
m = memoryview(a)
|
||||
print(list(m))
|
||||
print(list(m[1:-1]))
|
||||
m[2] = 6
|
||||
print(a)
|
||||
18
tests/basics/memoryview_gc.py
Normal file
18
tests/basics/memoryview_gc.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# test memoryview retains pointer to original object/buffer
|
||||
|
||||
b = bytearray(10)
|
||||
m = memoryview(b)[1:]
|
||||
for i in range(len(m)):
|
||||
m[i] = i
|
||||
|
||||
# reclaim b, but hopefully not the buffer
|
||||
b = None
|
||||
import gc
|
||||
gc.collect()
|
||||
|
||||
# allocate lots of memory
|
||||
for i in range(100000):
|
||||
[42, 42, 42, 42]
|
||||
|
||||
# check that the memoryview is still what we want
|
||||
print(list(m))
|
||||
@@ -1,23 +0,0 @@
|
||||
# check modulo matches python definition
|
||||
|
||||
# this tests compiler constant folding
|
||||
print(123 % 7)
|
||||
print(-123 % 7)
|
||||
print(123 % -7)
|
||||
print(-123 % -7)
|
||||
|
||||
a = 321
|
||||
b = 19
|
||||
print(a % b)
|
||||
print(a % -b)
|
||||
print(-a % b)
|
||||
print(-a % -b)
|
||||
|
||||
|
||||
a = 987654321987987987987987987987
|
||||
b = 19
|
||||
|
||||
print(a % b)
|
||||
print(a % -b)
|
||||
print(-a % b)
|
||||
print(-a % -b)
|
||||
36
tests/extmod/uheapq1.py
Normal file
36
tests/extmod/uheapq1.py
Normal file
@@ -0,0 +1,36 @@
|
||||
try:
|
||||
import uheapq as heapq
|
||||
except:
|
||||
import heapq
|
||||
|
||||
try:
|
||||
heapq.heappop([])
|
||||
except IndexError:
|
||||
print("IndexError")
|
||||
|
||||
try:
|
||||
heapq.heappush((), 1)
|
||||
except TypeError:
|
||||
print("TypeError")
|
||||
|
||||
def pop_and_print(h):
|
||||
l = []
|
||||
while h:
|
||||
l.append(str(heapq.heappop(h)))
|
||||
print(' '.join(l))
|
||||
|
||||
h = []
|
||||
heapq.heappush(h, 3)
|
||||
heapq.heappush(h, 1)
|
||||
heapq.heappush(h, 2)
|
||||
print(h)
|
||||
pop_and_print(h)
|
||||
|
||||
h = [4, 3, 8, 9, 10, 2, 7, 11, 5]
|
||||
heapq.heapify(h)
|
||||
print(h)
|
||||
heapq.heappush(h, 1)
|
||||
heapq.heappush(h, 6)
|
||||
heapq.heappush(h, 12)
|
||||
print(h)
|
||||
pop_and_print(h)
|
||||
10
tests/io/file_readinto_len.py
Normal file
10
tests/io/file_readinto_len.py
Normal file
@@ -0,0 +1,10 @@
|
||||
b = bytearray(30)
|
||||
f = open("io/data/file1", "rb")
|
||||
# 2nd arg (length to read) is extension to CPython
|
||||
print(f.readinto(b, 8))
|
||||
print(b)
|
||||
|
||||
b = bytearray(4)
|
||||
f = open("io/data/file1", "rb")
|
||||
print(f.readinto(b, 8))
|
||||
print(b)
|
||||
4
tests/io/file_readinto_len.py.exp
Normal file
4
tests/io/file_readinto_len.py.exp
Normal file
@@ -0,0 +1,4 @@
|
||||
8
|
||||
bytearray(b'longer l\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
4
|
||||
bytearray(b'long')
|
||||
@@ -69,10 +69,10 @@ print(sorted(list(viper_set(1, 2))))
|
||||
# raising an exception
|
||||
@micropython.viper
|
||||
def viper_raise(x:int):
|
||||
raise SystemError(x)
|
||||
raise OSError(x)
|
||||
try:
|
||||
viper_raise(1)
|
||||
except SystemError as e:
|
||||
except OSError as e:
|
||||
print(repr(e))
|
||||
|
||||
# this doesn't work at the moment
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
(1, 3)
|
||||
[1, 3]
|
||||
[1, 3]
|
||||
SystemError(1,)
|
||||
OSError(1,)
|
||||
1
|
||||
1
|
||||
|
||||
@@ -5,10 +5,10 @@ print(spi)
|
||||
|
||||
spi = SPI(1, SPI.MASTER)
|
||||
spi = SPI(1, SPI.MASTER, baudrate=500000)
|
||||
spi = SPI(1, SPI.MASTER, 500000, polarity=1, phase=1, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
|
||||
spi = SPI(1, SPI.MASTER, 500000, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
|
||||
print(spi)
|
||||
|
||||
spi.init(SPI.SLAVE)
|
||||
spi.init(SPI.SLAVE, phase=1)
|
||||
print(spi)
|
||||
|
||||
spi.init(SPI.MASTER)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
SPI(1)
|
||||
SPI(1, SPI.MASTER, baudrate=328125, polarity=1, phase=1, bits=8)
|
||||
SPI(1, SPI.MASTER, baudrate=328125, polarity=1, phase=0, bits=8)
|
||||
SPI(1, SPI.SLAVE, polarity=1, phase=1, bits=8)
|
||||
b'\xff'
|
||||
b'\xff'
|
||||
|
||||
123
tools/pyboard.py
Normal file → Executable file
123
tools/pyboard.py
Normal file → Executable file
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
pyboard interface
|
||||
|
||||
@@ -19,10 +21,15 @@ To run a script from the local machine on the board and print out the results:
|
||||
|
||||
This script can also be run directly. To execute a local script, use:
|
||||
|
||||
./pyboard.py test.py
|
||||
|
||||
Or:
|
||||
|
||||
python pyboard.py test.py
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import time
|
||||
import serial
|
||||
|
||||
@@ -31,21 +38,26 @@ class PyboardError(BaseException):
|
||||
|
||||
class Pyboard:
|
||||
def __init__(self, serial_device):
|
||||
self.serial = serial.Serial(serial_device)
|
||||
self.serial = serial.Serial(serial_device, baudrate=115200, interCharTimeout=1)
|
||||
|
||||
def close(self):
|
||||
self.serial.close()
|
||||
|
||||
def read_until(self, min_num_bytes, ending, timeout=10):
|
||||
def read_until(self, min_num_bytes, ending, timeout=10, data_consumer=None):
|
||||
data = self.serial.read(min_num_bytes)
|
||||
if data_consumer:
|
||||
data_consumer(data)
|
||||
timeout_count = 0
|
||||
while True:
|
||||
if self.serial.inWaiting() > 0:
|
||||
data = data + self.serial.read(self.serial.inWaiting())
|
||||
time.sleep(0.01)
|
||||
timeout_count = 0
|
||||
elif data.endswith(ending):
|
||||
if data.endswith(ending):
|
||||
break
|
||||
elif self.serial.inWaiting() > 0:
|
||||
new_data = self.serial.read(1)
|
||||
data = data + new_data
|
||||
if data_consumer:
|
||||
data_consumer(new_data)
|
||||
#time.sleep(0.01)
|
||||
timeout_count = 0
|
||||
else:
|
||||
timeout_count += 1
|
||||
if timeout_count >= 10 * timeout:
|
||||
@@ -54,8 +66,12 @@ class Pyboard:
|
||||
return data
|
||||
|
||||
def enter_raw_repl(self):
|
||||
self.serial.write(b'\r\x03') # ctrl-C: interrupt any running program
|
||||
self.serial.write(b'\r\x03\x03') # ctrl-C twice: interrupt any running program
|
||||
self.serial.write(b'\r\x01') # ctrl-A: enter raw REPL
|
||||
data = self.read_until(1, b'to exit\r\n>')
|
||||
if not data.endswith(b'raw REPL; CTRL-B to exit\r\n>'):
|
||||
print(data)
|
||||
raise PyboardError('could not enter raw repl')
|
||||
self.serial.write(b'\x04') # ctrl-D: soft reset
|
||||
data = self.read_until(1, b'to exit\r\n>')
|
||||
if not data.endswith(b'raw REPL; CTRL-B to exit\r\n>'):
|
||||
@@ -65,31 +81,51 @@ class Pyboard:
|
||||
def exit_raw_repl(self):
|
||||
self.serial.write(b'\r\x02') # ctrl-B: enter friendly REPL
|
||||
|
||||
def follow(self, data_consumer=False):
|
||||
# wait for normal output
|
||||
data = self.read_until(1, b'\x04', data_consumer=data_consumer)
|
||||
if not data.endswith(b'\x04'):
|
||||
raise PyboardError('timeout waiting for first EOF reception')
|
||||
data = data[:-1]
|
||||
|
||||
# wait for error output
|
||||
data_err = self.read_until(2, b'\x04>')
|
||||
if not data_err.endswith(b'\x04>'):
|
||||
raise PyboardError('timeout waiting for second EOF reception')
|
||||
data_err = data_err[:-2]
|
||||
|
||||
# return normal and error output
|
||||
return data, data_err
|
||||
|
||||
def exec_raw(self, command, data_consumer=False):
|
||||
if isinstance(command, bytes):
|
||||
command_bytes = command
|
||||
else:
|
||||
command_bytes = bytes(command, encoding='ascii')
|
||||
|
||||
# write command
|
||||
for i in range(0, len(command_bytes), 32):
|
||||
self.serial.write(command_bytes[i:min(i+32, len(command_bytes))])
|
||||
time.sleep(0.01)
|
||||
self.serial.write(b'\x04')
|
||||
|
||||
# check if we could exec command
|
||||
data = self.serial.read(2)
|
||||
if data != b'OK':
|
||||
raise PyboardError('could not exec command')
|
||||
|
||||
return self.follow(data_consumer)
|
||||
|
||||
def eval(self, expression):
|
||||
ret = self.exec('print({})'.format(expression))
|
||||
ret = ret.strip()
|
||||
return ret
|
||||
|
||||
def exec(self, command):
|
||||
if isinstance(command, bytes):
|
||||
command_bytes = command
|
||||
else:
|
||||
command_bytes = bytes(command, encoding='ascii')
|
||||
for i in range(0, len(command_bytes), 32):
|
||||
self.serial.write(command_bytes[i:min(i+32, len(command_bytes))])
|
||||
time.sleep(0.01)
|
||||
self.serial.write(b'\x04')
|
||||
data = self.serial.read(2)
|
||||
if data != b'OK':
|
||||
raise PyboardError('could not exec command')
|
||||
data = self.read_until(2, b'\x04>')
|
||||
if not data.endswith(b'\x04>'):
|
||||
print(data)
|
||||
raise PyboardError('timeout waiting for EOF reception')
|
||||
if data.startswith(b'Traceback') or data.startswith(b' File '):
|
||||
print(data)
|
||||
raise PyboardError('command failed')
|
||||
return data[:-2]
|
||||
ret, ret_err = self.exec_raw(command)
|
||||
if ret_err:
|
||||
raise PyboardError('exception', ret, ret_err)
|
||||
return ret
|
||||
|
||||
def execfile(self, filename):
|
||||
with open(filename) as f:
|
||||
@@ -175,8 +211,37 @@ def main():
|
||||
if args.test:
|
||||
run_test(device=args.device)
|
||||
|
||||
for file in args.files:
|
||||
execfile(file, device=args.device)
|
||||
if len(args.files) == 0:
|
||||
try:
|
||||
pyb = Pyboard(args.device)
|
||||
ret, ret_err = pyb.follow(data_consumer=lambda d:print(str(d, encoding='ascii'), end=''))
|
||||
pyb.close()
|
||||
except PyboardError as er:
|
||||
print(er)
|
||||
sys.exit(1)
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(1)
|
||||
if ret_err:
|
||||
print(str(ret_err, encoding='ascii'), end='')
|
||||
sys.exit(1)
|
||||
|
||||
for filename in args.files:
|
||||
try:
|
||||
pyb = Pyboard(args.device)
|
||||
pyb.enter_raw_repl()
|
||||
with open(filename) as f:
|
||||
pyfile = f.read()
|
||||
ret, ret_err = pyb.exec_raw(pyfile, data_consumer=lambda d:print(str(d, encoding='ascii'), end=''))
|
||||
pyb.exit_raw_repl()
|
||||
pyb.close()
|
||||
except PyboardError as er:
|
||||
print(er)
|
||||
sys.exit(1)
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(1)
|
||||
if ret_err:
|
||||
print(str(ret_err, encoding='ascii'), end='')
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
531
tools/pydfu.py
Executable file
531
tools/pydfu.py
Executable file
@@ -0,0 +1,531 @@
|
||||
#!/usr/bin/env python
|
||||
# This file is part of the OpenMV project.
|
||||
# Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
|
||||
# This work is licensed under the MIT license, see the file LICENSE for
|
||||
# details.
|
||||
|
||||
"""This module implements enough functionality to program the STM32F4xx over
|
||||
DFU, without requiringdfu-util.
|
||||
|
||||
See app note AN3156 for a description of the DFU protocol.
|
||||
See document UM0391 for a dscription of the DFuse file.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import re
|
||||
import struct
|
||||
import sys
|
||||
import usb.core
|
||||
import usb.util
|
||||
import zlib
|
||||
|
||||
# VID/PID
|
||||
__VID = 0x0483
|
||||
__PID = 0xdf11
|
||||
|
||||
# USB request __TIMEOUT
|
||||
__TIMEOUT = 4000
|
||||
|
||||
# DFU commands
|
||||
__DFU_DETACH = 0
|
||||
__DFU_DNLOAD = 1
|
||||
__DFU_UPLOAD = 2
|
||||
__DFU_GETSTATUS = 3
|
||||
__DFU_CLRSTATUS = 4
|
||||
__DFU_GETSTATE = 5
|
||||
__DFU_ABORT = 6
|
||||
|
||||
# DFU status
|
||||
__DFU_STATE_APP_IDLE = 0x00
|
||||
__DFU_STATE_APP_DETACH = 0x01
|
||||
__DFU_STATE_DFU_IDLE = 0x02
|
||||
__DFU_STATE_DFU_DOWNLOAD_SYNC = 0x03
|
||||
__DFU_STATE_DFU_DOWNLOAD_BUSY = 0x04
|
||||
__DFU_STATE_DFU_DOWNLOAD_IDLE = 0x05
|
||||
__DFU_STATE_DFU_MANIFEST_SYNC = 0x06
|
||||
__DFU_STATE_DFU_MANIFEST = 0x07
|
||||
__DFU_STATE_DFU_MANIFEST_WAIT_RESET = 0x08
|
||||
__DFU_STATE_DFU_UPLOAD_IDLE = 0x09
|
||||
__DFU_STATE_DFU_ERROR = 0x0a
|
||||
|
||||
_DFU_DESCRIPTOR_TYPE = 0x21
|
||||
|
||||
|
||||
# USB device handle
|
||||
__dev = None
|
||||
|
||||
__verbose = None
|
||||
|
||||
# USB DFU interface
|
||||
__DFU_INTERFACE = 0
|
||||
|
||||
|
||||
def init():
|
||||
"""Initializes the found DFU device so that we can program it."""
|
||||
global __dev
|
||||
devices = get_dfu_devices(idVendor=__VID, idProduct=__PID)
|
||||
if not devices:
|
||||
raise ValueError('No DFU device found')
|
||||
if len(devices) > 1:
|
||||
raise ValueError("Multiple DFU devices found")
|
||||
__dev = devices[0]
|
||||
|
||||
# Claim DFU interface
|
||||
usb.util.claim_interface(__dev, __DFU_INTERFACE)
|
||||
|
||||
# Clear status
|
||||
clr_status()
|
||||
|
||||
|
||||
def clr_status():
|
||||
"""Clears any error status (perhaps left over from a previous session)."""
|
||||
__dev.ctrl_transfer(0x21, __DFU_CLRSTATUS, 0, __DFU_INTERFACE,
|
||||
None, __TIMEOUT)
|
||||
|
||||
|
||||
def get_status():
|
||||
"""Get the status of the last operation."""
|
||||
stat = __dev.ctrl_transfer(0xA1, __DFU_GETSTATUS, 0, __DFU_INTERFACE,
|
||||
6, 20000)
|
||||
# print (__DFU_STAT[stat[4]], stat)
|
||||
return stat[4]
|
||||
|
||||
|
||||
def mass_erase():
|
||||
"""Performs a MASS erase (i.e. erases the entire device."""
|
||||
# Send DNLOAD with first byte=0x41
|
||||
__dev.ctrl_transfer(0x21, __DFU_DNLOAD, 0, __DFU_INTERFACE,
|
||||
"\x41", __TIMEOUT)
|
||||
|
||||
# Execute last command
|
||||
if get_status() != __DFU_STATE_DFU_DOWNLOAD_BUSY:
|
||||
raise Exception("DFU: erase failed")
|
||||
|
||||
# Check command state
|
||||
if get_status() != __DFU_STATE_DFU_DOWNLOAD_IDLE:
|
||||
raise Exception("DFU: erase failed")
|
||||
|
||||
|
||||
def page_erase(addr):
|
||||
"""Erases a single page."""
|
||||
if __verbose:
|
||||
print("Erasing page: 0x%x..." % (addr))
|
||||
|
||||
# Send DNLOAD with first byte=0x41 and page address
|
||||
buf = struct.pack("<BI", 0x41, addr)
|
||||
__dev.ctrl_transfer(0x21, __DFU_DNLOAD, 0, __DFU_INTERFACE, buf, __TIMEOUT)
|
||||
|
||||
# Execute last command
|
||||
if get_status() != __DFU_STATE_DFU_DOWNLOAD_BUSY:
|
||||
raise Exception("DFU: erase failed")
|
||||
|
||||
# Check command state
|
||||
if get_status() != __DFU_STATE_DFU_DOWNLOAD_IDLE:
|
||||
|
||||
raise Exception("DFU: erase failed")
|
||||
|
||||
|
||||
def set_address(addr):
|
||||
"""Sets the address for the next operation."""
|
||||
# Send DNLOAD with first byte=0x21 and page address
|
||||
buf = struct.pack("<BI", 0x21, addr)
|
||||
__dev.ctrl_transfer(0x21, __DFU_DNLOAD, 0, __DFU_INTERFACE, buf, __TIMEOUT)
|
||||
|
||||
# Execute last command
|
||||
if get_status() != __DFU_STATE_DFU_DOWNLOAD_BUSY:
|
||||
raise Exception("DFU: set address failed")
|
||||
|
||||
# Check command state
|
||||
if get_status() != __DFU_STATE_DFU_DOWNLOAD_IDLE:
|
||||
raise Exception("DFU: set address failed")
|
||||
|
||||
|
||||
def write_memory(addr, buf, progress=None, progress_addr=0, progress_size=0):
|
||||
"""Writes a buffer into memory. This routine assumes that memory has
|
||||
already been erased.
|
||||
"""
|
||||
|
||||
xfer_count = 0
|
||||
xfer_bytes = 0
|
||||
xfer_total = len(buf)
|
||||
xfer_base = addr
|
||||
|
||||
while xfer_bytes < xfer_total:
|
||||
if __verbose and xfer_count % 512 == 0:
|
||||
print ("Addr 0x%x %dKBs/%dKBs..." % (xfer_base + xfer_bytes,
|
||||
xfer_bytes // 1024,
|
||||
xfer_total // 1024))
|
||||
if progress and xfer_count % 256 == 0:
|
||||
progress(progress_addr, xfer_base + xfer_bytes - progress_addr,
|
||||
progress_size)
|
||||
|
||||
# Set mem write address
|
||||
set_address(xfer_base+xfer_bytes)
|
||||
|
||||
# Send DNLOAD with fw data
|
||||
chunk = min(64, xfer_total-xfer_bytes)
|
||||
__dev.ctrl_transfer(0x21, __DFU_DNLOAD, 2, __DFU_INTERFACE,
|
||||
buf[xfer_bytes:xfer_bytes + chunk], __TIMEOUT)
|
||||
|
||||
# Execute last command
|
||||
if get_status() != __DFU_STATE_DFU_DOWNLOAD_BUSY:
|
||||
raise Exception("DFU: write memory failed")
|
||||
|
||||
# Check command state
|
||||
if get_status() != __DFU_STATE_DFU_DOWNLOAD_IDLE:
|
||||
raise Exception("DFU: write memory failed")
|
||||
|
||||
xfer_count += 1
|
||||
xfer_bytes += chunk
|
||||
|
||||
|
||||
def write_page(buf, xfer_offset):
|
||||
"""Writes a single page. This routine assumes that memory has already
|
||||
been erased.
|
||||
"""
|
||||
|
||||
xfer_base = 0x08000000
|
||||
|
||||
# Set mem write address
|
||||
set_address(xfer_base+xfer_offset)
|
||||
|
||||
# Send DNLOAD with fw data
|
||||
__dev.ctrl_transfer(0x21, __DFU_DNLOAD, 2, __DFU_INTERFACE, buf, __TIMEOUT)
|
||||
|
||||
# Execute last command
|
||||
if get_status() != __DFU_STATE_DFU_DOWNLOAD_BUSY:
|
||||
raise Exception("DFU: write memory failed")
|
||||
|
||||
# Check command state
|
||||
if get_status() != __DFU_STATE_DFU_DOWNLOAD_IDLE:
|
||||
raise Exception("DFU: write memory failed")
|
||||
|
||||
if __verbose:
|
||||
print ("Write: 0x%x " % (xfer_base + xfer_offset))
|
||||
|
||||
|
||||
def exit_dfu():
|
||||
"""Exit DFU mode, and start running the program."""
|
||||
|
||||
# set jump address
|
||||
set_address(0x08000000)
|
||||
|
||||
# Send DNLOAD with 0 length to exit DFU
|
||||
__dev.ctrl_transfer(0x21, __DFU_DNLOAD, 0, __DFU_INTERFACE,
|
||||
None, __TIMEOUT)
|
||||
|
||||
# Execute last command
|
||||
if get_status() != __DFU_STATE_DFU_MANIFEST:
|
||||
print("Failed to reset device")
|
||||
|
||||
# Release device
|
||||
usb.util.dispose_resources(__dev)
|
||||
|
||||
|
||||
def named(values, names):
|
||||
"""Creates a dict with `names` as fields, and `values` as values."""
|
||||
return dict(zip(names.split(), values))
|
||||
|
||||
|
||||
def consume(fmt, data, names):
|
||||
"""Parses the struct defined by `fmt` from `data`, stores the parsed fields
|
||||
into a named tuple using `names`. Returns the named tuple, and the data
|
||||
with the struct stripped off."""
|
||||
size = struct.calcsize(fmt)
|
||||
return named(struct.unpack(fmt, data[:size]), names), data[size:]
|
||||
|
||||
|
||||
def cstring(string):
|
||||
"""Extracts a null-terminated string from a byte array."""
|
||||
return string.split(b'\0', 1)[0]
|
||||
|
||||
|
||||
def compute_crc(data):
|
||||
"""Computes the CRC32 value for the data passed in."""
|
||||
return 0xFFFFFFFF & -zlib.crc32(data) - 1
|
||||
|
||||
|
||||
def read_dfu_file(filename):
|
||||
"""Reads a DFU file, and parses the individual elements from the file.
|
||||
Returns an array of elements. Each element is a dictionary with the
|
||||
following keys:
|
||||
num - The element index
|
||||
address - The address that the element data should be written to.
|
||||
size - The size of the element ddata.
|
||||
data - The element data.
|
||||
If an error occurs while parsing the file, then None is returned.
|
||||
"""
|
||||
|
||||
print("File: {}".format(filename))
|
||||
with open(filename, 'rb') as fin:
|
||||
data = fin.read()
|
||||
crc = compute_crc(data[:-4])
|
||||
elements = []
|
||||
|
||||
# Decode the DFU Prefix
|
||||
#
|
||||
# <5sBIB
|
||||
# < little endian
|
||||
# 5s char[5] signature "DfuSe"
|
||||
# B uint8_t version 1
|
||||
# I uint32_t size Size of the DFU file (not including suffix)
|
||||
# B uint8_t targets Number of targets
|
||||
dfu_prefix, data = consume('<5sBIB', data,
|
||||
'signature version size targets')
|
||||
print (" %(signature)s v%(version)d, image size: %(size)d, "
|
||||
"targets: %(targets)d" % dfu_prefix)
|
||||
for target_idx in range(dfu_prefix['targets']):
|
||||
# Decode the Image Prefix
|
||||
#
|
||||
# <6sBI255s2I
|
||||
# < little endian
|
||||
# 6s char[6] signature "Target"
|
||||
# B uint8_t altsetting
|
||||
# I uint32_t named bool indicating if a name was used
|
||||
# 255s char[255] name name of the target
|
||||
# I uint32_t size size of image (not incl prefix)
|
||||
# I uint32_t elements Number of elements in the image
|
||||
img_prefix, data = consume('<6sBI255s2I', data,
|
||||
'signature altsetting named name '
|
||||
'size elements')
|
||||
img_prefix['num'] = target_idx
|
||||
if img_prefix['named']:
|
||||
img_prefix['name'] = cstring(img_prefix['name'])
|
||||
else:
|
||||
img_prefix['name'] = ''
|
||||
print(' %(signature)s %(num)d, alt setting: %(altsetting)s, '
|
||||
'name: "%(name)s", size: %(size)d, elements: %(elements)d'
|
||||
% img_prefix)
|
||||
|
||||
target_size = img_prefix['size']
|
||||
target_data, data = data[:target_size], data[target_size:]
|
||||
for elem_idx in range(img_prefix['elements']):
|
||||
# Decode target prefix
|
||||
# < little endian
|
||||
# I uint32_t element address
|
||||
# I uint32_t element size
|
||||
elem_prefix, target_data = consume('<2I', target_data, 'addr size')
|
||||
elem_prefix['num'] = elem_idx
|
||||
print(' %(num)d, address: 0x%(addr)08x, size: %(size)d'
|
||||
% elem_prefix)
|
||||
elem_size = elem_prefix['size']
|
||||
elem_data = target_data[:elem_size]
|
||||
target_data = target_data[elem_size:]
|
||||
elem_prefix['data'] = elem_data
|
||||
elements.append(elem_prefix)
|
||||
|
||||
if len(target_data):
|
||||
print("target %d PARSE ERROR" % target_idx)
|
||||
|
||||
# Decode DFU Suffix
|
||||
# < little endian
|
||||
# H uint16_t device Firmware version
|
||||
# H uint16_t product
|
||||
# H uint16_t vendor
|
||||
# H uint16_t dfu 0x11a (DFU file format version)
|
||||
# 3s char[3] ufd 'UFD'
|
||||
# B uint8_t len 16
|
||||
# I uint32_t crc32
|
||||
dfu_suffix = named(struct.unpack('<4H3sBI', data[:16]),
|
||||
'device product vendor dfu ufd len crc')
|
||||
print (' usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, '
|
||||
'dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % dfu_suffix)
|
||||
if crc != dfu_suffix['crc']:
|
||||
print("CRC ERROR: computed crc32 is 0x%08x" % crc)
|
||||
return
|
||||
data = data[16:]
|
||||
if data:
|
||||
print("PARSE ERROR")
|
||||
return
|
||||
|
||||
return elements
|
||||
|
||||
|
||||
class FilterDFU(object):
|
||||
"""Class for filtering USB devices to identify devices which are in DFU
|
||||
mode.
|
||||
"""
|
||||
|
||||
def __call__(self, device):
|
||||
for cfg in device:
|
||||
for intf in cfg:
|
||||
return (intf.bInterfaceClass == 0xFE and
|
||||
intf.bInterfaceSubClass == 1)
|
||||
|
||||
|
||||
def get_dfu_devices(*args, **kwargs):
|
||||
"""Returns a list of USB device which are currently in DFU mode.
|
||||
Additional filters (like idProduct and idVendor) can be passed in to
|
||||
refine the search.
|
||||
"""
|
||||
|
||||
return list(usb.core.find(*args, find_all=True,
|
||||
custom_match=FilterDFU(), **kwargs))
|
||||
|
||||
|
||||
def get_memory_layout(device):
|
||||
"""Returns an array which identifies the memory layout. Each entry
|
||||
of the array will contain a dictionary with the following keys:
|
||||
addr - Address of this memory segment
|
||||
last_addr - Last address contained within the memory segment.
|
||||
size - size of the segment, in bytes
|
||||
num_pages - number of pages in the segment
|
||||
page_size - size of each page, in bytes
|
||||
"""
|
||||
cfg = device[0]
|
||||
intf = cfg[(0, 0)]
|
||||
mem_layout_str = usb.util.get_string(device, 255, intf.iInterface)
|
||||
mem_layout = mem_layout_str.split('/')
|
||||
addr = int(mem_layout[1], 0)
|
||||
segments = mem_layout[2].split(',')
|
||||
seg_re = re.compile(r'(\d+)\*(\d+)(.)(.)')
|
||||
result = []
|
||||
for segment in segments:
|
||||
seg_match = seg_re.match(segment)
|
||||
num_pages = int(seg_match.groups()[0], 10)
|
||||
page_size = int(seg_match.groups()[1], 10)
|
||||
multiplier = seg_match.groups()[2]
|
||||
if multiplier == 'K':
|
||||
page_size *= 1024
|
||||
if multiplier == 'M':
|
||||
page_size *= 1024 * 1024
|
||||
size = num_pages * page_size
|
||||
last_addr = addr + size - 1
|
||||
result.append(named((addr, last_addr, size, num_pages, page_size),
|
||||
"addr last_addr size num_pages page_size"))
|
||||
addr += size
|
||||
return result
|
||||
|
||||
|
||||
def list_dfu_devices(*args, **kwargs):
|
||||
"""Prints a lits of devices detected in DFU mode."""
|
||||
devices = get_dfu_devices(*args, **kwargs)
|
||||
if not devices:
|
||||
print("No DFU capable devices found")
|
||||
return
|
||||
for device in devices:
|
||||
print("Bus {} Device {:03d}: ID {:04x}:{:04x}"
|
||||
.format(device.bus, device.address,
|
||||
device.idVendor, device.idProduct))
|
||||
layout = get_memory_layout(device)
|
||||
print("Memory Layout")
|
||||
for entry in layout:
|
||||
print(" 0x{:x} {:2d} pages of {:3d}K bytes"
|
||||
.format(entry['addr'], entry['num_pages'],
|
||||
entry['page_size'] // 1024))
|
||||
|
||||
|
||||
def write_elements(elements, mass_erase_used, progress=None):
|
||||
"""Writes the indicated elements into the target memory,
|
||||
erasing as needed.
|
||||
"""
|
||||
|
||||
mem_layout = get_memory_layout(__dev)
|
||||
for elem in elements:
|
||||
addr = elem['addr']
|
||||
size = elem['size']
|
||||
data = elem['data']
|
||||
elem_size = size
|
||||
elem_addr = addr
|
||||
if progress:
|
||||
progress(elem_addr, 0, elem_size)
|
||||
while size > 0:
|
||||
write_size = size
|
||||
if not mass_erase_used:
|
||||
for segment in mem_layout:
|
||||
if addr >= segment['addr'] and \
|
||||
addr <= segment['last_addr']:
|
||||
# We found the page containing the address we want to
|
||||
# write, erase it
|
||||
page_size = segment['page_size']
|
||||
page_addr = addr & ~(page_size - 1)
|
||||
if addr + write_size > page_addr + page_size:
|
||||
write_size = page_addr + page_size - addr
|
||||
page_erase(page_addr)
|
||||
break
|
||||
write_memory(addr, data[:write_size], progress,
|
||||
elem_addr, elem_size)
|
||||
data = data[write_size:]
|
||||
addr += write_size
|
||||
size -= write_size
|
||||
if progress:
|
||||
progress(elem_addr, addr - elem_addr, elem_size)
|
||||
|
||||
|
||||
def cli_progress(addr, offset, size):
|
||||
"""Prints a progress report suitable for use on the command line."""
|
||||
width = 25
|
||||
done = offset * width // size
|
||||
print("\r0x{:08x} {:7d} [{}{}] {:3d}% "
|
||||
.format(addr, size, '=' * done, ' ' * (width - done),
|
||||
offset * 100 // size), end="")
|
||||
sys.stdout.flush()
|
||||
if offset == size:
|
||||
print("")
|
||||
|
||||
|
||||
def main():
|
||||
"""Test program for verifying this files functionality."""
|
||||
global __verbose
|
||||
# Parse CMD args
|
||||
parser = argparse.ArgumentParser(description='DFU Python Util')
|
||||
#parser.add_argument("path", help="file path")
|
||||
parser.add_argument(
|
||||
"-l", "--list",
|
||||
help="list available DFU devices",
|
||||
action="store_true",
|
||||
default=False
|
||||
)
|
||||
parser.add_argument(
|
||||
"-m", "--mass-erase",
|
||||
help="mass erase device",
|
||||
action="store_true",
|
||||
default=False
|
||||
)
|
||||
parser.add_argument(
|
||||
"-u", "--upload",
|
||||
help="read file from DFU device",
|
||||
dest="path",
|
||||
default=False
|
||||
)
|
||||
parser.add_argument(
|
||||
"-v", "--verbose",
|
||||
help="increase output verbosity",
|
||||
action="store_true",
|
||||
default=False
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
__verbose = args.verbose
|
||||
|
||||
if args.list:
|
||||
list_dfu_devices(idVendor=__VID, idProduct=__PID)
|
||||
return
|
||||
|
||||
try:
|
||||
init()
|
||||
except ValueError as er:
|
||||
print(str(er))
|
||||
sys.exit(1)
|
||||
|
||||
if args.mass_erase:
|
||||
print ("Mass erase...")
|
||||
mass_erase()
|
||||
|
||||
if args.path:
|
||||
elements = read_dfu_file(args.path)
|
||||
if not elements:
|
||||
return
|
||||
print("Writing memory...")
|
||||
write_elements(elements, args.mass_erase, progress=cli_progress)
|
||||
|
||||
print("Exiting DFU...")
|
||||
exit_dfu()
|
||||
return
|
||||
|
||||
print("No command specified")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
142
unix/main.c
142
unix/main.c
@@ -47,6 +47,7 @@
|
||||
#include "compile.h"
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
#include "builtin.h"
|
||||
#include "repl.h"
|
||||
#include "gc.h"
|
||||
#include "genhdr/py-version.h"
|
||||
@@ -64,9 +65,47 @@ mp_uint_t mp_verbose_flag = 0;
|
||||
long heap_size = 128*1024 * (sizeof(mp_uint_t) / 4);
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <signal.h>
|
||||
|
||||
STATIC mp_obj_t keyboard_interrupt_obj;
|
||||
|
||||
STATIC void sighandler(int signum) {
|
||||
if (signum == SIGINT) {
|
||||
mp_obj_exception_clear_traceback(keyboard_interrupt_obj);
|
||||
mp_pending_exception = keyboard_interrupt_obj;
|
||||
// disable our handler so next we really die
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define FORCED_EXIT (0x100)
|
||||
// returns standard error codes: 0 for success, 1 for all other errors
|
||||
// if FORCED_EXIT bit is set then script raised SystemExit and the
|
||||
// If exc is SystemExit, return value where FORCED_EXIT bit set,
|
||||
// and lower 8 bits are SystemExit value. For all other exceptions,
|
||||
// return 1.
|
||||
STATIC int handle_uncaught_exception(mp_obj_t exc) {
|
||||
// check for SystemExit
|
||||
if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) {
|
||||
// None is an exit value of 0; an int is its value; anything else is 1
|
||||
mp_obj_t exit_val = mp_obj_exception_get_value(exc);
|
||||
mp_int_t val = 0;
|
||||
if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) {
|
||||
val = 1;
|
||||
}
|
||||
return FORCED_EXIT | (val & 255);
|
||||
}
|
||||
|
||||
// Report all other exceptions
|
||||
mp_obj_print_exception(exc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Returns standard error codes: 0 for success, 1 for all other errors,
|
||||
// except if FORCED_EXIT bit is set then script raised SystemExit and the
|
||||
// value of the exit is in the lower 8 bits of the return value
|
||||
STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) {
|
||||
if (lex == NULL) {
|
||||
@@ -119,27 +158,30 @@ STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
// enable signal handler
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = sighandler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sa.sa_handler = SIG_DFL;
|
||||
#endif
|
||||
|
||||
// execute it
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
mp_call_function_0(module_fun);
|
||||
#ifndef _WIN32
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
#endif
|
||||
nlr_pop();
|
||||
return 0;
|
||||
} else {
|
||||
// uncaught exception
|
||||
// check for SystemExit
|
||||
mp_obj_t exc = (mp_obj_t)nlr.ret_val;
|
||||
if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) {
|
||||
// None is an exit value of 0; an int is its value; anything else is 1
|
||||
mp_obj_t exit_val = mp_obj_exception_get_value(exc);
|
||||
mp_int_t val = 0;
|
||||
if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) {
|
||||
val = 1;
|
||||
}
|
||||
return FORCED_EXIT | (val & 255);
|
||||
}
|
||||
mp_obj_print_exception((mp_obj_t)nlr.ret_val);
|
||||
return 1;
|
||||
#ifndef _WIN32
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
#endif
|
||||
return handle_uncaught_exception((mp_obj_t)nlr.ret_val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,16 +268,20 @@ int usage(char **argv) {
|
||||
}
|
||||
|
||||
#if MICROPY_MEM_STATS
|
||||
STATIC mp_obj_t mem_info(void) {
|
||||
STATIC mp_obj_t mem_info(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
printf("mem: total=" UINT_FMT ", current=" UINT_FMT ", peak=" UINT_FMT "\n",
|
||||
m_get_total_bytes_allocated(), m_get_current_bytes_allocated(), m_get_peak_bytes_allocated());
|
||||
printf("stack: " UINT_FMT "\n", mp_stack_usage());
|
||||
#if MICROPY_ENABLE_GC
|
||||
gc_dump_info();
|
||||
if (n_args == 1) {
|
||||
// arg given means dump gc allocation table
|
||||
gc_dump_alloc_table();
|
||||
}
|
||||
#endif
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mem_info_obj, mem_info);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mem_info_obj, 0, 1, mem_info);
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t qstr_info(void) {
|
||||
@@ -265,7 +311,14 @@ void pre_process_options(int argc, char **argv) {
|
||||
emit_opt = MP_EMIT_OPT_VIPER;
|
||||
#if MICROPY_ENABLE_GC
|
||||
} else if (strncmp(argv[a + 1], "heapsize=", sizeof("heapsize=") - 1) == 0) {
|
||||
heap_size = strtol(argv[a + 1] + sizeof("heapsize=") - 1, NULL, 0);
|
||||
char *end;
|
||||
heap_size = strtol(argv[a + 1] + sizeof("heapsize=") - 1, &end, 0);
|
||||
// Don't bring unneeded libc dependencies like tolower()
|
||||
if ((*end | 0x20) == 'k') {
|
||||
heap_size *= 1024;
|
||||
} else if ((*end | 0x20) == 'm') {
|
||||
heap_size *= 1024 * 1024;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
exit(usage(argv));
|
||||
@@ -276,6 +329,12 @@ void pre_process_options(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
void set_sys_argv(char *argv[], int argc, int start_arg) {
|
||||
for (int i = start_arg; i < argc; i++) {
|
||||
mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PATHLIST_SEP_CHAR ';'
|
||||
#else
|
||||
@@ -294,6 +353,11 @@ int main(int argc, char **argv) {
|
||||
|
||||
mp_init();
|
||||
|
||||
#ifndef _WIN32
|
||||
// create keyboard interrupt object
|
||||
keyboard_interrupt_obj = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
|
||||
#endif
|
||||
|
||||
char *home = getenv("HOME");
|
||||
char *path = getenv("MICROPYPATH");
|
||||
if (path == NULL) {
|
||||
@@ -368,6 +432,40 @@ int main(int argc, char **argv) {
|
||||
break;
|
||||
}
|
||||
a += 1;
|
||||
} else if (strcmp(argv[a], "-m") == 0) {
|
||||
if (a + 1 >= argc) {
|
||||
return usage(argv);
|
||||
}
|
||||
mp_obj_t import_args[4];
|
||||
import_args[0] = mp_obj_new_str(argv[a + 1], strlen(argv[a + 1]), false);
|
||||
import_args[1] = import_args[2] = mp_const_none;
|
||||
// Ask __import__ to handle imported module specially - set its __name__
|
||||
// to __main__, and also return this leaf module, not top-level package
|
||||
// containing it.
|
||||
import_args[3] = mp_const_false;
|
||||
// TODO: https://docs.python.org/3/using/cmdline.html#cmdoption-m :
|
||||
// "the first element of sys.argv will be the full path to
|
||||
// the module file (while the module file is being located,
|
||||
// the first element will be set to "-m")."
|
||||
set_sys_argv(argv, argc, a + 1);
|
||||
|
||||
mp_obj_t mod;
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
mod = mp_builtin___import__(MP_ARRAY_SIZE(import_args), import_args);
|
||||
nlr_pop();
|
||||
} else {
|
||||
// uncaught exception
|
||||
return handle_uncaught_exception((mp_obj_t)nlr.ret_val);
|
||||
}
|
||||
|
||||
if (mp_obj_is_package(mod)) {
|
||||
// TODO
|
||||
fprintf(stderr, "%s: -m for packages not yet implemented\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
} else if (strcmp(argv[a], "-X") == 0) {
|
||||
a += 1;
|
||||
} else if (strcmp(argv[a], "-v") == 0) {
|
||||
@@ -398,9 +496,7 @@ int main(int argc, char **argv) {
|
||||
path_items[0] = MP_OBJ_NEW_QSTR(qstr_from_strn(basedir, p - basedir));
|
||||
free(pathbuf);
|
||||
|
||||
for (int i = a; i < argc; i++) {
|
||||
mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
|
||||
}
|
||||
set_sys_argv(argv, argc, a);
|
||||
ret = do_file(argv[a]);
|
||||
break;
|
||||
}
|
||||
@@ -410,6 +506,10 @@ int main(int argc, char **argv) {
|
||||
ret = do_repl();
|
||||
}
|
||||
|
||||
if (mp_verbose_flag) {
|
||||
mem_info(0, NULL);
|
||||
}
|
||||
|
||||
mp_deinit();
|
||||
|
||||
#if MICROPY_ENABLE_GC && !defined(NDEBUG)
|
||||
|
||||
@@ -45,7 +45,9 @@
|
||||
#define MICROPY_STREAMS_NON_BLOCK (1)
|
||||
#define MICROPY_OPT_COMPUTED_GOTO (1)
|
||||
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
|
||||
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
|
||||
#define MICROPY_PY_BUILTINS_FROZENSET (1)
|
||||
#define MICROPY_PY_BUILTINS_COMPILE (1)
|
||||
#define MICROPY_PY_SYS_EXIT (1)
|
||||
#define MICROPY_PY_SYS_PLATFORM "linux"
|
||||
#define MICROPY_PY_SYS_MAXSIZE (1)
|
||||
@@ -58,6 +60,7 @@
|
||||
#define MICROPY_PY_UZLIB (1)
|
||||
#define MICROPY_PY_UJSON (1)
|
||||
#define MICROPY_PY_URE (1)
|
||||
#define MICROPY_PY_UHEAPQ (1)
|
||||
|
||||
// Define to MICROPY_ERROR_REPORTING_DETAILED to get function, etc.
|
||||
// names in exception messages (may require more RAM).
|
||||
|
||||
Reference in New Issue
Block a user