|
| 1 | +//! # Over-The-Air (OTA) Update Management |
| 2 | +//! |
| 3 | +//! This module implements secure firmware update capabilities for the TLSR8266 mesh lighting |
| 4 | +//! system. It provides the core functionality for receiving, validating, and storing firmware |
| 5 | +//! updates transmitted over the mesh network. |
| 6 | +//! |
| 7 | +//! ## OTA Update Architecture |
| 8 | +//! |
| 9 | +//! The OTA system is designed with the following principles: |
| 10 | +//! |
| 11 | +//! ### Security and Reliability |
| 12 | +//! - **Write-Verify Cycle**: Every flash write operation is immediately verified by reading back |
| 13 | +//! the data to ensure integrity |
| 14 | +//! - **Atomic Operations**: Flash writes are performed in discrete pages to prevent partial updates |
| 15 | +//! - **Error Recovery**: Failed writes are detected immediately and can trigger retransmission |
| 16 | +//! |
| 17 | +//! ### Flash Memory Management |
| 18 | +//! - **Dedicated Flash Region**: Firmware updates are written to a separate flash area to avoid |
| 19 | +//! corrupting the running firmware |
| 20 | +//! - **Sequential Writing**: Firmware data is written sequentially to prevent fragmentation |
| 21 | +//! - **Address Tracking**: Current write position is maintained to resume interrupted updates |
| 22 | +//! |
| 23 | +//! ### Integration with Mesh Network |
| 24 | +//! - **Packet-Based Transfer**: Firmware is transmitted in small packets suitable for mesh networking |
| 25 | +//! - **Progress Tracking**: Update progress is tracked and can be reported across the network |
| 26 | +//! - **Error Propagation**: Write failures are communicated back to the update initiator |
| 27 | +//! |
| 28 | +//! ## Flash Memory Layout |
| 29 | +//! |
| 30 | +//! ``` |
| 31 | +//! Flash Memory: |
| 32 | +//! ┌─────────────────┬─────────────────┬─────────────────┐ |
| 33 | +//! │ Running FW │ New FW Area │ Config/Data │ |
| 34 | +//! │ (Active) │ (OTA Target) │ (Persistent) │ |
| 35 | +//! └─────────────────┴─────────────────┴─────────────────┘ |
| 36 | +//! ↑ |
| 37 | +//! FLASH_ADR_LIGHT_NEW_FW |
| 38 | +//! ``` |
| 39 | +//! |
| 40 | +//! ## Update State Machine |
| 41 | +//! |
| 42 | +//! The OTA process follows this state progression: |
| 43 | +//! 1. **Idle**: No update in progress |
| 44 | +//! 2. **Receiving**: Accepting firmware data packets |
| 45 | +//! 3. **Continue**: Previous packet written successfully, ready for next |
| 46 | +//! 4. **Error**: Write/verify failure detected, update aborted |
| 47 | +//! 5. **Complete**: All firmware data received and verified |
| 48 | +
|
1 | 49 | use crate::config::FLASH_ADR_LIGHT_NEW_FW;
|
2 | 50 | use crate::sdk::drivers::flash::{flash_read_page, flash_write_page};
|
3 | 51 | use crate::sdk::light::OtaState;
|
4 | 52 | use crate::state::{OTA_UPDATE_CURRENT_FLASH_ADDRESS, SimplifyLS};
|
5 | 53 |
|
6 |
| -/// Saves OTA data to flash memory |
| 54 | +/// Saves OTA firmware data to flash memory with verification. |
| 55 | +/// |
| 56 | +/// This function implements the core OTA flash write algorithm with built-in verification |
| 57 | +/// to ensure data integrity. It performs atomic write operations followed by immediate |
| 58 | +/// read-back verification to detect any flash memory errors. |
| 59 | +/// |
| 60 | +/// # Flash Write Algorithm |
| 61 | +/// |
| 62 | +/// The function follows a strict write-verify-advance sequence: |
| 63 | +/// |
| 64 | +/// 1. **Address Calculation**: Computes the target flash address by adding the current |
| 65 | +/// write offset to the base OTA flash region address |
| 66 | +/// |
| 67 | +/// 2. **Flash Write Operation**: Writes the incoming data to flash memory using the |
| 68 | +/// hardware flash driver |
| 69 | +/// |
| 70 | +/// 3. **Verification Read**: Immediately reads back the written data from flash to |
| 71 | +/// verify the write operation succeeded |
| 72 | +/// |
| 73 | +/// 4. **Data Comparison**: Performs byte-by-byte comparison between the original data |
| 74 | +/// and the read-back data to detect any corruption |
| 75 | +/// |
| 76 | +/// 5. **State Update**: On successful verification, advances the write pointer for |
| 77 | +/// the next packet; on failure, returns error state |
| 78 | +/// |
| 79 | +/// # Error Detection |
| 80 | +/// |
| 81 | +/// The verification process detects several types of flash errors: |
| 82 | +/// - **Write Failures**: Flash cells that fail to program correctly |
| 83 | +/// - **Read Disturbance**: Previously written data corrupted by nearby writes |
| 84 | +/// - **Wear-Out**: Flash cells that have exceeded their write/erase cycles |
| 85 | +/// - **Power Glitches**: Incomplete writes due to power supply instability |
| 86 | +/// |
| 87 | +/// # Flash Memory Safety |
| 88 | +/// |
| 89 | +/// The function ensures safe flash operations by: |
| 90 | +/// - Using only the designated OTA flash region (prevents overwriting active firmware) |
| 91 | +/// - Performing sequential writes (prevents address conflicts) |
| 92 | +/// - Validating write operations before advancing (prevents partial corruption) |
| 93 | +/// - Maintaining atomic write semantics (each call either fully succeeds or fails) |
| 94 | +/// |
| 95 | +/// # Performance Considerations |
| 96 | +/// |
| 97 | +/// - **Flash Write Time**: Each write operation may take several milliseconds |
| 98 | +/// - **Verification Overhead**: Read-back verification doubles the flash access time |
| 99 | +/// - **Sequential Access**: Sequential writes are optimized by flash hardware |
| 100 | +/// - **Page Alignment**: Performance is optimal when data aligns with flash page boundaries |
| 101 | +/// |
| 102 | +/// # Parameters |
| 103 | +/// * `data` - Firmware data packet to write to flash (1-16 bytes typical) |
| 104 | +/// |
| 105 | +/// # Returns |
| 106 | +/// * `OtaState::Continue` - Data written and verified successfully, ready for next packet |
| 107 | +/// * `OtaState::Error` - Write or verification failed, update should be aborted |
| 108 | +/// |
| 109 | +/// # Side Effects |
| 110 | +/// * Modifies flash memory content in the OTA region |
| 111 | +/// * Updates `OTA_UPDATE_CURRENT_FLASH_ADDRESS` on successful writes |
| 112 | +/// * May trigger flash wear leveling operations (hardware-dependent) |
| 113 | +/// |
| 114 | +/// # Flash Endurance |
| 115 | +/// Flash memory has limited write/erase cycles (typically 10,000-100,000 cycles). |
| 116 | +/// This function contributes to flash wear and should only be used for legitimate |
| 117 | +/// firmware updates to preserve flash lifetime. |
7 | 118 | pub fn rf_ota_save_data(data: &[u8]) -> OtaState
|
8 | 119 | {
|
| 120 | + // Calculate target flash address: base OTA region + current write offset |
9 | 121 | let addr = OTA_UPDATE_CURRENT_FLASH_ADDRESS.get() + FLASH_ADR_LIGHT_NEW_FW;
|
| 122 | + |
| 123 | + // Write the firmware data packet to flash memory |
10 | 124 | flash_write_page(addr, data.len() as u32, data.as_ptr());
|
11 | 125 |
|
| 126 | + // Allocate temporary buffer for verification read (16 bytes max packet size) |
12 | 127 | let mut tmp = [0u8; 0x10];
|
| 128 | + |
| 129 | + // Read back the written data for verification |
13 | 130 | flash_read_page(addr, data.len() as u32, tmp.as_mut_ptr());
|
14 | 131 |
|
| 132 | + // Verify data integrity by comparing original data with read-back data |
15 | 133 | if data == &tmp[..data.len()] {
|
| 134 | + // Write verification successful - advance write pointer for next packet |
16 | 135 | OTA_UPDATE_CURRENT_FLASH_ADDRESS.set(OTA_UPDATE_CURRENT_FLASH_ADDRESS.get() + data.len() as u32);
|
17 | 136 | return OtaState::Continue;
|
18 | 137 | } else {
|
| 138 | + // Write verification failed - return error to abort update |
19 | 139 | return OtaState::Error;
|
20 | 140 | }
|
21 | 141 | }
|
0 commit comments