# STM32 General Design Choice
###### tags: `firmware_hardware` `electrical_system` `NTURT`
## Introduction
This documemtation hopes to explain the design choice made when developing stm32 firmware. In order for others to shorten the development time and avoid the traps that we make when developing stm32.
## Hardware
### Problematic HSE
*Problem in nucleo that uses stlink v3, which includes nucleo-g431kb and h723zg*
High speed external clock (hse) is a high presion external clock (usually a crystcal / ceramic oscillator) used to clock the mcu to replace the more inaccurate high speed internal clock (HSI), which is a RC oscillator in the mcu.
For nucleo boards that uses stlink v2, hse signal is supplied by the 8 MHz crystal. However, when st upgrades to stlink v3, the crystal is replaced by a 25 MHz one, and for somereason the signal frequency is devided by 3 before sending to mcu, which complicates things for a lot. Hence st acutally default to use the inaccurate hsi of the stlink to clock the mcu.[^1]
[^1]: hse for stlink v2 and v3 board: [NUCLEO-H743ZI vs. NUCLEO-H743ZI2 and STLINK V3 vs. STLINK V2](https://dm1cr.de/nucleo-h743zi-vs-nucleo-h743zi2-and-stlink-v3-vs-stlink-v2)
> Since the accuracy of hsi is really not great comparing to a crystcal / ceramic oscillator, we choose to use the 25/8M Hz clock signal and manually tune the clock config in cubemx. Yet since we can only type in 8.333 instead of 25/3, so auto-generated settings might be inacurrate.
### Core coupled memory (CCM)
*Feature in stm32g4*
Core coupled memory is a region of sram that code can be executed from with zero wait-state, in comparison to flash memory that might require up to 3 cpu cycles wait time. For how to use ccm checkout: [Use STM32F3/STM32G4 CCM SRAM](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwiy-pDutZb9AhUJNt4KHfDWDUMQFnoECB0QAQ&url=https%3A%2F%2Fwww.st.com%2Fresource%2Fen%2Fapplication_note%2Fan4296-use-stm32f3stm32g4-ccm-sram-with-iar-embedded-workbench-keil-mdkarm-stmicroelectronics-stm32cubeide-and-other-gnubased-toolchains-stmicroelectronics.pdf&usg=AOvVaw1kQcyOgn9Y5m9NygKQ8cEY).
CCM is acutally part of the 32KB sram of stm32-g431, is just that the address of ccm is also mapped to the end of the other sram. So when explicitly using CCM, remember to modify the lengh of ram to 22KB. (The length of the ccm is 10KB.)
Executing code from CCM provides most optimal and deterministic behavior, yet with `ART accelerator` of stm32, the performance between executing code form ccm and using art accelerator is very similar[^2].
Yet ART accelerator is not configurable through `stm32cudemx`. To configure, modify `PREFETCH_ENABLE`, `INSTRUCTION_CACHE_ENABLE`, `DATA_CACHE_ENABLE` of `stm32g4xx_hal_conf.h`.
> Since art accelerator provides similar performance without requiring a dedicated sram to store code, ccm is not used.
[^2]: [STM32G4芯片内不同空间运行代码的速率比较](https://blog.csdn.net/weixin_38106263/article/details/120192447)
### Memory protection unit (MPU)
*Feature in stm32g4, stm32h7*
==TBD==
### Cache
*Feature in stm32h7*
==TBD==
### Tightly coupled memory (TCM)
*Feature in stm32h7*
==TBD==
#### Memory protection unit
TCM is non-cacheable.[^3]
> Since tcm are non-cacheable, there's no need to use mpu to protect it.
[^3]: [TCM attributes and permissions](https://developer.arm.com/documentation/ddi0489/f/memory-system/tcm-interfaces/tcm-attributes-and-permissions)
## Software
### Newlib/newlib-nano
Newlib is essentially a optimized version of ANSI C (or GNU C) runtime library and math library for embedded systems (MCUs). It provides light weight [^4] and reentrant versions [^5][^6] of system calls (most notably `printf`) for resource constrained platforms.
Newlib-nano, which is yet another optimized version of newlib by arm for even smaller memory footprint, is used in stm32cubeide by default. However, such optimization sacrifices speed for size, and to some extent by a lot. [^7][^8][^9]
> Since both stm32g4 and stm32h7 have plenty of flash and ram availible, performance improvement provided by newlib (instead of the size optimization provided by newlib-nano) is the choice here.
[^4]: memory footprint reduction when using newlib: [Reducing memory usage with a custom printf and newlib-nano](https://os.mbed.com/blog/entry/Reducing-memory-usage-with-a-custom-prin/)
[^5]: what reentrancy is and how newlib implemented it: [Reentrancy in Newlib](https://www.codeinsideout.com/blog/freertos/reentrant/#)
[^6]: malloc was originally not thread-safe in freertos stm32 port, but is now fixed: [newlib-malloc solution that is thread safe by default](https://community.st.com/s/question/0D53W00001KRfkeSAD/is-stm32cubeide-newlib-with-freertos-now-really-thread-safe)
[^7]: Guideline to choose the c runtime library: [Which Embedded GCC Standard Library? newlib, newlib-nano, …](https://mcuoneclipse.com/2023/01/28/which-embedded-gcc-standard-library-newlib-newlib-nano/)
[^8]: Five times the performance in memcpy: Carmine Noviello. 2020. "Mastering STM32 - Second Edition": 242.
[^9]: Three times the performance in wolfssl: [Topic: Performance Advisory for Cortex M - Newlib vs Newlib-Nano](https://www.wolfssl.com/forums/topic1596-performance-advisory-for-cortex-m-newlib-vs-newlibnano.html)
#### assert
Newlib does not provide a friendly assert macro. [^10]
> Since newlib-nano assert is weird, custom assert macro is used to replaced it.
[^10]: [How to get assert to print to UART? STM32 newlib nano](https://stackoverflow.com/questions/61357391/how-to-get-assert-to-print-to-uart-stm32-newlib-nano).