Skip to content

Commit eb19dab

Browse files
authored
Merge pull request #60 from bxparks/develop
merge v1.2.3 into master
2 parents 9be7557 + 1e8490a commit eb19dab

File tree

10 files changed

+628
-96
lines changed

10 files changed

+628
-96
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
11
# Changelog
22

33
* Unreleased
4+
* 1.2.3 (2022-02-24)
5+
* Rename `unixhostduino_main()` to `epoxyduino_main()`, and make it
6+
static. No need to expose it publicly.
7+
* Add `enableTerminalEcho()` function to enable terminal echoing.
8+
See [Enable Terminal Echo](README.md#EnableTerminalEcho).
9+
* Update examples and [EpoxyFS/README.md](libraries/EpoxyFS) to be
10+
compatible with new `LittleFS` library in ESP32 >=2.0.0.
11+
* Add [EpoxyFS/SeekBenchmark](libraries/EpoxyFSexamples/SeekBenchmark) to
12+
measure the performance loss of calling `seek()` before a `read()`.
13+
* Sometimes the client-code is simpler when reading multiple records
14+
if it can call `seek()` with an explicit offset before each `read()`.
15+
* The alternative would be calling `read()` multiple times sequentially
16+
and using its internal cursor to advance automatically.
17+
* This benchmark shows that `seek()` causes significant performance
18+
loss, even if the `seek()` offset is identical to the internal cursor,
19+
so might be expected to be optimized away.
20+
* Add notes about [Debugging](README.md#Debugging) tools and options
21+
under a Unix environment, such as Valgrind.
422
* 1.2.2 (2022-02-02)
523
* Add a `using Print::write` statement in `StdioSerial.h` to
624
pull in all other overloaded `write()` methods from the parent `Print`

README.md

Lines changed: 95 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ For actual application development, I have started to build a set of
4141
libraries within EpoxyDuino which emulate the versions that run the actual
4242
hardware:
4343

44-
* EpoxyFS: emulation of the ESP8266 LittleFS or ESP32 LITTLEFS
44+
* EpoxyFS: emulation of the ESP8266 LittleFS or ESP32 LittleFS
4545
* EpoxyEepromAvr: emulation of AVR-flavored `EEPROM`
4646
* EpoxyEepromEsp: emulation of ESP-flavored `EEPROM`
4747

@@ -51,7 +51,7 @@ portable to a vanilla Unix environment, EpoxyDuino may work well for you.
5151
Running an Arduino program natively on a desktop-class machine has some
5252
advantages:
5353

54-
* The development cycle can be lot faster because the compilers on the the
54+
* The development cycle can be lot faster because the compilers on the
5555
desktop machines are a lot faster, and we also avoid the upload and flash
5656
process to the microcontroller.
5757
* The desktop machine can run unit tests which require too much flash or too
@@ -68,7 +68,7 @@ The disadvantages are:
6868
environments (e.g. 16-bit `int` versus 32-bit `int`, or 32-bit `long` versus
6969
64-bit `long`).
7070

71-
**Version**: 1.2.2 (2022-02-02)
71+
**Version**: 1.2.3 (2022-02-24)
7272

7373
**Changelog**: See [CHANGELOG.md](CHANGELOG.md)
7474

@@ -91,10 +91,13 @@ The disadvantages are:
9191
* [Alternate Arduino Core](#AlternateArduinoCore)
9292
* [PlatformIO](#PlatformIO)
9393
* [Command Line Flags and Arguments](#CommandLineFlagsAndArguments)
94+
* [Debugging](#Debugging)
95+
* [Valgrind](#Valgrind)
9496
* [Supported Arduino Features](#SupportedArduinoFeatures)
9597
* [Arduino Functions](#ArduinoFunctions)
9698
* [Serial Port Emulation](#SerialPortEmulation)
97-
* [Unix Line Mode](#UnixLineMode)
99+
* [Unix Line Mode](#UnixLineMode)
100+
* [Enable Terminal Echo](#EnableTerminalEcho)
98101
* [Libraries and Mocks](#LibrariesAndMocks)
99102
* [Inherently Compatible Libraries](#InherentlyCompatibleLibraries)
100103
* [Emulation Libraries](#EmulationLibraries)
@@ -258,7 +261,7 @@ provided by the Arduino IDE:
258261
an `#include <Arduino.h>` include line at the top of the file. This is
259262
compatible with the Arduino IDE which automatically includes `<Arduino.h>`.
260263
* The Arduino IDE supports multiple `ino` files in the same directory. (I
261-
believe it simply concontenates them all into a single file.) EpoxyDuino
264+
believe it simply concatenates them all into a single file.) EpoxyDuino
262265
supports only one `ino` file in a given directory.
263266
* The Arduino IDE automatically generates forward declarations for functions
264267
that appear *after* the global `setup()` and `loop()` methods. In a normal
@@ -422,9 +425,9 @@ These parent Makefiles can be used in Continuous Integration, as shown below.
422425

423426
You can use EpoxyDuino to run continuous integration tests or
424427
validations on the [GitHub Actions](https://github.com/features/actions)
425-
infrastructure. The basic `ubuntu-18.04` docker image already contains the C++
426-
compiler and `make` binary. You don't need to install the Arduino IDE or the
427-
Arduino CLI. You need:
428+
infrastructure. The basic `ubuntu-18.04` or `ubuntu-20.04` docker image already
429+
contains the C++ compiler and `make` binary. You don't need to install the
430+
Arduino IDE or the Arduino CLI. You need:
428431

429432
* EpoxyDuino,
430433
* your project that you want to test,
@@ -580,8 +583,8 @@ compiler, which will activate any code that is guarded by:
580583

581584
If the `EPOXY_CORE` make variable is insufficient (e.g. because the appropriate
582585
changes have not been incorporated into `$(EPOXY_DUINO_DIR)/cores/epoxy/`), then
583-
the `EPOXY_CORE_PATH` provides an even bigger hammer. It defines the the
584-
full-path to the Arduino Core API files.
586+
the `EPOXY_CORE_PATH` provides an even bigger hammer. It defines the full-path
587+
to the Arduino Core API files.
585588

586589
By default, this is set to `$(EPOXY_DUINO_DIR)/cores/epoxy`. You can create your
587590
own set of Arduino API files in a directory of your choosing, and set this
@@ -645,6 +648,52 @@ Usage: ./CommandLine.out [--help|-h] [-s] [--include word] [--] [words ...]
645648
A more advanced example can be seen in
646649
[AUnit/TestRunner.cpp](https://github.com/bxparks/AUnit/blob/develop/src/aunit/TestRunner.cpp).
647650

651+
<a name="Debugging"></a>
652+
### Debugging
653+
654+
A huge benefit of compiling Arduino programs using EpoxyDuino is that all the
655+
debugging tools in a Unix environment become automatically available. For
656+
example:
657+
658+
* External Tools
659+
* [Valgrind](https://valgrind.org/docs/manual/quick-start.html)
660+
* [GDB Debugger](https://www.sourceware.org/gdb/)
661+
* Compiler Options
662+
* [Address Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) (ASan)
663+
* [Memory Sanitizer](https://github.com/google/sanitizers/wiki/MemorySanitizer)
664+
(MSan)
665+
* [Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) (UBSan)
666+
667+
I am not an expert on any of these sanitizers, and I have not enabled them by
668+
default in the `EpoxyDuino.mk` file. But you have the capability to add them to
669+
your `Makefile` through the `CXXFLAGS` variable.
670+
671+
Below are some things that I have found useful in my own limited experience.
672+
673+
<a name="Valgrind"></a>
674+
#### Valgrind
675+
676+
I have found the [Valgrind](https://valgrind.org/docs/manual/quick-start.html)
677+
tool quite helpful in tracking down Segmentation Fault crashes. Here is a quick
678+
start:
679+
680+
1. Compile your program using the `-g` flag.
681+
* This is not strictly necessary but this will allow Valgrind to print line
682+
numbers to the source code in the stack trace.
683+
* Two ways:
684+
* Pass the pass through the command line: `$ make CXXFLAGS=-g`
685+
* Edit the `Makefile` and add a `CXXFLAGS += -g` directive
686+
near the top of the file.
687+
2. Run the program under the `valgrind` program.
688+
* Valgrind has tons of options and flags. Here are the flags that I use
689+
(don't remember where I got them):
690+
* `$ alias val='valgrind --tool=memcheck --leak-check=yes
691+
--show-reachable=yes --num-callers=20 --track-fds=yes'`
692+
* `$ val ./MyProgram.out`
693+
694+
When the program crashes because of a `nullptr` dereference, Valgrind will show
695+
exactly where that happened in the source code.
696+
648697
<a name="SupportedArduinoFeatures"></a>
649698
## Supported Arduino Features
650699

@@ -665,7 +714,7 @@ which are implemented:
665714
* `bit()`, `bitRead()`, `bitSet()`, `bitClear()`, `bitWrite()`
666715
* `random()`, `randomSeed()`, `map()`
667716
* `makeWord()`
668-
* `F_CPU`, `clockCyclesPerMicrosecond(), `clockCyclesToMicroseconds(),
717+
* `F_CPU`, `clockCyclesPerMicrosecond(), `clockCyclesToMicroseconds()`,
669718
`microsecondsToClockCycles()`
670719
* `HIGH`, `LOW`, `INPUT`, `OUTPUT`, `INPUT_PULLUP`
671720
* I2C and SPI pins: `SS`, `MOSI`, `MISO`, `SCK`, `SDA`, `SCL`
@@ -692,7 +741,7 @@ which are implemented:
692741
* `IPAddress` class
693742
* `WCharacter.h`
694743
* `isAlpha()`, `isAscii()`, etc.
695-
* `toLowerCase(), `toUpperCase()`, etc
744+
* `toLowerCase()`, `toUpperCase()`, etc
696745
* `Wire.h` (stub implementation)
697746
* `SPI.h` (stub implementation)
698747

@@ -704,7 +753,7 @@ v1.8.2 or v1.8.3. A number of tweaks have been made to support slight variations
704753
in the API of other platforms, particularly the ESP8266 v2.7.4 and ESP32 v1.0.6
705754
cores.
706755

707-
The `Print.printf()` function is an extension to the `Print` class that is
756+
The `Print::printf()` function is an extension to the `Print` class that is
708757
provided by many Arduino-compatible microcontrollers (but not the AVR
709758
controllers). It is implemented here for convenience. The size of the internal
710759
buffer is `250` characters, which can be changed by changing the
@@ -748,7 +797,7 @@ the program. But this convenience means that the Arduino program running under
748797
worth the trade-off.
749798

750799
<a name="UnixLineMode"></a>
751-
### Unix Line Mode
800+
#### Unix Line Mode
752801

753802
(Added in v1.2.0)
754803

@@ -821,6 +870,31 @@ test(myTest) {
821870
}
822871
```
823872
873+
<a name="EnableTerminalEcho"></a>
874+
#### Enable Terminal Echno
875+
876+
(Added in v1.2.3)
877+
878+
By default, the `stdin` of the terminal is set to `NOECHO` mode for consistency
879+
with the actual serial port of an Arduino microcontroller. However when running
880+
a command line utility on a Unix terminal emulator using EpoxyDuino, it is often
881+
useful to enable echoing so that the characters being typed are visible.
882+
883+
To enable echoing, call the `enableTerminalEcho()` function from the global
884+
`setup()`:
885+
886+
```C++
887+
void setup() {
888+
...
889+
890+
#if defined(EPOXY_DUINO)
891+
enableTerminalEcho();
892+
#endif
893+
894+
...
895+
}
896+
```
897+
824898
<a name="LibrariesAndMocks"></a>
825899
## Libraries and Mocks
826900

@@ -854,7 +928,8 @@ These 3 types are described in more detail below.
854928
### Inherently Compatible Libraries
855929

856930
Almost all libraries that I write will be inherently compatible with EpoxyDuino
857-
because EpoxyDuino is what I use to develop and test my libraries.
931+
because EpoxyDuino is what I use to develop and test my libraries. For example,
932+
the following should compile using EpoxyDuino:
858933

859934
* AUnit (https://github.com/bxparks/AUnit)
860935
* AceButton (https://github.com/bxparks/AceButton)
@@ -881,7 +956,7 @@ EpoxyDuino. I have provided 3 such libraries within the EpoxyDuino project:
881956
* [libraries/EpoxyFS](libraries/EpoxyFS)
882957
* An implementation of a file system compatible with
883958
[ESP8266 LittleFS](https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html)
884-
and [ESP32 LITTLEFS](https://github.com/lorol/LITTLEFS).
959+
and [ESP32 LitteFS](https://github.com/espressif/arduino-esp32/tree/master/libraries/LittleFS).
885960
* Two EEPROM implementations:
886961
* [libraries/EpoxyEepromAvr](libraries/EpoxyEepromAvr)
887962
* API compatible with
@@ -903,20 +978,20 @@ the Linux/MacOS host.
903978
Mock libraries are designed to run under EpoxyDuino and provide non-working API
904979
stubs of the target library. These libraries are useful to verify that a program
905980
compiles, but they do not allow us to actually verify that the library works as
906-
intended. This limitation may be sufficient for Continous Integration purposes.
981+
intended. This limitation may be sufficient for Continuous Integration purposes.
907982

908983
* Wire
909-
* The `Wire.h` header file is provided automatically by the `<Arduino.h>`
984+
* The `<Wire.h>` header file is provided automatically by the `<Arduino.h>`
910985
file in EpoxyDuino. No additional library needs to be added to the
911986
`ARDUINO_LIBS` variable in the `Makefile`.
912-
* It provides only mock functions of the actualy `Wire` library that
987+
* It provides only mock functions of the actually `Wire` library that
913988
is provided by real Arduino frameworks.
914989
* This was added very early in the development of EpoxyDuino so that I could
915990
compile some of my programs. I don't think I realized at the time that
916991
`Wire` is a separate (but built-in) library. In retrospect, it may have
917992
been better to split this file into a separate mock library.
918993
* SPI
919-
* The `SPI.h` header file was contributed recently (see #18 and #19) and
994+
* The `<SPI.h>` header file was contributed recently (see #18 and #19) and
920995
is included automatically by the `<Arduino.h>` file in EpoxyDuino.
921996
* It follows the same pattern as `Wire`, the header file provides only mock
922997
functions of the actual `SPI` library.

cores/epoxy/Arduino.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
#define EPOXY_DUINO_EPOXY_ARDUINO_H
1515

1616
// xx.yy.zz => xxyyzz (without leading 0)
17-
#define EPOXY_DUINO_VERSION 10202
18-
#define EPOXY_DUINO_VERSION_STRING "1.2.2"
17+
#define EPOXY_DUINO_VERSION 10203
18+
#define EPOXY_DUINO_VERSION_STRING "1.2.3"
1919

2020
#include <algorithm> // min(), max()
2121
#include <cmath> // abs()
@@ -245,10 +245,7 @@ void setup();
245245
/** Provided in the client code's *.ino file. */
246246
void loop();
247247

248-
/** Default entrypoint, runs setup() and loop() */
249-
int unixhostduino_main(int argc, char** argv);
250-
251-
/** Calls unixhostduino_main() unless overriden by user */
248+
/** Calls epoxyduino_main() unless overriden by user */
252249
int main(int argc, char** argv);
253250

254251
/** Copy of the argc parameter of main() as a global variable. */
@@ -257,6 +254,16 @@ extern int epoxy_argc;
257254
/** Copy of the argv parameter of main() as a global variable. */
258255
extern const char* const* epoxy_argv;
259256

257+
/**
258+
* Enable echoing of each character. By default echoing is turned off for
259+
* consistency with the behavior of the serial port of a real Arduino
260+
* microcontroller. However when running on a Unix machine inside a terminal
261+
* emulator, it is often more useful to enable echoing so that the user can see
262+
* the characters being typed. This function should be called in the setup(),
263+
* guarded by a `#if defined(EPOXY_DUINO)`.
264+
*/
265+
void enableTerminalEcho();
266+
260267
}
261268

262269
// WMath prototypes

cores/epoxy/main.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ int epoxy_argc;
116116

117117
const char* const* epoxy_argv;
118118

119-
int unixhostduino_main(int argc, char** argv) {
119+
static int epoxyduino_main(int argc, char** argv) {
120120
epoxy_argc = argc;
121121
epoxy_argv = argv;
122122

@@ -130,12 +130,23 @@ int unixhostduino_main(int argc, char** argv) {
130130
}
131131
}
132132

133+
void enableTerminalEcho() {
134+
struct termios term;
135+
if (tcgetattr(STDIN_FILENO, &term) == -1) {
136+
return;
137+
}
138+
term.c_lflag |= ECHO;
139+
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &term) == -1) {
140+
return;
141+
}
142+
}
143+
133144
// Weak reference so that the calling code can provide its own main().
134145
int main(int argc, char** argv)
135146
__attribute__((weak));
136147

137148
int main(int argc, char** argv) {
138-
return unixhostduino_main(argc, argv);
149+
return epoxyduino_main(argc, argv);
139150
}
140151

141152
}

0 commit comments

Comments
 (0)