Writing the code to blink an on-board [LED](https://en.wikipedia.org/wiki/Light-emitting_diode), then compiling and uploading it to the *dev board*, and seeing the LED actually *blink* is an excellent way to verify that all the tools, both software and hardware are working as intended. But first, a choice ... There are many "runtimes" for µCs, such as [Arduino](https://docs.arduino.cc/programming/), [STMCube](https://www.st.com/en/ecosystems/stm32cube.html), [libopencm3](https://github.com/libopencm3/libopencm3/blob/master/README.md), and [CMSIS](https://arm-software.github.io/CMSIS_6/latest/General/index.html). These act as low-level foundation to simplify writing application code. I'm going to show a few versions of the LED blinker, to illustrate some differences in coding style. ## Arduino version ```c++ #include <Arduino.h> const int LED = PC13; void setup () { pinMode(LED, OUTPUT); } void loop () { digitalWrite(LED, LOW); delay(100); digitalWrite(LED, HIGH); delay(400); } ``` ## CMSIS version ```c #include <stm32f4xx.h> void delay (int n) { for (volatile int i = 0; i < n * 1000; ++i) {} } int main () { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; GPIOC->MODER &= ~GPIO_MODER_MODE13_Msk; GPIOC->MODER |= GPIO_MODER_MODE13_0; while (1) { GPIOC->ODR &= ~GPIO_ODR_OD13; delay(100); GPIOC->ODR |= GPIO_ODR_OD13; delay(400); } } ``` (the CMSIS version doesn't delay exactly 100+400 ms, the LED will blink at a different rate) The Arduino version provides conventions which work across many different µC types, whereas the CMSIS version stays very close to the low-level hardware and needs a more detailed setup. The limitations of the Arduino approach and the level of detail needed in the CMSIS approach are part of the reason why I chose to take things in a somewhat different direction. ## JeeH version ```c++ #include <jee.h> #include <jee/cycles.h> using namespace jeeh; const Pin led {"C13","P"}; int main () { cycles::init(); while (true) { led = 0; cycles::msBusy(100); led = 1; cycles::msBusy(400); } } ``` ## Build and upload To make this work, one of the the above code versions should be saved in an empty folder as a file called `blink.cpp`, along with a file `platformio.ini` with the following contents: ```ini [platformio] src_dir = . [env:blink] platform = ststm32 framework = cmsis board = blackpill_f411ce upload_protocol = dfu ``` Hold down the BOOT0 button and briefly press NRST. The board is now in "bootloader mode". Then any of the above programs can be built from the command line using this command: pio run -t upload - for the Arduino build, "`framework = cmsis`" must be changed to "`framework = arduino`" - for JeeH, add two lines: "`lib_deps = jcw/jeeh@7`" and "`build_flags = -std=c++17`" *If all is well, the on-board LED will now blink ...* If not: - if there are compile errors: check the contents of files `blink.cpp` and `platformio.ini` - if the upload does not succeed: check the USB cable and repeat the BOOT/NRST step ## Some comparisons The amount of code generated for these builds reflects the runtime overhead of each: ``` Arduino: RAM: [ ] 0.9% (used 1156 bytes from 131072 bytes) Flash: [ ] 2.2% (used 11368 bytes from 524288 bytes) CMSIS: RAM: [ ] 0.0% (used 28 bytes from 131072 bytes) Flash: [ ] 0.1% (used 364 bytes from 524288 bytes) JeeH: RAM: [ ] 0.2% (used 248 bytes from 131072 bytes) Flash: [ ] 0.2% (used 936 bytes from 524288 bytes) ``` The Arduino build has more "built-in conventions", adding to the amount of generated code. The other builds will increase in size as more runtime features are added and enabled.