I somehow missed this topic earlier but I played a bit with
embedded runtime last month so I'll share some thoughts.
On Sunday, 10 May 2015 at 06:55:07 UTC, Jens Bauer wrote:
On Sunday, 10 May 2015 at 01:55:53 UTC, Mike wrote:
I've also considered another interesting approach. It seems
possible to port all features of D right to the metal,
essentially embedding the RTOS directly into the runtime.
Then D is your RTOS :-)
I do like this approach better, and that resembles the way I've
been thinking until now.
Yes, it might require more work, but strongly I think it's
worth it.
I believe this would also give the user the most convenient
D-compiler (and toolchain).
I'm also strongly in favor of integrating an RTOS with the
runtime, especially if we publish it under a liberal license,
just as the D runtime is distributed now.
Since most of existing RTOSes are distributed under either
proprietary license or GPL, having a ready-to-use RTOS without
legal restrictions could work towards the adoption of D in the
embedded market. I would start with evaluating the existing
concurrency APIs in terms of their applicability in such RTOS.
Generally, if we stick to the pay-as-you-go approach most
features of D runtime (even exceptions and RTTI) can be ported.
They will not imply any costs when not used, but will be ready to
use out-of-the-box when they're needed. We could advertise it
using e.g. automatically generated charts showing the cost of
each feature. Also, there are already compiler switches to show
GC allocations and TLS variables, so a similar approach could be
used for other potentially costly features.
As for TLS, I think we should not change D semantics by
implicitly making all globals __gshared, but instead follow Dan's
suggestion to create a specific TLS model which statically
resolves thread-local variables to regular globals in
single-threaded builds.
I did some experiments with porting small parts of Phobos and
druntime.
Initial tests show that e.g. semihosted writefln costs about 4KB
of flash initially + about 0.5KB per each new argument type list
(GDC, -Os, Cortex-M3). Sure, it may seem a lot if your uC has
16KB or less, but in such case you probably wouldn't use
formatted output much in C either. You don't pay for it when you
don't call it, and when you need it - it's there and it's fully
functional and type safe (unlike C's printf). And of course
there're probably ways to optimize it.
Also I think exceptions could be possible to implement without
large costs. I've already got scope(exit) and scope(success)
working, and IMHO this is already a huge advantage over manual
cleanup. I started working on unwinding using the libgcc support
but other duties stopped me from finishing it. I'll try to push
this work on github later this week.
I've run the above on LM3S6965 (qemu) and STM32F103
(Nucleo-F103RB).