|
| 1 | +--- |
| 2 | +title: STM32 Firmware Design Patterns |
| 3 | +date: 2022-03-21 14:45:00 +0800 |
| 4 | +categories: [embedded] |
| 5 | +tags: [stm32f10x, firmware, programming-techniques, system-configuration] |
| 6 | +--- |
| 7 | +This article explores essential design patterns and programming techniques commonly used in STM32F10x firmware development. |
| 8 | + |
| 9 | +## 1. Robust Clock Stability Check |
| 10 | +```c |
| 11 | +do { |
| 12 | + HSEStatus = RCC->CR & RCC_CR_HSERDY; |
| 13 | + StartUpCounter++; |
| 14 | +} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); |
| 15 | +``` |
| 16 | + |
| 17 | +This pattern shows an elegant approach to clock stability verification: |
| 18 | +- Uses a timeout counter to prevent infinite waiting |
| 19 | +- Continuously monitors the ready flag |
| 20 | +- Combines timeout and status check in a single condition |
| 21 | +- Smart use of do-while to ensure at least one check |
| 22 | + |
| 23 | +## 2. Careful Status Verification |
| 24 | +```c |
| 25 | +if ((RCC->CR & RCC_CR_HSERDY) != RESET) { |
| 26 | + HSEStatus = (uint32_t)0x01; |
| 27 | +} else { |
| 28 | + HSEStatus = (uint32_t)0x00; |
| 29 | +} |
| 30 | +``` |
| 31 | + |
| 32 | +Instead of using the previous HSEStatus directly, the code: |
| 33 | +- Re-checks the register status for extra safety |
| 34 | +- Uses explicit casting to ensure type safety |
| 35 | +- Employs the RESET constant for better readability |
| 36 | +- Avoids potential race conditions in status checking |
| 37 | + |
| 38 | +## 3. Smart Flash Configuration |
| 39 | +```c |
| 40 | +#if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL |
| 41 | + /* Enable Prefetch Buffer */ |
| 42 | + FLASH->ACR |= FLASH_ACR_PRFTBE; |
| 43 | + /* Flash wait state */ |
| 44 | + FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); |
| 45 | + |
| 46 | + #ifndef STM32F10X_CL |
| 47 | + FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0; |
| 48 | + #else |
| 49 | + if (HSE_VALUE <= 24000000) { |
| 50 | + FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0; |
| 51 | + } else { |
| 52 | + FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1; |
| 53 | + } |
| 54 | + #endif |
| 55 | +``` |
| 56 | + |
| 57 | +This section demonstrates sophisticated configuration handling: |
| 58 | +- Uses nested preprocessor conditions for different device families |
| 59 | +- Enables prefetch buffer for performance optimization |
| 60 | +- Adjusts flash wait states based on clock frequency |
| 61 | +- Maintains clear register manipulation despite complex conditions |
| 62 | + |
| 63 | +## 4. Clock Switch Verification |
| 64 | +```c |
| 65 | +while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x04) { |
| 66 | +} |
| 67 | +``` |
| 68 | + |
| 69 | +A simple but crucial check that: |
| 70 | +- Ensures clock switching is complete |
| 71 | +- Uses a busy-wait loop for timing-critical operations |
| 72 | +- Explicitly checks the status bits |
| 73 | +- Guarantees system stability before proceeding |
| 74 | + |
| 75 | +## Key Takeaways |
| 76 | + |
| 77 | +1. **Defensive Programming** |
| 78 | + - Multiple layers of status checking |
| 79 | + - Timeout mechanisms |
| 80 | + - Register re-verification |
| 81 | + |
| 82 | +2. **Performance Optimization** |
| 83 | + - Smart use of prefetch buffer |
| 84 | + - Dynamic flash wait states |
| 85 | + - Efficient register operations |
| 86 | + |
| 87 | +3. **Hardware Abstraction** |
| 88 | + - Device family conditional compilation |
| 89 | + - Clock frequency-based adjustments |
| 90 | + - Clear register manipulation patterns |
0 commit comments