Small fixes to the documentation

This commit is contained in:
Romain Goyet
2020-03-09 22:22:21 -04:00
committed by LeaNumworks
parent cf84a30768
commit c1215063ee
5 changed files with 15 additions and 17 deletions

2
docs/build/index.md vendored
View File

@@ -54,7 +54,7 @@ git clone https://github.com/numworks/epsilon.git
## Run Epsilon on your computer
Once the SDK has been installed, just open your terminal (Msys2, Terminal.app, xterm, etc...) and type the following commands:
Once the SDK has been installed, just open your terminal (Msys2, Terminal.app, xterm) and type the following commands:
```
make PLATFORM=simulator clean

View File

@@ -46,12 +46,11 @@ The choice of a programming language is a controversial topic. Not all of them c
- It is a [system](https://en.wikipedia.org/wiki/System_programming_language) programming language, which is something we need since we have to write some low-level code.
- It has excellent tooling: several extremly high-quality compilers
- It is used for several high-profile projects LLVM, WebKit, MySQL, Photoshop, etc... This ensures a strong ecosystem of tools, code and documentation.
- It is used for several high-profile projects LLVM, WebKit, MySQL, Photoshop This ensures a strong ecosystem of tools, code and documentation.
- It easily allows Object-Oriented Programming, which is a convenient abstraction.
Of course knowing a tool means knowing its limits. C++ isn't exempt of defaults:
- It *is* a complicated language. The C++ 11 specification is 1300 pages long.
- It *is* a complicated language. The C++ 11 specification is 1'300 pages long.
- It allows for a lot of abstractions, which is a double-edged sword. It can allow for some very tricky code, and it's very easy to have complex operations being run without noticing.
If you want to contribute to Epsilon, you'll need to learn some C++.
@@ -66,7 +65,7 @@ The stack memory is possibly the most used area of memory. It contains all local
#### Heap memory
Unfortunately, local variables can't answer all use cases, and sometimes one need to allocate memory that lives longer than a function call. This is traditionally done by using a pair of *malloc* / *free* functions.
Unfortunately, local variables can't answer all use cases, and sometimes one need to allocate memory that lives longer than a function call. This is traditionally done by using a pair of `malloc` / `free` functions.
This raises a lot of potential problems that can trigger unpredictable dynamic behaviors:
@@ -77,7 +76,7 @@ This raises a lot of potential problems that can trigger unpredictable dynamic b
<dd class="text-justify">Memory allocation has to be contiguous. So the allocation algorithm has to use a smart heuristic to ensure that it will not fragment its allocated space too much.</dd>
</dl>
Some automatic memory management solutions do exist (garbage collection, smart pointers), but they all come with a cost. We decided to manually manage dynamic memory, but to use it as sparingly as possible.
We decided to avoid `malloc` altogether and to use a mix of static allocation and a pool of relocatable garbage-collected nodes for manipulating mathematical expressions.
### Writing code that runs on the bare metal
@@ -90,8 +89,8 @@ In practice, this means that the firmware will need to know in advance how the m
- Where will we store read-only variables?
- Where will the code live in memory?
The firmware will also need to take special care of the system initialization. There is no such thing as a "main" function on a firmware. Instead, on Cortex-M4 devices, after reset the CPU simply jumps to the address contained at address 0x00000000 (which happens to be the first bytes of flash memory). So if your firmware starts by 0x12345678, code execution will start at address 0x12345678.
The firmware will also need to take special care of the system initialization. There is no such thing as a "main" function on a firmware. Instead, on Cortex-M devices, after reset the CPU simply jumps to the address contained at address 0x00000000 (which happens to be the first bytes of flash memory). So if your firmware starts by 0x12345678, code execution will start at address 0x12345678.
Enforcing such a careful memory layout would be an impossible job without the proper tool. Fortunately, embedded linkers can be scripted and allow this kind of tailor-made configuration. You'll find Epsilon's linker script in "ion/src/device/boot/flash.ld" - it is heavily commented and should be self-explanatory.
Enforcing such a careful memory layout would be an impossible job without the proper tool. Fortunately, embedded linkers can be scripted and allow this kind of tailor-made configuration. You'll find Epsilon's linker script in [ion/src/device/n0110/flash.ld](https://github.com/numworks/epsilon/blob/master/ion/src/device/n0110/flash.ld) - it is heavily commented and should be self-explanatory.
That being said, there are additional things the OS usually takes care of which we need to do ourselves : for example, initialize global variables to zero. This is done in the "ion/src/device/boot/rt0.cpp" file, which is worth reading too.
That being said, there are additional things the OS usually takes care of which we need to do ourselves : for example, initialize global variables to zero. This is done in the [ion/src/device/shared/boot/rt0.cpp](https://github.com/numworks/epsilon/blob/master/ion/src/device/shared/boot/rt0.cpp) file, which is worth reading too.

View File

@@ -11,25 +11,25 @@ By providing multiple implementations of the Ion functions, we therefore can get
## Device
This is the reference platform corresponding to the actual device. To really understand what the code is doing, you'll need to refer to our <a href="../../../hardware/electrical/">Electrical Engineering</a> pages. Among other thing, Ion is responsible for handling the boot process and the memory layout of the code on the device:
This is the reference platform corresponding to the actual device. To really understand what the code is doing, you'll need to refer to our [Electrical Engineering](https://www.numworks.com/resources/engineering/hardware/electrical/) pages. Among other thing, Ion is responsible for handling the boot process and the memory layout of the code on the device:
### Boot
On boot, the Cortex core interprets the beginning of Flash memory as an array of addresses, each having a specific meaning. For example, the first value gives the address of the stack and the second one the address the processor jumps to right after reset. This list of addresses is called the <a href="https://github.com/numworks/epsilon/blob/master/ion/src/device/boot/isr.c">ISR table</a>.
On boot, the Cortex core interprets the beginning of Flash memory as an array of addresses, each having a specific meaning. For example, the first value gives the address of the stack and the second one the address the processor jumps to right after reset. This list of addresses is called the [ISR table](https://github.com/numworks/epsilon/blob/master/ion/src/device/shared/boot/isr.c).
### Memory layout
Like we saw in the previous paragraph, the MCU has a specific memory layout (for example, Flash starts at address 0x08000000) and expects certain values at certain addresses. To ensure the firmware is laid out in memory exactly how the processor expects it, we use a custom <a href="https://github.com/numworks/epsilon/blob/master/ion/src/device/boot/flash.ld">linker script</a>.
Like we saw in the previous paragraph, the MCU has a specific memory layout (for example, Flash starts at address 0x08000000) and expects certain values at certain addresses. To ensure the firmware is laid out in memory exactly how the processor expects it, we use a custom [linker script](https://github.com/numworks/epsilon/blob/master/ion/src/device/n0110/flash.ld).
## Simulator
The simulator platform implements Ion calls using the <a href="http://www.fltk.org/">FLTK</a> library. The result is a native GUI program that can run under a variety of operating systems such as Windows, macOS or most Linux distributions.
The simulator platform implements Ion calls using the [SDL](https://www.libsdl.org/) library. The result is a native GUI program that can run under a variety of operating systems such as Windows, macOS or most Linux distributions.
It's very practical to code using the simulator, but one has to pay attention to the differences from an actual device: it'll be significantly faster, and will have a lot more memory. So code written using the simulator should always be thoroughly tested on an actual device.
## Emscripten
The emscripten platform implements Ion calls for a Web browser. This lets us build a version of Epsilon that can run directly in a browser, as shown in our <a href="/simulator/">online simulator</a>. The C++ code is transpiled to JavaScript using Emscripten, and then packaged in a webpage.
The emscripten platform implements Ion calls for a Web browser. This lets us build a version of Epsilon that can run directly in a browser, as shown in our [online simulator](https://www.numworks.com/simulator/). The C++ code is transpiled to JavaScript using Emscripten, and then packaged in a webpage.
Building on Emscripten takes quite a lot of time so you will most likely not want to use it for development purposes. But obviously it's a very neat feature for end users who can give the calculator a spin straight from their browser.

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -1,5 +1,5 @@
---
title: Poincare
title: Poincaré
---
# Poincaré
@@ -9,7 +9,7 @@ Poincare takes text input such as `1+2*3` and turns it into a tree structure, th
Each node of a tree represents either an operator or a value. All nodes have a type (`Type::Addition`, `Type::Multiplication`...) and some also store a value (ie `Type::Rational`).
![A example expression tree of Epsilon software](<%= p "expression_tree.svg" %>){:class="img-right"}
![A example expression tree of Epsilon software](<%= p "expression-tree.svg" %>){:class="img-right"}
According to their types, expressions are childless (`Type::Rational`) or store pointers to their children (we call those children operands). To ease tree traversal, each node also keeps a pointer to its parent: that information is somewhat redundant but makes dealing with the expression tree much easier. `Multiplication` and `Addition` are the only type that can hold an infinite number of operands. Other expressions have a fixed number of operands: for instance, an `AbsoluteValue` will only ever have one child.
## RTTI: Run-time type information
@@ -43,7 +43,6 @@ To sort those operands, we defined an order on expressions with the following fe
* The order relationship is depth-first recursive: if two expressions are equal in type and values, we compare their operands starting with the last.
* To compare two expressions, we first sort their commutative children to ensure the unicity of expression representations. This guarantees that the order is total on expressions.
![Order relationship on expressions](<%= p "order.svg" %>){:class="img-responsive"}
In the example, both root nodes are r so we compare their last operands. Both are equal to $$\pi$$ so we compare the next operands. As 3 > 2, we can conclude on the order relation between the expressions.