Open kasperl opened 8 years ago
The main 'board' should really be a singleton.
There's not much state in these objects (since most of it's held in the hardware), but it doesn't really make sense to have more than one instance (per hardware unit - one board might have 3 ADC units, for example).
I'm not sure I'd make them complete compile-time constants, though, since that'll tie the code that uses them to a specific implementation.
What I'd really like, is to be able to inject the concrete board-specific class at compile time, maybe through a project/hardware manifest, so the rest of the code can be as generic as possible, making it easier to support multiple boards with the same application code.
I think having a main library per board that passes a board-object to the rest of the program is the right way to 'inject' the dependency.
I agree that having board objects as instantiatable objects is not the right solution. Having more than one instance (of any board) in a given application does not make sense.
We might use Interface Libraries (configuration specific imports) to abstract over board differences to create a program that can run on several boards.
File board_interface.dart
import 'package:gpio/gpio.dart';
// Main LED.
GpioOutputPin get led {}
File board.dart
export 'board_interface.dart'
if (board.stm32f746g_discovery) 'board_stm32f746g_discovery.dart'
if (board.stm32f411re_nucleo) 'board_stm32f411re_nucleo.dart'
show led;
File board_stm32f746g_discovery.dart
import 'package:stm32/stm32f746g_disco.dart';
// Use LED1 as main LED.
final led = gpio.initOutput(LED1);
File board_stm32f411re_nucleo.dart
import 'package:stm32/stm32f411re_nucleo.dart';
// Use LED2 as main LED.
final led = gpio.initOutput(LED2);
And the main program
import 'dart:dartino'
import 'board.dart'
main() {
led.toggle();
sleep(500);
}
The passing either -Dboard.stm32f746g_discovery
or -Dboard.stm32f411re_nucleo
at compile-time should make the main file compile for both boards.
If we get the board selection integrated into the compilation/project setup the the -D
options should be set automatically when compiling from project configuration.
Another solution to allow for generic programs is to make the board classes form a class hierarchy and have a factory constructor instatiate the concrete object using an environment constant. For example, new Stm32Board()
would return either a Stm32F7DiscoveryBoard
or Stm32F411RENucleoBoard
(depending on the target platform specified), but a new Stm32F411RENucleoBoard
would throw an error if the STM32F746G board is specified as target.
Right now, we insist on all users of important system wide properties to first create an instance of a specific class through something like
new STM32F746GDiscovery()
. Why?Does it make sense for two such objects to co-exist within the same process? How much state does the objects you can grab hold from from the STM32F746GDiscovery instance have?
I think most users would prefer this kind of board-support library:
or maybe even insist on making all the objects involved compile-time constants that hold any necessary state in static fields.