Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

This is exactly, exactly what I've been looking for. As a software engineer whose professional career has focused entirely around the web, embedded systems is a strange, enticing landscape with what seems to be an "old guard," that eschews the frenetic pace of web technologies and frameworks, and relies on old, proven, get-shit-done tooling and technology. Which is amazing. But it also means that no one is writing blog posts on medium about this stuff, and beginner tutorials are sparse. For spoiled Elixir devs like me, this is perfect.


Microcontrollers have got a lot more accessible since Arduino. There's lots of beginner material out there, although admittedly not on Medium. (Unsurprisingly, the people involved prefer a more bare metal approach and put it on blogs or forums instead)

The tooling is nearly always C, so it's interesting to see Rust moving into this space. Memory management is not so much of an issue, but multitasking correctness is; perhaps there will be some new micro-RTOS framework with provably correct interrupt handling. (We have sel4, but that's not quite the same thing)

As you get more low level, the tutorials get sparser. You move into FPGAs, where you have a choice of two languages with 1970s design principles, or third-party tools which work despite the manufacturer's total closedness. As you go deeper into actual IC design, nobody will attempt it without supervision from someone experienced to tell you all the little tricks. And then there's analog IC design, which is basically black magic.


> The tooling is nearly always C

With the esp8266 and low end arm controllers, there has been an explosion of languages for embedded applications; micropython, lua, es, basic, even lisp. Particularly for beginners, this is a good thing. Having said that, the dev environments are somewhat lacking at this stage, and I'm wondering if we'll soon be at a point where they'll be enough resources to just put Linux or other OS straight onto the microcontroller.


Yes, but the ecosystem is so heavily geared towards C there that if you want to do anything non-trivial, you'll need to use C anyway.

I wonder how easily one can link C libraries with MicroPython, that'd be the best of both worlds.


Shouldn't be too hard considering that the entire thing is written in C.


you can also use inline assembly on certain platforms. (last i checked anyways)


> "You move into FPGAs, where you have a choice of two languages with 1970s design principles"

I'm assuming you're referring to VHDL and Verilog. There are plenty of other hardware definition languages out there. Chisel, CλaSH, MyHDL, etc... Can see a more complete list here:

https://en.wikipedia.org/wiki/Hardware_description_language


Sure, those languages might exist as a design document somewhere, but you are not going to have a lot of luck finding an FPGA vendor that actually supports them.


Chisel compiles to verilog, so you don't need vendor support.


Similarly, CλaSH and MyHDL also compile to Verilog (or VHDL).


Oh, that's pretty cool. I might look into that then.


Also in this stack, one step below using an Arduino, would be to use existing microcontrollers (or other ICs), but design your own circuit board. In contrast to IC design, this is something you can do on a hobbyist budget. Actually, if you don't etch the board yourself, but have it made and mailed, all you need is soldering equipment to populate the board with the components.


I've got the equipment to do hot air soldering, and I flatter myself that I've gotten pretty good at some fine SMD work, but these days I rarely bother. The premium on a service like macrofab.com usually is less than the money I waste on spare parts I accidentally destroy and postage from many different distributors.


Can not thank you enough for that comment. I was looking for a local shop that could assemble a couple of prototypes for me and the quotes they provided were at least 3-4 times what macrofab shows me.


Any cheap China-based alternatives?


C++, Oberon, Ada, Java, Pascal and Basic are also an option

https://www.mikroe.com/products/#compilers-software

http://www.astrobe.com/default.htm

http://www.microej.com/resources/supported-platforms/

http://www.adacore.com/press/8-bit-avr-microcontroller/

As for source for information, for me it used to be the Elektor magazine, available in a few languages.

Up to a few years, it was still common to occasionally see Pascal listings on it.

But you are right, the embedded culture is mostly C, and using alternatives, even C++, tends to end in culture clash, as Dan Saks referred to it in his CppCon 2016 talk.


What kinds of things would you want proven correct about your code's interrupt handling?


