So playing with Arduinos, and helping other people do it, I'm struck by how many unnecessary problems we're still struggling with. For example:
- The heap grows up and the stack grows down, and there's no memory protection. Even if you don't use recursion, there's no way to get help from the compiler computing your maximum stack depth, so the way you discover you've malloced too much memory is that your stack corrupts some malloced block, or vice versa. - You'd really like to do that allocation at compile time so you can get an error message. (The inability to get error messages at run time is kind of a step back from microcomputer programming in the 80s.) But allocating a frame buffer of a specified but constant size at runtime looks like this: TV.begin(NTSC, 86, 120); and as far as I know there's no way in C++ to make this work as a global static object: TV::output tv(NTSC, 86, 120); ...which should statically allocate 86*120/8 bytes for the framebuffer, giving you a compile error if there isn't that much RAM left to allocate. - More than allocating memory, I'm allocating *time*. I noticed that a sound waveform was sounding a little bit funny; I hooked the audio output up to my sound card and recorded a waveform with Audacity and discovered that I was getting buffer underruns every frame. I'd like to be able to interrogate the compiler about whether a particular bytebeat is going to take too many cycles to execute instead of improvising an oscilloscope. - And I'd like to construct routines at compile-time by traversing data structures. Maybe each scan line of the video ought to have eight bits spat out from the audio buffer as pixels, three cycles each, followed by an oscilloscope display consisting of setting a pin low, 128-N cycles of delay, setting a pin high, N cycles of delay, setting a pin low, and returning from the ISR. But it's very important that there not be a delay (and especially a variable delay!) between the 8 bits and the oscilloscope display. So treating inlining as an optional optimization that the compiler may choose to perform or not is not really acceptable. - In general, C is not suitable for timing-accurate code for this reason. But doing it in assembly is crappy. - There's normally no multithreading; although there are libraries using setjmp(), they're not widely used. This may be related to the difficulties of managing multiple threads of unknown stack depth in 2K of RAM. But it makes certain very common kinds of programming far more complicated than they need to be. - There's a storage class qualifier ("PROGMEM") for data that end up in program memory (32K of Flash) instead of RAM. But there doesn't seem to be a way to automatically choose the correct version of a function based on whether its arguments are in RAM or in PROGMEM; instead you have to manually replace `strcpy` with `strcpy_P` in the right places when you move a string from RAM to PROGMEM. (I'm pretty sure the compiler tells you if you get this wrong, although I haven't tried it.) But I don't think you can get the compiler to compile the functions of a class for a PROGMEM `this` pointer, let alone compile one version for a RAM `this` and one version for a PROGMEM `this`. So you have to waste precious RAM on constant objects. (Worse, in C++, the minimum sizeof is 1, to ensure that all objects have distinct addresses.) - On an 8-bit processor, performance is quite dramatically affected by the range the compiler infers for intermediate results; division is a particularly bad problem, particularly since GCC doesn't have mixed-size division subroutines. A single inadvertent 32-bit-by-32-bit division per audio sample makes the Arduino start to buffer-underrun. So the upshot is that I end up doing a lot of stuff either by hand or at runtime that I'd like to do automatically at compile time, and then I have to debug problems by trial and error instead of getting useful error messages. C++, despite adding a fair bit of compile-time power and optional type and memory safety to C, has other usability problems of its own. Is there work out there I've overlooked? BitC <http://www.bitc-lang.org/docs/bitc/bitc-origins.html> seems like the closest thing. ATS looks like it might be able to do something like this, but I can't make heads or tails of the programs, which I think bodes ill for the digital artists who basically just want a scripting language for LEDs. Maybe Rust? Kragen -- To unsubscribe: http://lists.canonical.org/mailman/listinfo/kragen-tol