Introduction to Embedded Systems Programming (Ada)
learn.adacore.com
learn.adacore.com
Can someone speak, at a high-level, on how Ada manages memory? I'm gonna read the docs, but if anyone has a good explanation here, that would be appreciated!
In general, I'm interested in learning more about embedded languages that are not C/C++ or Rust. To give some context, my dream embedded language is one like F# or OCaml that can be embedded (i.e., has manual memory management or some other solution).
It often isn’t necessary to explicitly use pointers to dynamically allocated memory. For example, Ada lets you return an array of unknown size by value from a function. These unconstrained objects are stored on what is called a “secondary stack”, which is basically a special allocation pool for holding these objects managed by the language runtime.
When you do use pointers, the compiler is very strict to try and avoid dangling pointers. You can also create custom pointer types and assign them to memory pools, so dynamic allocations of that pointer type get made in the pool (and not in the normal heap).
You can also use manual memory management (using the `new` keyword and the `Unchecked_Deallocation` function similar to malloc() and free()).
There is also a finalizer class you can inherit from that adds a destructor to record types, so you can use RAII, too.
I used F# a bit and learned a lot from it, and the same with Elixir and Nerves. Nim is procedural but it has an "enlightened procedural" take that feels like functional programming in some ways. Partly thats due to the very powerful type system - for example Nim lets you define custom distinct (not aliased) number types just like F#. Nim also inherits a fair bit from Pascal and so shares points with Ada like ints with custom ranges. Theres some rough points, but largely its made me enjoy programming again.
The esp32 is a good intro route since they're easy to setup. I wrote a wrapper for esp-idf which is used in production in at least two embedded shops: https://github.com/elcritch/nesper (its stable but I haven't had time to update docs for a ehile)
You can run it on Arduinos as well. Theres a pure Nim setup called Ratel and a rp2040 wrapper too. :)
It is low level ;). There is a function like malloc that allocates memory, but there is no free, since re-using freed memory is a common source of bugs in C programs. The idea is that you do all your memory allocation (buffers etc.) during program startup. If an allocation fails, you log the error and exit. Once the program is up and running, you don't allocate any more. Embedded systems, remember. You do everything in fixed memory regions. In critical systems there are some tools that make sure your stack allocations never exceed whatever. Ada programs are not allowed to crash.
That said, most Ada implementations do have something like free, but it is not part of the standard and you are supposed to be very careful with it.
You might like this, "random walk through Ada": http://cowlark.com/2014-04-27-ada/index.html
See https://www.adaic.org/resources/add_content/standards/05aarm....
Ada has free() via "Unchecked_Dealocation", which since Ada 95 is hardly directly called, beacause the language introduced support for RAII via controlled types.
Many data types like strings and vectors are capable of dynamic managing memory themselves, thus no need for the malloc()/free() dance like in C.
When stack allocations, or other kinds of allocations fail from those dynamic types, an exception is thrown, that can be caught and the same operation retried with smaller sizes.
With SPARK integration into standard Ada, formal proofs can be used to handle how memory and other resources are being managed.
Finally, due to Rust's sucess bringing affine types into the mainstream, Ada is also having a go into affine types, influenced by ParaSail experiment whose author now works at AdaCore (not to forget the remaining 6 Ada vendors still in business).
Pico Keys (https://www.tindie.com/products/fabien-c/pico-keys/) is a good example of a complex project built with rp2040_hal.
Note that this library is specific to the RP2040, not the larger Raspberry Pi boards. Some Ada drivers for those exist, but are not as well documented.
I also gave a short talk about some of the challenges I encountered earlier this year: https://youtu.be/Pwd9Q5ELAGM