Mostly whether the mechanism for passing data to and from the main program is sound; but also whether things like interrupt priority make sense and whether your re-trigger handling or re-entrancy are going to work properly (an interrupt happens while you're in the handler for the same interrupt). It might be sufficient simply to have a good set of primitives for this, rather than an actual proof.

Basically whether it's going to deadlock or miss interrupts. Deadlock is immediate disaster, but at least the JTAG will help you .. if the device hasn't self-destructed. Missing interrupts is worse because it's extremely hard to debug.

Forcing DMA to behave would also be great, although this isn't strictly a microcontroller issue. I've seen a few war stories where people are trying to debug memory corruption where the program is completely correct - but some other device has simply DMA'd over it. I think this was involved in https://googleprojectzero.blogspot.co.uk/2017/04/over-air-ex... too.


I believe rust's safety guarantees are enough to ensure the soundness of passing data to/from interrupt contexts and interrupt handler re-entrancy. See rtfm[0] for an example and a good explanation. I think DMA handling can be made safe by using the right abstractions, and then you'd just need to trust that any piece of code that accesses the memory uses the abstraction instead of accessing it directly.

Checking interrupt priorities sounds like an interesting problem. What is the state of the art in deadlock prevention? It would also be cool if you could tell the compiler "I need this interrupt handler to return in less than n clock cycles." I wonder if someone could write a rust compiler plugin to check that.

[0]: http://blog.japaric.io/fearless-concurrency/


Top 10 Causes of Nasty Firmware Bugs

https://embeddedgurus.com/blog/2010/12/top-10-causes-of-nast...

it would be great if all those would be easy issues, or solved.


> The tooling is nearly always C, so it's interesting to see Rust moving into this space. Memory management is not so much of an issue, but multitasking correctness is; perhaps there will be some new micro-RTOS framework with provably correct interrupt handling.

Give Céu a look[0]. It was specifically designed for embedded computing, and compiles to C, making it very easy to interface with existing libraries. It requires no manual memory management, and has very nice structured synchronous reactive concurrency primitives.

(EDIT: I realise that multitasking and concurrency aren't quite the same thing; it also has experimental interrupt support though)

Here's a made-up example for Arduino (for which it has support out of the box[1]). It creates two concurrent fading LEDs at different frequencies, and resetting at the push of a button:

    #include "arduino/arduino.ceu"
    
    input  int PIN_02; // button input
    output int PWM_05; // LED outputs, remember that pins 5 and 6
    output int PWM_06; // have a higher PWM frequency on the UNO
    
    // a code block that concurrently fades an LED in and out
    // `pin`   the output pin of the LED
    // `min`   min value of the fade
    // `max`   max value of the fade
    // `delay`   number of milliseconds to wait between increasing/decreasing `analogWrite`
    code/await Fade_forever(var u8 pin, var u8 min, var u8 max, var uint delay) -> void do
      loop do
        var int i;
        loop i in [min->max] do // fade in loop
          if pin == 5 then
            emit PWM_05(i);
          else/if pin == 6 then
            emit PWM_06(i);
          end
          await delay ms;
        end
        loop i in [min<-max] do // fade out loop
          if pin == 5 then
            emit PWM_05(i);
          else/if pin == 6 then
            emit PWM_06(i);
          end
          await delay ms;
        end
      end
    end
    
    loop do //endless loop
      // if *any* of these three code blocks (trails) end, all of the remaining trails in
      // a `par/or` are aborted and code resumes (in this case, the loop restarts).
      // By comparison, a `par/and` construct would require *all* of the trails to
      // terminate before continuing.
      par/or do
        await PIN_02; // .. meaning that if a button is pressed, we reset the loop
      with
        // fade the LED at pin 5 quickly between 64 and 192
        await Fade_forever(5, 64, 192, 5)
      with
        // fade the LED at pin 6 slowly between 0 and 255
        // note that because it fades over almost twice range (255 vs 128)
        // but not exact, it's around eight times slower, not four, and it
        // will slowly go out of sync. 
        // We can push the button to reset however!
        await Fade_forever(5, 0, 255, 20)
    end
[0] http://ceu-lang.org/, http://fsantanna.github.io/ceu/out/manual/v0.20/

[1] https://github.com/fsantanna/ceu-arduino


Can confirm, in my emag applications class I had tools from "black magic something something" company printed on the top.


Small micro controllers don't have the resources you're used to. The smallest thing I ever wrote code for was in the PIC family and had 176 bytes of RAM and like 4 or 8K of flash (EEPROM?). Even on more common parts you may find only a few K of RAM and 10's or 100's of K flash. In that space we don't do any dynamic memory allocation, never mind garbage collection. If you did it's entirely possible you'd run out of heap space and the program would crash. It's a really different world than what web developers and app developers are used to. I highly recommend taking the dive even if it's just for fun and to see a different type of software development.


The recommended development board isn't that bad. 256Kb Flash memory, 48-Kbyte RAM. It's not as tight as a classic Arduino.

This is where Rust's safety helps. Debugging embedded code on small machines is a huge pain. The more problems caught at compile time, the better off you are. A compile time error beats JTAG debugging every time.

The article gets kind of vague once they get beyond LED-blinking and busy-waiting. They implement a brute-force CPU dispatcher and call it "async" programming. They never get to interrupts at all.

Rust on little machines makes sense, but it needs more support underneath to deal with timers, interrupts, and concurrency. There are projects working on this.[1]

[1] https://users.rust-lang.org/t/rust-for-embedded-development-...


> Rust on little machines makes sense, but it needs more support underneath to deal with timers, interrupts, and concurrency. There are projects working on this.[1]

NB. the OP is part of that project, from the same author.


Rust needs a CPU dispatcher underneath, so the thread and lock primitives can work. A minimal single-process multiple-thread OS, something like VxWorks, is all that's needed. This would probably be something you'd link with the program.

It's better to have one good one CPU dispatcher than making users roll their own crappy one for each application.


What do you mean by 'need'?

If you mean every Rust program requires a dispatcher to run, then no, Rust does not need a CPU dispatcher. Thread and locks are not primitives: they're implemented in the standard library (the std part, specifically). The 'thread' safety guarantees don't rely on that functionality, instead the arrows go the other way: the spawning and locking constructs build on the guarantees (driven by the Send and Sync traits, which are purely compile-time constructs) to provide expressive yet safe API. For instance, there's numerous operating systems built in Rust, for instance intermezzOS seems to be pure Rust except for the single file https://github.com/intermezzOS/kernel/blob/master/src/asm/bo... .

If you mean that it would be really nice if there was a general purpose dispatcher library available, then sure, that seems like something that would be great on crates.io.

In any case, I don't see how your comment relates to mine.


Rust with a CPU dispatcher offers the opportunity to get beyond the raw busy-wait and basic interrupt handling of Arduino-type code without going all the way to a full Linux system. That's what I'm getting at here.


The first micro I ever used (as a kid in the late '90s) was a PIC16C62A. 128 bytes of RAM, 3.5kB of EPROM. Not EEPROM, this was the UV-erasable stuff. I didn't have a UV lamp so I could only program during the day when I could take it outside & peel back the black electrical tape from the window to erase it.


And you might want to avoid multiplication operations, because the compiler will likely have to implement those in software, which will be slow, and might make your program too large to fit in the memory… :-)


This is targeted at cortex m4, arm cores with hardware integer and division (and even integer simd).


Got it. I was thinking of the world of microcontrollers in general.


As a rule, I now try to avoid anything that isn't 32 bits with hardware multiplier. Unless you need a controller for under 50 cents I don't think that's a high bar any more. Floating point - much as I'd like to make it a minimum requirement I still enjoy doing some math in fixed point.

Oh for the day when RV32IMAF can be considered low end.


For me, it's the elegance of making do with the least sophisticated components. Using a microcontroller at all can be seen as bringing out the big guns.


The AVRs, at least some of them, have reasonable Flash and RAM and EEPROM (v nice), and a single-instruction multiply. Much nicer than the 8-bit CPUs that I used to program back in days of yore...


>a single-instruction multiply

But not single cycle ;)

This is important!


MUL/MULS/FMULS are all two cycles, to be exact.


OK, thank you for the correction!

Still a lot faster than a bunch of shift+add!


Pff, look at the fancy people over here!


The recommended 32Fs have FPUs so the hit isn't all that bad


I highly recommend nerdkits (http://www.nerdkits.com) for someone in your shoes. You basically build an Arduino and it explains each part along the way. The included PDF is worth the price alone.


All their kits and components are out of stock.


Yeah, front page last-updated 2013, too.


This embedded dude longs to use Erlang on his MCUs. Closest I can get to it is one of the embedded *nixes. Raspberry PIs are great for prototyping but not all that easy a sell on the BOM


There's a new mcu from microchip, that has 32mb dram, for ~$7. Might get you closer to your erlang dream.

It uses new , cheap multi-die assembly techniques, which microchip also used in their ~$1 Bluetooth chip. So I think with time, and with an attractive software ecosystem,we'll see interesting new mcu's and price points.


> There's a new mcu from microchip, that has 32mb dram

...and a long list of errata, some of them quite serious: http://ww1.microchip.com/downloads/en/DeviceDoc/80000736A.pd...

(note that if you look for it on Microchip website, the official link to the errata is also wrong at the moment!)

Some people also reported a few heat issues, since it's got to dissipate heat from the memory and heat from the MCU, which starts being a bit large and a bit fast (for an MCU). Nothing extreme, but it has has to be considered in some setups.

IMO, it's better to wait for other revisions of this chip, other versions in this family, or something else.


This is quite a list. There are so many "Module x is not functional. Workaround: None." its amazing. How did they manage screw up the VBAT pin?


~$1 Bluetooth chip, is that the ATBTLC1000?


https://www.newbiehack.com/MicrocontrollerTutorial.aspx is an ok (not great but not bad either) way to learn about micro controllers. We used this site in a course I took.

YMMV though. People in my class who lacked the experience I had with C and C++ from before had to struggle quite a lot.


One could argue that blog posts wouldn't be needed since the books written on the material are generally accepted as mature coverage of the subject




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: