
Programming ARM μC in Rust at four different levels of abstraction - signa11
http://pramode.in/2018/02/20/programming-a-microcontroller-in-rust-at-four-levels-of-abstraction/
======
unwind
This is great and really helps emphasize why I should look into Rust some day
(I program STM32s in C for a living).

It would have been awesome if this had shown the resulting assembly for the
first few cases, too.

~~~
jabot
They do that in a prior post:

[http://pramode.in/2018/01/31/ti-launchpad-with-rust-new-
io/](http://pramode.in/2018/01/31/ti-launchpad-with-rust-new-io/)

~~~
unwind
Thanks, that's very nice and impressive. Zero-cost abstractions are very
attractive.

------
jfries
Wow level 3 there was really elegant. In general I try to find use for a
strong type system to force correct code, but here it's Rust's ownership model
that ends up saving the day.

------
classics2
> A GPIO pin starts out as an input; in that state, you can’t call the
> function set_high. It is a compile time error!

Which is throughly incorrect. Of course you can set the state of an output
register that’s set to input, that state will just not appear on the pin.

~~~
jabot
The state of the pin is encoded in the type of the variable that is used to
access the pin.

This kind of encoding prevents you from making the programming error of
writing to an input pin - which is technically possible, just useless.

~~~
emilfihlman
Not even remotely useless, it's often a feature.

~~~
jsight
Oh? When would you use this? I'm sure there must be some reason, but I can't
think of one.

~~~
dbcurtis
Consider a I/O pin set to open-drain drive. It either actively pulls the
output pin to the ground rail, or the I/O floats. Externally, you have a pull-
up resistor.

If there are multiple chips connected in open-drain, you write the I/O pin to
0 or 1 to either ground or float the pin. You read the I/O pin to see if
anyone else has grounded it if you haven't. This was called "wired-OR" in the
old days. (It's really AND, but was commonly used in DeMorgan equivalent form
for communication buses before tri-state drivers became a thing. I'll get my
cane and hobble back to my rocking chair now..)

~~~
posterboy
I think in the old days, before CMOS, this was called open-collector. I had
learned about it in first semester digital logic not too long ago playing with
the "high speed" 7400 series. If I remember correctly, the latch needs to
support the open collector capability, but the reason escapes me.

~~~
dbcurtis
Open collector if you have a bipolar technology. Modern microcontrollers are
CMOS, so the pull-down transistor has a drain, not a collector. TTL is
bipolar, so the transistor has a collector.

------
madez
Why is it necessary to mark the interrupt handler and the panic formatting
function as extern C functions? Is the C way of doing that set in silicon?

~~~
m1el
C and Rust (can) have different calling conventions. C is the de-facto
standard calling convention. When you mark a function as `extern "C"`, it
means that it can be called as if it is a C function.

~~~
madez
But what C code is running alongside the Rust code on the microcontroller that
would make adhering to the C calling convention necessary? Is the hardware
expecting the C calling convention?

~~~
friendzis
I just skimmed over this, toolchain setup talks about TivaTi/Stellaris, code
is for STM32F. My memory is muddy on this, so take it with a bit of salt.
Cores have specific "interrupt context" (do not recall the actual name) with a
specific set of call[er]-saved registers (EABI). Making fault handlers `extern
C` is a way to ensure that these functions adhere to that EABI and do not
clobber processor state. Probably.

~~~
TickleSteve
There is an interrupt-mode stack and a user-mode stack, the stacks are
switched on interrupt invocation.

The value pushed on to the stack is a special value that causes a pop into SP
to switch stacks back on return.

