|
| 1 | +# Bitfilled MM I/O demonstration |
| 2 | + |
| 3 | +This simple project serves as a demonstration of how the [bitfilled][bitfilled] C++20 library |
| 4 | +provides a better abstraction to memory mapped register operations, than traditional C-based solutions, |
| 5 | +in terms of readability, correctness and performance. |
| 6 | + |
| 7 | +## Contents |
| 8 | + |
| 9 | +The project is a **very** stripped down firmware for the STM32F4Discovery board, |
| 10 | +the only thing it does is initialize the button and LED GPIOs, |
| 11 | +and mirrors the button state on the LED in the main loop. |
| 12 | +Please take a look at [`Src/main.cpp`](./Src/main.cpp) to get an idea, and make your own conclusions about readability. |
| 13 | +There are 3 build configurations that achieve the same result with different approaches, |
| 14 | +all of them are built and tested with [renode][renode] hardware simulation. |
| 15 | + |
| 16 | +### stm32cube |
| 17 | + |
| 18 | +This preset uses the STM32 LL GPIO driver, |
| 19 | +a thin wrapper layer over [CMSIS][cmsis] register operations. |
| 20 | +It uses **144 bytes** of code memory. |
| 21 | +As the LL (just like HAL) driver operates with pin masks instead of pin positions, |
| 22 | +the `LL_GPIO_SetPinMode()` call has to recalculate the pin position, |
| 23 | +causing the inflated code size compared to the presented alternatives below. |
| 24 | +(It would make for an interesting benchmark to see how many pin writes or reads |
| 25 | +could offset this extra cost.) |
| 26 | + |
| 27 | +### bitfilled |
| 28 | + |
| 29 | +This preset uses the bitfilled MM register definition found above `main()`, |
| 30 | +functionally performing the same operations as the *stm32cube* variant, |
| 31 | +however requiring only **80 bytes** of code memory. |
| 32 | + |
| 33 | +### bitfilled-bitband |
| 34 | + |
| 35 | +This preset also uses the bitfilled MM register definition, specialized with bit-band operation support. |
| 36 | + |
| 37 | +<details> |
| 38 | + <summary>Bit-band access primer</summary> |
| 39 | + |
| 40 | +Bit-band access is a relatively obscure feature of ARM Cortex M3 and M4 CPUs, |
| 41 | +where the first 1MB address space of SRAM and peripheral regions have their respective 32MB bit-band |
| 42 | +alias address spaces, which allow accessing an individual bit atomically, |
| 43 | +with the CPU performing the read-modify-write cycle internally. |
| 44 | +A great feature on paper, it never saw widespread adoption, |
| 45 | +and later MCUs of the series dropped it entirely. |
| 46 | +IMHO its failure can be largely attributed to a lack of convenient software abstraction method, |
| 47 | +including a complete exclusion from the scope of [CMSIS][cmsis], ARM's own standard. |
| 48 | +It's also difficult to adopt on e.g. the STM32 platform, as their different MCU series map the peripherals in wildly |
| 49 | +different addresses, so any portable implementation must be able to easily switch between |
| 50 | +bit-band and regular code paths. |
| 51 | + |
| 52 | +</details> |
| 53 | + |
| 54 | +--- |
| 55 | + |
| 56 | +Following the same code path as before, the bit-band support increases code size to **100 bytes**, |
| 57 | +which can be attributed to the cost of bit address mapping calculations. |
| 58 | +However, with the assurance of atomic read-modify-write bit access, |
| 59 | +it is possible to use a more optimal solution (copying the input bit to the output bit location). |
| 60 | +This brings the code size down to **84 bytes** - still worse than the base bitfilled approach. Another problem is that the renode simulation of this build fails (the code itself works as expected, [bug report][renode-bitband-issue]). |
| 61 | + |
| 62 | +The bitfilled library manages to implement bit-band support without any change in the API, |
| 63 | +at the cost of increased code size. |
| 64 | +With that in mind, the current conclusion on bit-band use is this: |
| 65 | +use them where concurrent access poses a threat to data integrity |
| 66 | +(so on peripherals with shared use, e.g. RCC, GPIO). |
| 67 | +Note that bit-band support can be selected on the individual register level |
| 68 | +(and there's no technical limitation against enabling it on individual register bit level). |
| 69 | + |
| 70 | + |
| 71 | +[bitfilled]: https://github.com/IntergatedCircuits/bitfilled |
| 72 | +[cmsis]: https://arm-software.github.io/CMSIS_6/latest/General/index.html |
| 73 | +[renode]: https://renode.io/about/ |
| 74 | +[renode-bitband-issue]: https://github.com/renode/renode/issues/829 |
0 commit comments