without any external wiring.
This patch introduces the new method
Esp.rebootIntoUartDownloadMode()
When the user calls this method the ESP8266 reboots into the UART
download mode. In this mode the user can use esptool.py to flash a new
firmware file. The following command was used to test it:
$ esptool.py --before no_reset --after soft_reset --chip esp8266 \
--port /dev/ttyUSB0 --baud 460800 write_flash 0x0 firmware.bin
The implementation is based on the original implementation in the
boot ROM. Some parts of the original implementation can be found in
[1]. This patch is a squashed and simplified version of [2]. The non
squashed version might be helpful in case of debugging issues.
[1] https://github.com/twischer/xtensa-subjects/blob/master/reversed/bootrom.c
[2] https://github.com/twischer/Arduino/tree/reboot_uart_download_full
Signed-off-by: Timo Wischer <twischer@freenet.de>
RODATA can be copied automatically by the bootrom, so no reason not to
allow its use for strings and constants in eboot.c
Revert to pfalcon's original uzlib since the single patch to remove
RODATA is not required.
Rationalize eboot.ld linker script, clean up BSS and init it in code.
Saves 112 bytes of space in the bootloader sector by removing the
extra code associated with literal loads.
* Move CRC out of bootload sector
We added protection to only erase the bootload sector when flashing an
image when the new sector != the old sector. This was intended to
minimize the chance of bricking (i.e. if there was a powerfail during
flashing of the boot sector the chip would be dead).
Unfortunately, by placing the CRC inside the eboot sector *every*
application will have a unique eboot sector (due to the crc/len), so
this protection doesn't work.
Move the CRC into the first 8 bytes of IROM itself. This frees up extra
space in the boot sector and ensures that eboot won't be reflashed
unless there really is an eboot change.
* allow to set pin to OUTPUT_OPEN_DRAIN in analogWrite
* remove parameter with default value
* Update core_esp8266_wiring_pwm.cpp
* update documentation accordingly
Add basic 24 bit mode to the I2S API with a i2s_set_bits() call.
By default 16b mode is still used, but if i2s_set_bits(24) is run
before i2s_begin() then the HW will drive 24-bits of data. This
data must be left-aligned (i.e. bits 31..8) in 4-byte samples.
Fixes#5244 (the HW doesn't support 8 or 32 bits, only 16 or 24).
* Allow specifying waveform generator in source code
Allows code to explicitly specify which waveform generator it wants,
without needing to use one of the 100 IDE menus or adding a `-D`
compile-time define.
Uses weakrefs to allow for apps to call `enablePhaseLockedWaveform();`
within their `setup()` (or anywhere, really) and have the phase locked
versions override the default waveform generators automatically.
For example:
````
void setup() {
// Uncomment following line to use phase-locked waveform generator
// enablePhaseLockedWaveform();
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
analogWriteRange(1000);
}
void loop() {
analogWrite(LED_BUILTIN, 100);
delay(1000); // Wait for a second
analogWrite(LED_BUILTIN, 900);
delay(2000); // Wait for two seconds (to demonstrate the active low LED)
}
````
Also adds an example showing it's use.
Address @dok-net's comments and also remove the _weak/_bound version of
startWaveform() since it's invariant of the actual waveform generator.
* Add inline always option to HeapSelect
* Add option to force DRAM for pvPort... APIs
* revert print_loc premature change
* Renamed macro to be more specific, FORCE_ALWAYS_INLINE to FORCE_ALWAYS_INLINE_HEAP_SELECT
Added replacement for the Boot ROM `_xtos_set_exception_handler`
to handle installing our replacement `_xtos_c_wrapper_handler`.
Simplified install in the non 32-bit exception module to make use of the
improved `_xtos_set_exception_handler`
Reorganized and improved comments.
Fixes#6410
We actually provide a function prototype for `analogReference()` in
`Arduino.h`, but no implementation. Add a dummy one that only supports
DEFAULT (like other Arduino boards).
resets. It seems you should not use input registers for scratch registers.
Add an extra output register instead. No code size increase.
Light refactoring for readability
Added "C" reference code for Extended ASM
Save two cycles by loading a0 early in exc-c-wrapper-handler.S
Use optimization O2
Net change in size, 0 bytes with optimization. Save 4 bytes w/o Optimization.
With changes and "O2" save 3 cycles on write and 6 cycles on read.
* Upgrade to upstream newlib 4.0.0 release
Includes 64 bit time_t and 5 years of updates.
Binary incompatible with libraries which use time_t (due to the size
difference). Recompiling with the new newlib should be sufficient for
most libraries, assuming source is available.
* Remove tools/sdk/libc directory, it isn't used anywhere
Somewhere along the line the copy of libc in tools/sdl/libc was taken
out of the build process. Files in there are not used, take add'l time
to build and install on a toolchain release, and just cause confusion.
Remove them.
* Fix 64-bit time for LittleFS
The core was setting 64-bit times automatically on new file creation or
updates, but would fail when attempting to read them back due to 64/32b
confusion.
Now attempt to read 64b time, and if that fails fallback to reading 32b
time to allow both old and new FS to preserve timestamps.
* Update to jjsuwa-sys3175 additions to GCC and newlib
@jjsuwa-sys3175 contributed multiple patches to GCC, included in
the toolchain, as well as a slightly faster pgm_read_byte() macro.
* Rebuild w/addl GCC patches, new BearSSL flags
* Remove copied libgcc.a file, is contained in toolchain
This commit adds W5500 W5100 and ENC28j60 drivers from @njh with credits
They are available in libraries/
An example is added in W5500 examples directory
plus:
* Extract dhcp server from lwip2 and add it to the core as a class.
It must always be present, it is linked and can be called by fw on boot.
So it cannot be stored in a library.
* ethernet: static or dhcp works
* PPPServer: example
* bring WiFi.config() to the lwIP generic interface (argument reorder common function)
* move hostname() from WiFI-STA to generic interface
* remove non readable characters from dhcp-server comments
* dhcp-server: magic_cookie is part of bootp rfc
* fixes from https://github.com/d-a-v/W5500lwIP/issues/17
* enable lwip_hook_dhcp_parse_option()
* +ethernet tcp client example in w5500 library examples
Fixes#7775
Clean up the passing/setting of custom File time callbacks and add a
host test verifying they work. Existing core was not passing custom
timeCallbacks set at the FS level down to open()ed files, resulting in
them calling the default time(nullptr) and reporting wrong file modify
times.
Two parameters are added to allow using only i2s-in/out-data pin.
This is necessary when i2so-bck and i2so-ws are repurposed
especially because they overlap with SPI GPIO.
* PoC cache configuration control
Expaned boards.txt.py to allow new MMU options and create revised .ld's
Updated eboot to pass 48K IRAM segments.
Added Cache_Read_Enable intercept to modify call for 16K ICACHE
Update platform.txt to pass new mmu options through to compiler and linker preprocessor.
Added quick example: esp8266/MMU48K
* Style corrections
Added MMU_ qualifier to new defines.
Moved changes into their own file.
Don't know how to fix platformio issue.
* Added detailed description for Cache_Read_Enable.
Updated tools/sizes.py to report correct IRAM size and indicate ICACHE size.
Merged in earlephilhower's work on unaligned exception. Refactored and added
support for store operations and changed the name to be more closely aligned
with its function. Improved crash reporting path.
* Style and MMU_SEC_HEAP corrections.
* Improved asm register usage.
Added some inline functions to aid in byte and short access to iRAM.
* only byte read has been tested
Updated .ld file to work better with platform.io; however, I am still
missing some steps, so platformio will still fail.
* Interesting glitch in boards.txt after github merge. A new board in
master was missing new additions added by boards.txt.py in the PR.
Which the CI flags when it rebuilds boards.txt.
* Support for 2nd Heap, excess IRAM, through umm_malloc.
Adapted changes to umm_malloc, Esp.cpp, StackThunk.cpp,
WiFiClientSecureBearSSL.cpp, and virtualmem.ino to irammem.ino from
@earlephilhower PR #6994.
Reworked umm_malloc to use context pointers instead of copy context.
umm_malloc now supports allocations from IRAM. Added class
HeapSelectIram, ... to aid in selecting alternate heaps,
modeled after class InterruptLock.
Restrict alloc request from ISRs to DRAM.
Never ending improvements to debug printing.
Sec Heap option now pulls in free IRAM left over in the 1st 32K block.
Managed through umm_malloc with HeapSelectIram.
Updated examples.
* Post push CI cleanup.
* Cleanup part II
* Cleanup part III
* Updates to support platformio, maybe.
* Added exception C wrapper replacement.
* CI Cleanup
* CI Cleanup II
Don't know what to do with platformio it doesn't like my .S file.
ifdef out USE_ISR_SAFE_EXC_WRAPPER to block the new assemlby module
from building on platformio only.
* Changes to exc-c-wrapper-handler.S to assemble under platformio.
* For platformio, Correction to toolchain-xtensa include path.
@mcspr, Thankyou!
* Temporarily added --print-memory-usage to ld parameters for cross-checking IRAM size.
* undo change to platform.txt
* correct merge conflict. take 1
* Fixed #if... for building umm_get_oom_count. It was not building when UMM_STATS_FULL was used.
* Commented out XMC support. Compatibility issues with PoC when using 16K ICACHE.
* Corrected size.py, DRAM bracketing changed to not include ICACHE with DRAM total.
* Added additional _context for support of use of UMM_INLINE_METRICS.
Corrected some UMM_POSION missed edits.
* Changes to clear errors and warnings from toolchain 10.1
Several fixes and improvements to example MMU48K.
With the improved optimization in toolchain 10.1 The example divide by 0
exception was failing with a HWDT event instead of its exception handler.
The compiler saw the obscured divide by 0 and replaced it with a break point.
* Isolated incompatable definitions related to _xtos_set_exception_handler.
GDBSTUB definitions are different from the BootROM's.
* Update tools/platformio-build.py
Co-authored-by: Max Prokhorov <prokhorov.max@outlook.com>
* Requested changes
Changed mmu related usages of ETS_... defines to DBG_MMU_...
Cleanup in example MMU48K.ino. Removed stale memory reference macro
and mmu_status print statement. Cleanup printf '\n' to be '\r\n'.
Improved issolation of development debug prints from the rest of the debug prints.
* Corrected comment. And added missing include.
* Improve comment.
* style and comment correction
* Added draft mmu.rst file and updated index.
Updated example HeapMetric.ino to also illustrate use of IRAM
Improved comments in exc-c-wrapper-handler.S. Added insurance IRQ disable.
* Updated mmu.rst
Improved function name uniqueness for is_iram, is_dram, and is_icache by
adding prefix mmu_. Also, made them available outside of a debug build.
Made pointer precision width more specific.
Made some of the static inline functions in mmu_irm.h safe for ISRs by
setting then for always inline.
* Add a default MMU_IRAM_SIZE value for a new CI test to pass.
Extended use 'umm_heap_context_t *_context' argument in ..._core functions
and expanded its usage to reduce unnecessary repeated calls to
umm_info(NULL, false), also removed recursion from umm_info(NULL, true).
Fixed stack buffer length in umm_info_safe_printf_P and heap.cpp.
Added example for creating an IRAM reserve section.
Updated mmu.rst. Grammar and spelling corrections.
* CI appeasement
* CI appeasement with comment correction.
* Ensure SYS always runs with DRAM Heap selected.
* Add/move heap stack overflow/underflow check to Esp.cpp where the event was discarded.
* Improved comment clarity of purpose for IramReserve.ino. Clean up MMU48K.ino
* Added missing #include
* Corrected usage of warning
* CI appeasement and use #message not #pragma message
* Updated git version of eboot.elf to match build version.
Good test catch.
* Remove conditional build option USE_ISR_SAFE_EXC_WRAPPER, always install.
Use the replacement wrapper on non32xfer_exception_handler install.
Added comments to code describing some exception handling issues.
* Updated mmu.rst
* Expanded and clarified comments.
Limited access to some detailed typdefs/prototypes to .cpp
modules, to avoid future build conflicts.
Completed TODO for verifing that the "C" structure struct __exception_frame
matches the ASM version.
Fixed some typo's, code rot, and added some more cases in examaple irammem.ino.
Refactored a little and reordered printing to ease comparison between methods.
Corrected `#ifdef __cplusplus` coverage area. Cleaned up `extern "C" ...` usage.
Fixes issues with including mmu_iram.h or esp8266_undocumented.h in .c files.
* Style fixes and more cleanup
* Style fix
* Remove unnessasary IRAM_ATTR from install_non32xfer_exception_handler
Some comment tuning.
In the context of _xtos_set_exception_handler and the functions it registers,
changed to type int for exception cause type. This is also the type used by gdbstub
and some other Xtensa files I found.
Fixes#7721 by adding a new error code for when Update::end is called
without any progress at all being made (i.e. no data actually ::write()
to the Update object.
* Re-implement PWM generator logic
Add special-purpose PWM logic to preserve alignment of PWM signals for
things like RGB LEDs.
Keep a sorted list of GPIO changes in memory. At time 0 of the PWM
cycle, set all pins to high. As time progresses bring down the
additional pins as their duty cycle runs out. This way all PWM signals
are time aligned by construction.
This also reduces the number of PWM interrupts by up to 50%. Before,
both the rising and falling edge of a PWM pin required an interrupt (and
could shift arround accordingly). Now, a single IRQ sets all PWM rising
edges (so 1 no matter how many PWM pins) and individual interrupts
generate the falling edges.
The code favors duty cycle accuracy over PWM period accuracy (since PWM
is simulating an analog voltage it's the %age of time high that's the
critical factor in most apps, not the refresh rate). Measurements give
it about 35% less total error over full range at 20khz than master.
@me-no-dev used something very similar in the original PWM generator.
* Adjust running PWM when analogWriteFreq changed
Use fixed point math to adjust running PWM channels to the new
frequency.
* Also preserve phase of running tone/waveforms
Copy over full high/low periods only on the falling edge of a cycle,
ensuring phase alignment for Tone and Servo.
* Clean up signed/unsigned mismatch, 160MHz operat'n
* Turn off PWM on a Tone or digitalWrite
Ensure both the general purpose waveform generator and the PWM generator
are disabled on a pin used for Tone/digitalWrite.
* Remove hump due to fixed IRQ delta
A hump in the dueling PWMs was very prominent in prior pulls.
The hump was caused by having a PWM falling edge just before the cycle
restart, while having the other channel requesting a 1->0 transition
just outside the busy-loop window of 10us. So it gets an IRQ for channel
B 0->1, then waits 2..8us for the next PWM full cycle 0->1, and ends up
returning from interrupt and not scheduling another IRQ for 10us...hence
the horizontal leg of the bump...
Reduce the minimum IRQ latency a little bit to minimize this effect.
There will still be a (significantly smaller) hump when things cross, but
it won't be anywhere near as bad or detectable.
* Speed PWM generator by reordering data struct
Breaking out bitfields required a load and an AND, slowing things down
in the PWM loop. Convert the bitfield into two separate natural-sized
arrays to reduce code size and increase accuracy.
* Remove if() that could never evaluate TRUE
* Add error feedback to waveform generation
Apply an error term to generated waveform phase times to adjust for any
other ongoing processes/waveforms. Take the actual edge generation
times, subtract them from the desired, and add 1/4 of that (to dampen
any potential oscillations) to the next similar phase of that waveform.
Allows the waveform to seek its proper period and duty cycle without
hardcoding any specific calibrations (which would change depending on
the codepaths, compiler options, etc.) in the source.
* Move _stopPWM and _removePWMEntry to IRAM
Thanks to @dok-net for noticing these need to be in IRAM as they may be
called by digitalWrites in an IRQ.
* Avoid long wait times when PWM freq is low
* Fix bug where tone/pwm could happen on same pin
* Adjust for random 160MHZ operation
The WiFi stack sometimes changes frequency behind our backs, so ESP's
cycle counter does not count constant ticks.
We can't know how long it's been at a different than expected frequency,
so do the next best thing and make sure we adjust any ESP cycles we're
waiting for by the current CPU speed.
This can lead to a blip in the waveform for 1 period when the frequency
toggles from normal, and when it toggles back, but it should remain
for the intervening periods.
Should avoid a lot of LED shimmering and servo errors during WiFi
connection (and maybe transmission).
* Clean up leftover debugs in ISR
* Subtract constant-time overhead for PWM, add 60khz
PWM has a constant minimum time between loops with a single pin, so pull
that time out of the desired PWM period and shift the center of the PWM
frequency closer to the desired without any dynamic feedback needed.
Enable 60khz PWM, even though it's not terribly useful as it causes an
IRQ every ~8us (and each IRQ is 2-3us). The core can still run w/o WDT,
but it's performance is about 5x slower than unloaded.
* Fix GPIO16 not toggling properly.
* Remove constant offset to PWM period
analogWrite doesn't know about the change in total PWM cycles, so it is
possible for it to send in a value that's beyond the maximum adjusted
PWM cycle count, royally messing up things. Remove the offset.
Also, fix bug with timer callback functions potentially disabling the
timer if PWM was still active.
* Remove volatiles, replace with explicit membarrier
Volatiles are expensive in flash/IRAM as well as in runtime because they
introduce `memw` instructions everywhere their values are used.
Remove the volatiles and manually mark handshake signals for
re-read/flush to reduce code and runtime in the waveform generator/PWM.
* Consolidate data into single structure
Save IRAM and flash by using a class to hold waveform generator state.
Allows for bast+offset addressing to be used in many cases, removing
`l32r` and literals from the assembly code.
* Factor out common timer shutdown code
* Remove unneeded extra copy on PWM start
* Factor out common edge work in waveform loop
* Factor out waveform phase feedback loop math
* Reduce PWM size by using 32b count, indexes
Byte-wide operations require extra instructions, so make index and count
a full 32-bits wide.
* GP16O is a 1-bit register, just write to it
Testing indicates that GP16O is just a simple 1-bit wide register in the
RTC module. Instead of |= and &- (i.e. RmW), use direct assignment in
PWM generator.
* Increase PWM linearity in low/high regions
By adjusting the PWM cycle slightly to account for the fixed time
through the compute loop, increase the linear response near the min and
max areas.
* Remove redundant GetCycleCount (non-IRQ)
* Factor out common timer setup operations
* Fix clean-waveform transition, lock to tone faster
New startWaveform waveforms were being copied over on the falling edge
of the cycle, not the rising edge. Everything else is based on rising
edge, so adjust accordingly.
Also, feedback a larger % of the error term in standard waveform
generation. Balances the speed at which it locks to tones under
changing circumstances with it not going completely bonkers when a
transient error occurs due to some other bit.
* Reduce IRAM by pushing more work to _setPWM
Simply mark pins as inactive, don't adjust the ordered list until the
next _startPWM call (in IROM).
* Fix typo in PWM pin 1->0 transition
Actually check the pin mask is active before setting the PWM pin low.
D'oh.
* Combine cleanup and pin remove, save 50 bytes IROM
The cleanup (where marked-off pins are removed from the PWM time map)
and remove (where a chosen pin is taken out of the PWM map) do
essentially the same processing. Combine them and save ~50 bytes of
code and speed things up a tiny bit.
* Remove unused analogMap, toneMap
Save ~100 bytes of IROM by removing the tone/analog pin tracking from
the interface functions. They were completely unused.
* Save IRAM/heap by adjusting WVF update struct
The waveform update structure included 2 32-bit quantities (so, used
8 * 17 = 136 bytes of RAM) for the next cycle of a waveform.
Replace that with a single update register, in a posted fashion. The
logic now sets the new state of a single waveform and returns
immediately (so, no need to wait 1ms if you've got an existing waveform
of 1khz). The waveform NMI will pick up the changed value on its next
cycle.
Reduces IRAM by 40 bytes, and heap by 144 bytes.
* Don't duplicate PWM period calculation
Let the waveform generator be the single source of truth for the PWM
period in clock cycles.
Reduces IRAM by 32 bytes and makes things generally saner.
* Factor out common PWM update code
Replace repeated PWM update logic with a subroutine, and move the
PWMUpdate pointer into the state itself. Reduces IROM and IRAM,
removes code duplication.
Also remove single-use macros and ifdef configurable options as the
IRAM and IROM impact of them are now not very large.
* Fix regression when analogWrite done cold
Lost an `initTimer()` call in a refactoring, resulting in the core
hanging forever while waiting for the NMI which will never happen.
Re-add as appropriate.
* Save 16b of IRAM by not re-setting edge intr bit
Per @dok-net, drop the rewrite of the edge trigger flag in the timer
interrupt register. It's set on startup and never cleared, so this is
redundant. Drops ~16 bytes of IRAM.
* Allow on-the-fly PWM frequency changes
When PWM is running and analogWriteFreq is called, re-calculate the
entire set of PWM pins to the new frequency. Preserve the raw
numerator/denominator in an unused bit of the waveform structure to
avoid wasting memory.
* Adjust for fixed overhead on PWM period
Pulls the actual PWM period closer to the requested one with a simple,
0-overhead static adjustment.
* Fix value reversal when analogWrite out of range
Silly mistake, swapped high and low values when checking analogWrite for
over/under values. Fixed
* Don't optimize the satopWaveform call
Save a few bytes of IRAM by not using -O2 on the stopWaveform call. It
is not a speed-critical function.
* Avoid side effects in addPWMtoList
* Adjust PWM period as fcn of # of PWM pins
Results in much closer PWM frequency range over any number of PWM pins,
while taking 0 add'l overhead in IRAM or in the IRQ.
* Fix occasional Tone artifacts
When _setPWMFreq was called the initial PWM mask was not set to 0
leading to occasional issues where non-PWM pins would be set to 1
on the nextPWM cycle. Manifested itself as an overtone at the PWM
frequency +/-.
* Reduce CPU usage and enhance low range PWM output
Borrow a trick from #7022 to exit the busy loop when the next event is
too far out. Also reduce the IRQ delta subtraction because it was
initially not NMI so there was much more variation than now.
Keep the PWM state machine active at a higher prio than the standard
tone generation when the next edge is very close (i.e. when we're at
the max or min of the range and have 2 or more near edges). Adds a
lot of resolution to the response at low and high ranges.
Go from relative to absolute cycle counts in the main IRQ loop so that
we don't mingle delta-cycles when the delta start was significantly
different.
* Update min IRQ time to remove humps in PWM linearity
Keep PWM error <2.0% on entire range, from 0-100%, and remove the
hump seen in testC by fixing the min IRQ delay setting.
* Remove minor bump at high PWM frequencies
The IRQ lead time was a tiny bit undersized, causing IRQs to come back
too late for about .25us worth of PWM range. Adjust the constant
accordingly
* Allow 100% high or low periods.
Let output remain at current level on stopping instead of always turning to low.
* Fix serious jitter issues in previous versions.
* Use ESP.getCycleCount() just like everyone else.
* Highest timer rate at which this runs stable appears to be 2µs (500kHz).
* Guard for zero period length undefined waveforms.
Fix for zero duty or off cycles and expiring from them.
* Cycle precision for expiry instead of special treatment for 0 value.
* Give expiry proper precedence over updating a waveform
* Important comment
* Refactored, identical behavior.
* Use plural for bit arrays.
* Fix for completely duty or all off cycle period case.
* Expiration is explicitly relative to service time.
* Comment updated, here it's about cycles not usecs.
* Revert misconception of how waveformToEnable/Disable communicates with the NMI handler.
* Rewrite to keep phase in sync if period remains same during duty cycle change.
Refactor identifies to distinguish CPU clock cycle from waveform cycle.
* Rather iterate even if full-duty or no-duty cycle in period, than too many calculations in NMI handler.
* Must fire timer early to reach waveform deadlines, otherwise under some load aggressive jitter occurs.
* Schedule expiry explicitly, too.
Needed to keep track of next timer ccy in each iteration, not just when changing level.
* Quick change lets analogWrite keep phase for any duty cycle (including 0% and 100%).
* Set duration to multiple of period, so tone stops on LOW pin output.
* Improve phase timing
* Eror causing next Timer IRQ to fail busy-to-off cycle transitions.
* Regression fix, don't reset timer if pending shortly.
* Rather reschedule ISR instead of busy looping during permitted maximum time.
* Lead time improved for ISR
* Reduce number of cycle calculations.
* Reactive the gcc optimize pragmas.
* Simplify calculation.
* handles overshoot where an updated period is shorter than the previous duty cycle
* Misleading code, there must ever be only one bit set at a time, start and stop block until the ISR has handled and reset the token.
* Prevent missing a duty cycle unless it is overshot already.
* Continuously remove distant pending waveform edges from the loop, continuously update now.
* Replace volatile for one-way exchange into ISR with memory fence.
* Remove redundant stack object.
* Revert pending waveform removal from loop - corrupts continuous next event computation.
* Reduce if/do ... while to while
* Convert relative timings to absolute.
* Relax waveform start to possibly cluster phases into same IRQ interval.
* max 12us in ISR seems to work best for servo/fan/led/tone combo test.
* Restructured code in ISR for expiration, this saves 36 byte IRAM, and improves PWM resolution.
* Simplified overshot detection and 0% / 100% duty cycle.
* Leave ISR early if rescheduling is more promising than busy-waiting until next edge.
* Stabilized timings.
* Prevent WDT under load.
* Use clock cycle resolution instead of us for analogWrite.
* Reduce idle calculations in ISR.
* Optimize in-ISR time.
* Support starting new waveform in phase with another running waveform.
* Align phase for analogWrite PWMs.
* Tune preshoot, add lost period fast forward.
* Adapt phase sync code from analogWrite to Servo
* Fix for going off 100% duty cycle period.
* Eschew obfuscation.
* Fixed logic for zero duty cycle.
* Determine generator quantum during same IRQ - this is better than timer resolution, but non-zero.
* Tune timings, fix write barriers and overshoot logic.
* Migrate Tone to waveform with CPU cycle precision
* Can do 60kHz PWM.
* Recalibrated timings after performance optimizations.
Initialize GPIO if needed.
* Fix regression for waveform runtime.
* Test cycle duration values for signed arithmetic safety.
* Performance tuning.
* Performance tweak, in-ISR quantum is now 1.12µs.
* Round up duration instead of down - possibly to zero, which means forever.
* Extend phase alignment with optional phase offset.
* Slightly better in-ISR quantum approximation for steadier increments.
* Waveform stopped by runtime limit in iSR doesn't deinit the timer, but stopWaveform refuses
to do anything if the waveform was stopped by runtime, either.
* Improved quantum correction code.
* Fix broken multi-wave generation.
* Aggregate GPIO output across inner loop. True phase sync, and now better performance.
* IRQ latency can be reduced from 2 to 1 us now, no WDT etc.
* Improved handling of complete idle cycle miss, progress directly into duty cycle.
* Recalibrated after latest changes and reverts.
* Overshoot compensation for duty cycle results in PWM milestone.
* Adjustments to duty/idle cycle to mitigate effects of floating duty cycle logic.
* Remove implicit condition from loop guard and fix timer restart duration
* Host all static globals in an anonymous static struct.
* Busy wait directly for next pending event and go to that pin.
* Record nextEventCcy in waveform struct to save a few cycles.
* Adapt duty cycle modification to only fix full duty and all idle cases.
* Remember next pin to operate between IRQs.
* Don't set pinMode each time on already running PWM or Tone.
* Remove quantum, correct irq latency from testing,reuse isr timeout from master et al
* Move updating "now" out of inner loop, prevents float between pins that are in phase lock.
* Merge init loop with action loop again.
* Adaptive PWM frequency and floating duty cycle.
* Predictive static frequency scaling.
* Dynamic frequency down-scaling
* Frequency scaling is only for PWM-like applications, anything needing real time duty cycles or frequency must be able to fail on overload.
* Conserve IRAM cache, resort to best effort.
* Directly scale frequency for all duty/all idle waves to reasonable maximum, reduces thrashing.
* Getting the math right beats permanently reducing PWM frequency.
* Rename identifier to help think about the problem.
* AutoPwm correction moved to correct location - after overshoot recalc - and allow limited duty floating
* Finish overshoot math fixes.
* First set pin mode, then digital write.
* Simplify calculations, fix non-autoPwm for servo use, where exact duty is needed, idle is elastic.
* Move wave initialization and modification outside the inner loop.
* Some optimizing.
* Updating "now" in the inner loop should lessen interference
* Finally get rid of volatile and use atomic thread fence memory barriers, great for ISR performance.
* Improved idle cycle overshoot mitigation.
* Improved duty cycle overshoot mitigation.
Case for investigation: 3% (shl 5) vs. 1.5% (shl 6), either less fuzz, but a few marked stray spots, or more fuzz, but no bumps in counter-PWM travel test.
* Move startPin etc. into common static struct
* Persist next event cycle across ISR invocations, like initPin was before.
* Recalibrated DELTAIRQ and IRQLATENCY. Tested @ 3x 40kHz PWM + 440Hz Tone
* CPU clock to Timer1 ccy correction must be dynamic even when BSP is compiled for fixed CPU clock.
* Corrected use of Timer1 registers and add rationale to Timer1 use in comment.
Recalibrate for improved frequence downscaling @ 80MHz and 160MHz.
* Let duty cycle overshoot correction depend on relative impact compareed to both period and duty.
* 80MHz/160MHz specific code can be compile-time selected in general, only NMI is affected by
apparent CPU frequency scaling in SDK code.
* Seems that removing the redudant resetting of edge interrupt mode shaves 0.5us off rearm latency.
* Recalibrated delta irq ccys.
* Off-by-one in 100% duty overshoot correction.
* Simple register writes.
* Memory fences checked and joining events into same loop iteration that are close to one another.
* Shorten progression when going off 100% duty.
* Code simplifications.
* Dynamically map pins out from in-ISR handling based on next event timing.
Major performance boost.
* Reverting maximum IRQ period to 10ms. This sets the wave reprogramming rate to 100Hz max.
* Revert recent change that is the most likely cause of reported PWM frequency drop regression.
* Much simplified overshoot mitigation code.
* Fixing overshoot mitigation, 3x 880Hz, 256 states now.
* Increase resolution by keeping reference time moving forward earlier.
* Mitigation logic for ESP8266 SDK boosting to 160MHz during some WiFi ops.
* Event timestamps are all recorded for compile-time CPU frequency, the timer ticks conversion
must be set at compile-time also. The SDK WiFi 160MHz boost mitigation temporarily handles
the CPU clock running twice as fast.
* Expired pins must not be checked for next event.
* Recalibrate after latest changes.
* Save a few bytes code.
* Guards are in place, so xor rather than and bitwise not.
* Reduce memory use.
* SDK boost to 160MHz may last across multiple ISR invocations, therefore adjust target ccy instead of ccount.
* Overshoot mitigation w/o PWM frequency change.
* New PWM overshoot mitigation code keeps frequency. Averages duty between consecutive periods.
* Small refactoring, remove code path that is never taken even at 3x25kHz/1023 PWM.
* Don't ever skip off duty, no matter if late or infinitely short.
* Shed speed-up code that didn't speed up things.
* Must always recompute new waveform.nextEventCcy if there is any busy pin.
* Break out of ISR if timespan to next event allows, instead of busy waiting and stealing CPU cycles from userland.
* Minor code simplification.
* Improve code efficiency.
* Improved performance of loop.
* Recalibrated.
* No positive effect of lead time inclusion was found during testing, remove this code.
Maximum period duration limit is implicit to timer, consider it documented constraint, don't runtime
check in ISR.
* Fix WDT when at 160MHz CPU clock the Timer1 is set below 1µs.
* Consolidate 160MHz constexpr check, finish 1µs minimum for Timer1 fix.
* Test for non-zero before subtract should improve performance.
* Reviewers/tested noted they were seeing WDT, and this change appeared to fix that.
* More expressive use of parentheses and alias CPU2X for reduced code size.
* Bug fix: at 160MHz compiled, don't force minimum Timer1 latency to 2µs.
* Alternate CPU frequency scaling mitigation.
* Handle time-of-flight in the right spot.
* Remove _toneMap from Tone.cpp
Co-authored-by: david gauchard <gauchard@laas.fr>
* WString: Optimize a bit
* move bodies of dtor, `init()` and `charAt()` to .h (implicitly inlined)
* unify descriptions of the initialization into one: `init()` (literally), that is called from each ctors, `invalidate()` and `move()`
* invert the SSO state logic in order to make init state zeroed (as a result, each inlined `init()` saves 1 insn)
* detab and trim
* remove `inline` from .h
* cosmetics
* optimize the non-SSO -> SSO transition part of `changeBuffer()`
* remove duped body of `operator =(StringSumHelper &&rval)`
* remove common subexpressions from `lastIndexOf()` and `substring()`
* eliminate `strlen(buf)` after calling `sprintf(buf, ...)` that returns # of chars written
* eliminate `len()` after calling `setLen(newlen)`
* make ctor`(char c)` inlineable
* optimize `setLen()`
* replace constant-forwarding overload functions with default argument ones
* optimize `concat(char c)`
* * optimize `init()` more
* TZ: help newlib parser
Timezones coded with numeric abbreviations <±nn>±nn<±nn>[±nn][,...] are incorrectly parsed
by newlib's TZ parser.
Replacing <±nn> occurences by UNK allows newlib's TZ parser to nicely interpret all timezones.
Detailed explanation in https://github.com/earlephilhower/newlib-xtensa/issues/12
* Add Print::availableForWrite method
Adds an availableForWrite() method to the Print class, matching current
ArduinoCore-API commit 398e70f188e2b861c10d9ffe5e2bfcb6a4a4f489 .
Hook availableForWrite into the SDFS filesystem (other FSes don't have
this capability built-in).
Fixes#7650
* WiFiClient::availableForWrite proto matching Print
* Fix Netdump signedness warning
* Clean up Serial availableForWrite
This is evidently a breaking change due to the type difference.
Arduino's `availableForWrite` returns an `int`, while the
(multiply-implemented, non-virtual) core `availableForWrite` returned
`size_t`.
* Do not write more data than requested on PUYA flashes
* Always align flash reads/writes to 4 bytes
* fixup! Always align flash reads/writes to 4 bytes
This commit simplifies the code a bit and fixes a bug that caused wrong number of bytes to be
written
* fixup! Always align flash reads/writes to 4 bytes
* fixup! Always align flash reads/writes to 4 bytes
* Check for result before additional read/write
* Add overloads for unaligned reads/writes
* fixup! Add overloads for unaligned reads/writes
* fixup! Add overloads for unaligned reads/writes
* fixup! Add overloads for unaligned reads/writes
* fixup! Add overloads for unaligned reads/writes
* fixup! Add overloads for unaligned reads/writes
* fixup! Add overloads for unaligned reads/writes
* fixup! Add overloads for unaligned reads/writes
* Add tests for flashRead/flashWrite
* fixup! Add overloads for unaligned reads/writes
* fixup! Add tests for flashRead/flashWrite
* fixup! Add tests for flashRead/flashWrite
* fixup! Add overloads for unaligned reads/writes
* Allow test framework to use cores/esp8266/Arduino.h directly
* fix wps debugging
* some more missing debug.h
* Hunt down debug.h and roll-back
TODO: rename it to something else... it is an internal header
* Move abs+round checks to test/device/test_sw
* Restore macros for C code
* fixup! Move abs+round checks to test/device/test_sw
* Fix bad c/p, actually try round with ints
* tweak c macros per review
* fix gcc-10 missing cerrno include
* (test) WString: c_str() returns null pointer
target = std::move(source) does not reset buffer pointer back to the sso
* wstring: correctly do move invalidation & copy
based on the #7553 without isSSO -> isHeap rename and inline optimizations
additionally, remove useless pre-c++11 preprocessor checks
Co-authored-by: Takayuki 'January June' Suwa <jjsuwa@sys3175.com>