Upon start-up, _boot module is executed from frozen files to do early
initialization, e.g. create and mount the flash filesystem. Then
"boot.py" is executed if it exists in the filesystem. Finally, "main.py"
is executed if exists to allow start-on-boot user applications.
This allows a user to make a custom boot file or startup application
without recompiling the firmware, while letting to do early initialization
in Python code.
Based on RFC https://github.com/micropython/micropython/issues/1955.
With .rodata being in FlashROM now, gap can be much smaller now. InstRAM
can be max 32K, and with segment headers, that already makes it more than
32K. Then there's some .data still, and the next Flash page boundary is
0x9000. That figure should be more or less future-proof.
TODO: Refactor makeimg to take FlashROM segment offset from file name.
This was originally used for non-event based REPL processing. Then it
was unused when event-based processing was activated. But now that event
based is disabled, and non-event based is back, there has been new ring
buffer code to process the chars.
Event-driven loop (push-style) is still supported and default (controlled
by MICROPY_REPL_EVENT_DRIVEN setting, as expected).
Dedicated loop worked even without adding ets_loop_iter(), though that
needs to be revisited later.
Before this change, if REPL blocked executing some code, it was possible
to still input new statememts and excuting them, all leading to weird,
and portentially dangerous interaction.
TODO: Current implementation may have issues processing input accumulated
while REPL was blocked.
The idea is following: underlying interrupt-driven or push-style data source
signals that more data is available for dupterm processing via call to
mp_hal_signal_dupterm_input(). This triggers a task which pumps data between
actual dupterm object (which may perform additional processing on data from
low-level data source) and input ring buffer.
But now it's generic ring buffer implemented via ringbuf.h, and is intended
for any type of input, including dupterm's, not just UART. The general
process work like this: an interrupt-driven input source puts data into
input_buf, and then signals new data available via call to
mp_hal_signal_input().
PWM implementation uses a timer and interrupts (FRC1), taken from
Espressif's/NodeMCU's implementation and adapted for our use.
8 channels are supported, on pins 0, 2, 4, 5, 12, 13, 14, 15.
Usage:
import machine
pwm0 = machine.PWM(machine.Pin(0))
pwm0.freq(1000)
pwm0.duty(500)
Frequency is shared (ie the same) for all channels. Frequency is
between 1 and 1000. Duty is between 0 and 1023.
This implementation provides the same interface and uses the same
datastructures as used by BootROM, i.e. is a drop-in replacement for it.
But it offers one advantage: it allows to run single iteration of
event-pumping loop.
Original BootROM function are renamed, prefixed with underscore. There's
a switch which allows to use forward calls to them, for compatibility
testing.
The implementation also includes workarounds for hardware timer handler,
and these workarounds may be SDK version specific.
Allows to set (in case keyword args are given) or query (in case a single
"symbolic keyword" (a string, value is the same as keyword)) arbitrary
interface paramters (i.e. extensible and adaptable to various hardware).
Example usage:
ap_if = network.WLAN(1)
ap_if.config(essid="MicroPython on Air")
print(ap_if.config("essid"))
Allows to up/down interface when called with a boolean, or query current
state if called without args. This per-interface method is intended to
supersede adhoc network.wifi_mode() function.
On ESP8266, there're 2 different interfaces. Pretending it's not the case
desn't make sense. So, network.WLAN() now takes interface id, and returns
interface object. Individual operations are then methods of interface
object. Some operations require i/f of specific type (e.g. .connect()
makes sense only for STA), other are defined for any (e.g. .ifconfig(),
.mac()).
None of the other ports do, since introduction of mp_state_ctx_t. In
the case of current esp8266 port, heap is inside BSS, so scanning it
picked up a lot of dead pointers.
Enabling standard assert() (by removing -DNDEBUG) produces non-bootable
binary (because all messages go to .rodata which silently overflows).
So, for once-off debugging, have a custom _assert().
Initialize RTC period coefficients, etc. if RTC RAM doesn't contain valid
values. time.time() then will return number of seconds since power-on, unless
set to different timebase.
This reuses MEM_MAGIC for the purpose beyond its initial purpose (but the whole
modpybrtc.c need to be eventually reworked completely anyway).
The first argument to the type.make_new method is naturally a uPy type,
and all uses of this argument cast it directly to a pointer to a type
structure. So it makes sense to just have it a pointer to a type from
the very beginning (and a const pointer at that). This patch makes
such a change, and removes all unnecessary casting to/from mp_obj_t.
This is a convenience function similar to pyexec_file. It should be used
instead of raw mp_parse_compile_execute because the latter does not catch
and report exceptions.
py/mphal.h contains declarations for generic mp_hal_XXX functions, such
as stdio and delay/ticks, which ports should provide definitions for. A
port will also provide mphalport.h with further HAL declarations.
Scenario: module1 depends on some common file from lib/, so specifies it
in its SRC_MOD, and the same situation with module2, then common file
from lib/ eventually ends up listed twice in $(OBJ), which leads to link
errors.
Make is equipped to deal with such situation easily, quoting the manual:
"The value of $^ omits duplicate prerequisites, while $+ retains them and
preserves their order." So, just use $^ consistently in all link targets.
MicroPython "network" module interface requires it to contains classes
to instantiate. But as we have a static network interace, make WLAN()
"constructor" just return module itself, and just make all methods
module-global functions.
Pasting more or less sizable text into ESP8266 REPL leads to random chars
missing in the received input. Apparent cause is that using RTOS messages
to pass individual chars one by one is to slow and leads to UART FIFO
overflow. So, instead of passing chars one by one, use RTOS msg to signal
that input data is available in FIFO, and then let task handler to read
data directly from FIFO.
With this change, lost chars problem is gone, but the pasted text is
truncated after some position. At least 500 chars can be pasted reliably
(at 115200 baud), but 1K never pastes completely.
1. Updated linker script, now user app appears to contain exception vector
table and oesn't work (faults) without it.
2. Commened out support for GPIO pulldown, which was removed in this SDK
version without clear explanation, but apparently because it was released
without proper validation, and now turns out it doesn't work as expected,
or there's a different function there.
As user_init() is not a true main functions, the stack pointer captured within
is not pointing at the base of the stack. This caused gc_collect being called
with sp being higher than stack_end, causing integer overflow and crashing as
gc tried to scan almost the entire address space.
esp8266 port now has working raw and friendly REPL, as well as working
soft reset (CTRL-D at REPL, or raise SystemExit).
tools/pyboard.py now works with esp8266 port.
* UDP currently not supported
* As there is no way (that I know of) the espconn_regist_connectcb()
callback can recognize on which socket has the connection arrived,
only one listening function at a time is supported
Previous to this patch the printing mechanism was a bit of a tangled
mess. This patch attempts to consolidate printing into one interface.
All (non-debug) printing now uses the mp_print* family of functions,
mainly mp_printf. All these functions take an mp_print_t structure as
their first argument, and this structure defines the printing backend
through the "print_strn" function of said structure.
Printing from the uPy core can reach the platform-defined print code via
two paths: either through mp_sys_stdout_obj (defined pert port) in
conjunction with mp_stream_write; or through the mp_plat_print structure
which uses the MP_PLAT_PRINT_STRN macro to define how string are printed
on the platform. The former is only used when MICROPY_PY_IO is defined.
With this new scheme printing is generally more efficient (less layers
to go through, less arguments to pass), and, given an mp_print_t*
structure, one can call mp_print_str for efficiency instead of
mp_printf("%s", ...). Code size is also reduced by around 200 bytes on
Thumb2 archs.
To enable parsing constants more efficiently, mp_parse should be allowed
to raise an exception, and mp_compile can already raise a MemoryError.
So these functions need to be protected by an nlr push/pop block.
This patch adds that feature in all places. This allows to simplify how
mp_parse and mp_compile are called: they now raise an exception if they
have an error and so explicit checking is not needed anymore.
This enables proper interfacing with underlying OS - MicroPython doesn't
run the main loop, OS does, MicroPython just gets called when some event
takes place.
This patch consolidates all global variables in py/ core into one place,
in a global structure. Root pointers are all located together to make
GC tracing easier and more efficient.
Some rodata items can go in iram/irom segment, but not others. With
this patch ESP now has 24256 bytes of heap ram. It passes 228 out of
248 tests from tests/basics directory.