I’ve posted the source code of a demo application that drives a 24x WS2812B
LED ring and can be controlled via a serial interface, remotely if you use a
Bluetooth adapter. It uses the DMA to reach redrawing speeds of up to 160 FPS
while keeping the CPU use relatively low (15% @ 8 MHz).
I also have posted some thoughts about a
CircularBuffer abstraction to use
with the DMA and peripherals like the ADC. If you have opinions on that comment
on the thread.
I still fail to see why that would be necessary.
Like I said that’s one way.
HAL would take care of mapping that to the required registers to implement
That would be the role of the configuration layer I mentioned. As I said no
concrete proposal for something like that for the RTFM framework.
However there’s nothing preventing anybody from just addressing GPIOs using
the physical names (or pin numbers) to implement complete custom solutions
just using the chips.
Unlike the AVR Cortex-M chips usually have remappable peripherals. For
example, the PA2 on the stm32f103 could be used as an analog pin (ADC2), serial
pin (TX2), a PWM pin (T2C2), an input capture pin (T2C2) or a quadrature encoder
interface pin (T2C2).
I meant that the Arduino, AFAIK, doesn’t solve this configuration problem: “how
is functionality distributed across all the available pins (without overlap)”.
Arduino doesn’t have to deal with this problem on the AVR because each pin has a
single (alternate) function (apart from GPIO).
Remapping is also why the blue-pill uses peripheral names like USART1 in the
API, the USART1 could be using pins PA9 (TX) and PA10 (TX) or PB6 (TX)
and PB7 (RX), instead of something like
write(PA9, b'H'), what if PA9 was
configured as a PWM pin (T1C2)? - that shouldn’t compile but it’s better, IMO,
if you can make the mistake in the first place.
No need to say, oh, for this board I need to reserve this register and this
register because I want to use GPIO A1, and then initialise the GPIO with the
correct registers and clutter the whole program with board specific details…
There’s no proposal for implicit initialization (as in it gets taken care of
something / someone other than the application writer) for the RTFM framework.
It’s highly related to the configuration problem I mentioned.
I’d argue that it’s the function of the chip crate to define the peripherals,
and BSP to map peripherals to pins based on the board layout, and to implement
the HAL (relying on chip crate functionality wher e it’s common across
I suppose we could store the configuration as crates – that sounds a lot like
the “#define” / C model. I wonder if that’s the most flexible solution. We do
have unstable compiler plugins but I’d rather avoid something that breaks often
(cf. Zinc’s demise).
The application should, where possible*, be BSP/board agnostic.
That sounds like a rather reduced set of applications. But I suppose there’s
value in having a “Hello, world” application to test your whole toolchain /
OTOH if you application targets a set of very similar boards then it may make
more sense to build the application against a single board crate and deal with
the small differences via features / #[cfg]s.
That’s a nice hierarchy.
An embedded developer would be free to build an application using solely those
traits and have it run correctly with a recompile on any of those board crates
simply by using Cargo features.
Hmm, Cargo features are not the right … feature for this I think since they
are binary. For example, it doesn’t make much sense to compile an application
with both the features “board_a” and “board_b” enabled. You want something
that resembles an open ended enum.
There’s also the problem of
if you are using traits since the trait implementation will be in a different
crate for each board. We probably want something better than:
#[cfg(board = "A")]
extern crate board_a as board;
#[cfg(board = "B")]
extern crate board_b as board;
#[cfg(board = "Z")]
extern crate board_z as board;
to make an application compilable for several boards …
Kinda makes you wish that it was possible to link to a crate using a command
line argument but without having to explicitly add the
extern crate to the
source code. I think someone may have already proposed / asked for something
like that on rust-lang/rfcs.