LCOV - code coverage report
Current view: top level - AP_FlashStorage - AP_FlashStorage.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 135 244 55.3 %
Date: 2026-09-09 11:02:08 Functions: 9 15 60.0 %

          Line data    Source code
       1             : /*
       2             :    Please contribute your ideas! See https://ardupilot.club/dev for details
       3             : 
       4             :    This program is free software: you can redistribute it and/or modify
       5             :    it under the terms of the GNU General Public License as published by
       6             :    the Free Software Foundation, either version 3 of the License, or
       7             :    (at your option) any later version.
       8             : 
       9             :    This program is distributed in the hope that it will be useful,
      10             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :    GNU General Public License for more details.
      13             : 
      14             :    You should have received a copy of the GNU General Public License
      15             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include <AP_HAL/AP_HAL.h>
      19             : #include <AP_FlashStorage/AP_FlashStorage.h>
      20             : #include <AP_Math/AP_Math.h>
      21             : #include <AP_InternalError/AP_InternalError.h>
      22             : #include <stdio.h>
      23             : 
      24             : #define FLASHSTORAGE_DEBUG 0
      25             : 
      26             : #if FLASHSTORAGE_DEBUG
      27             : #define debug(fmt, args...)  do { printf(fmt, ##args); } while(0)
      28             : #else
      29             : #define debug(fmt, args...)  do { } while(0)
      30             : #endif
      31             : 
      32             : // constructor.
      33        2145 : AP_FlashStorage::AP_FlashStorage(uint8_t *_mem_buffer,
      34             :                                  uint32_t _flash_sector_size,
      35             :                                  FlashWrite _flash_write,
      36             :                                  FlashRead _flash_read,
      37             :                                  FlashErase _flash_erase,
      38        2145 :                                  FlashEraseOK _flash_erase_ok) :
      39        2145 :     mem_buffer(_mem_buffer),
      40        2145 :     flash_sector_size(_flash_sector_size),
      41        2145 :     flash_write(_flash_write),
      42        2145 :     flash_read(_flash_read),
      43        2145 :     flash_erase(_flash_erase),
      44        2145 :     flash_erase_ok(_flash_erase_ok) {}
      45             : 
      46             : // initialise storage
      47           3 : bool AP_FlashStorage::init(void)
      48             : {
      49             :     debug("running init()\n");
      50             : 
      51             :     // start with empty memory buffer
      52           3 :     memset(mem_buffer, 0, storage_size);
      53             : 
      54             :     // find state of sectors
      55             :     struct sector_header header[2];
      56             : 
      57             :     // read headers and possibly initialise if bad signature
      58           7 :     for (uint8_t i=0; i<2; i++) {
      59           5 :         if (!flash_read(i, 0, (uint8_t *)&header[i], sizeof(header[i]))) {
      60           0 :             return false;
      61             :         }
      62           5 :         bool bad_header = !header[i].signature_ok();
      63           5 :         enum SectorState state = header[i].get_state();
      64           5 :         if (state != SECTOR_STATE_AVAILABLE &&
      65           1 :             state != SECTOR_STATE_IN_USE &&
      66             :             state != SECTOR_STATE_FULL) {
      67           1 :             bad_header = true;
      68             :         }
      69             : 
      70             :         // initialise if bad header
      71           5 :         if (bad_header) {
      72           1 :             return erase_all();
      73             :         }
      74             :     }
      75             : 
      76             :     // work out the first sector to read from using sector states
      77           2 :     enum SectorState states[2] {header[0].get_state(), header[1].get_state()};
      78             :     uint8_t first_sector;
      79             : 
      80           2 :     if (states[0] == states[1]) {
      81           0 :         if (states[0] != SECTOR_STATE_AVAILABLE) {
      82           0 :             return erase_all();
      83             :         }
      84           0 :         first_sector = 0;
      85           2 :     } else if (states[0] == SECTOR_STATE_FULL) {
      86           0 :         first_sector = 0;
      87           2 :     } else if (states[1] == SECTOR_STATE_FULL) {
      88           0 :         first_sector = 1;
      89           2 :     } else if (states[0] == SECTOR_STATE_IN_USE) {
      90           2 :         first_sector = 0;
      91           0 :     } else if (states[1] == SECTOR_STATE_IN_USE) {
      92           0 :         first_sector = 1;
      93             :     } else {
      94             :         // doesn't matter which is first
      95           0 :         first_sector = 0;
      96             :     }
      97             : 
      98             :     // update current sector in case first sector has changed
      99           2 :     current_sector = first_sector;
     100             : 
     101             :     // load data from any current sectors
     102           6 :     for (uint8_t i=0; i<2; i++) {
     103           4 :         uint8_t sector = (first_sector + i) & 1;
     104           4 :         if (states[sector] == SECTOR_STATE_IN_USE ||
     105           2 :             states[sector] == SECTOR_STATE_FULL) {
     106           2 :             if (!load_sector(sector)) {
     107           0 :                 return erase_all();
     108             :             }
     109             :         }
     110             :     }
     111             : 
     112             :     // clear any write error
     113           2 :     write_error = false;
     114           2 :     reserved_space = 0;
     115             :     
     116             :     // if the first sector is full then write out all data so we can erase it
     117           2 :     if (states[first_sector] == SECTOR_STATE_FULL) {
     118           0 :         current_sector = first_sector ^ 1;
     119           0 :         if (!write_all()) {
     120           0 :             return erase_all();
     121             :         }
     122             :     }
     123             : 
     124             :     // erase any sectors marked full
     125           6 :     for (uint8_t i=0; i<2; i++) {
     126           4 :         if (states[i] == SECTOR_STATE_FULL) {
     127           0 :             if (!erase_sector(i, true)) {
     128           0 :                 return false;
     129             :             }
     130             :         }
     131             :     }
     132             : 
     133           2 :     reserved_space = 0;
     134             :     
     135             :     // ready to use
     136           2 :     return true;
     137             : }
     138             : 
     139             : 
     140             : 
     141             : // switch full sector - should only be called when safe to have CPU
     142             : // offline for considerable periods as an erase will be needed
     143           0 : bool AP_FlashStorage::switch_full_sector(void)
     144             : {
     145             :     debug("running switch_full_sector()\n");
     146             : 
     147           0 :     if (in_switch_full_sector) {
     148           0 :         INTERNAL_ERROR(AP_InternalError::error_t::switch_full_sector_recursion);
     149           0 :         return false;
     150             :     }
     151           0 :     in_switch_full_sector = true;
     152           0 :     bool ret = protected_switch_full_sector();
     153           0 :     in_switch_full_sector = false;
     154           0 :     return ret;
     155             : }
     156             : 
     157             : // protected_switch_full_sector is protected by switch_full_sector to
     158             : // avoid an infinite recursion problem; switch_full_sector calls
     159             : // write() which can call switch_full_sector.  This has been seen in
     160             : // practice, and while it might be caused by corruption... corruption
     161             : // happens.
     162           0 : bool AP_FlashStorage::protected_switch_full_sector(void)
     163             : {
     164             :     // clear any write error
     165           0 :     write_error = false;
     166           0 :     reserved_space = 0;
     167             :     
     168           0 :     if (!write_all()) {
     169           0 :         return false;
     170             :     }
     171             : 
     172           0 :     if (!erase_sector(current_sector ^ 1, true)) {
     173           0 :         return false;
     174             :     }
     175             : 
     176           0 :     return switch_sectors();
     177             : }
     178             : 
     179             : // write some data to virtual EEPROM
     180          63 : bool AP_FlashStorage::write(uint16_t offset, uint16_t length)
     181             : {
     182          63 :     if (write_error) {
     183           0 :         return false;
     184             :     }
     185             :     //debug("write at %u for %u write_offset=%u\n", offset, length, write_offset);
     186             :     
     187          80 :     while (length > 0) {
     188          78 :         uint8_t n = max_write;
     189             : #if AP_FLASHSTORAGE_TYPE != AP_FLASHSTORAGE_TYPE_H7 && AP_FLASHSTORAGE_TYPE != AP_FLASHSTORAGE_TYPE_G4
     190             :         if (length < n) {
     191             :             n = length;
     192             :         }
     193             : #endif
     194             : 
     195          78 :         const uint32_t space_available = flash_sector_size - write_offset;
     196          78 :         const uint32_t space_required = sizeof(struct block_header) + max_write + reserved_space;
     197          78 :         if (space_available < space_required) {
     198           0 :             if (!switch_sectors()) {
     199           0 :                 if (!flash_erase_ok()) {
     200           0 :                     return false;
     201             :                 }
     202           0 :                 if (!switch_full_sector()) {
     203           0 :                     return false;                    
     204             :                 }
     205             :             }
     206             :         }
     207             : 
     208             :         struct PACKED {
     209             :             struct block_header header;
     210             :             uint8_t data[max_write];
     211             :         } blk;
     212             : 
     213          78 :         blk.header.state = BLOCK_STATE_WRITING;
     214          78 :         blk.header.block_num = offset / block_size;
     215          78 :         blk.header.num_blocks_minus_one = ((n + (block_size - 1)) / block_size)-1;
     216             : 
     217          78 :         uint16_t block_ofs = blk.header.block_num*block_size;
     218          78 :         uint16_t block_nbytes = (blk.header.num_blocks_minus_one+1)*block_size;
     219             : 
     220          78 :         memcpy(blk.data, &mem_buffer[block_ofs], block_nbytes);
     221             : 
     222             : #if AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_F4
     223             :         if (!flash_write(current_sector, write_offset, (uint8_t*)&blk.header, sizeof(blk.header))) {
     224             :             return false;
     225             :         }
     226             :         if (!flash_write(current_sector, write_offset+sizeof(blk.header), blk.data, block_nbytes)) {
     227             :             return false;
     228             :         }
     229             :         blk.header.state = BLOCK_STATE_VALID;
     230             :         if (!flash_write(current_sector, write_offset, (uint8_t*)&blk.header, sizeof(blk.header))) {
     231             :             return false;
     232             :         }
     233             : #elif AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_F1
     234             :         blk.header.state = BLOCK_STATE_VALID;
     235             :         if (!flash_write(current_sector, write_offset, (uint8_t*)&blk, sizeof(blk.header) + block_nbytes)) {
     236             :             return false;
     237             :         }
     238             : #elif AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_H7 || AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_G4
     239          78 :         blk.header.state = BLOCK_STATE_VALID;
     240          78 :         if (!flash_write(current_sector, write_offset, (uint8_t*)&blk, sizeof(blk.header) + max_write)) {
     241           0 :             return false;
     242             :         }
     243             : #endif
     244             : 
     245          78 :         write_offset += sizeof(blk.header) + block_nbytes;
     246             : 
     247          78 :         uint8_t n2 = block_nbytes - (offset % block_size);
     248             :         //debug("write_block at %u for %u n2=%u\n", block_ofs, block_nbytes, n2);
     249          78 :         if (n2 > length) {
     250          61 :             break;
     251             :         }
     252          17 :         offset += n2;
     253          17 :         length -= n2;
     254             :     }
     255             : 
     256             :     //debug("write_offset %u\n", write_offset);
     257             : 
     258             :     // handle wrap to next sector
     259             :     // write data
     260             :     // write header word
     261          63 :     return true;
     262             : }
     263             : 
     264             : /*
     265             :   load all data from a flash sector into mem_buffer
     266             :  */
     267           2 : bool AP_FlashStorage::load_sector(uint8_t sector)
     268             : {
     269           2 :     uint32_t ofs = sizeof(sector_header);
     270         137 :     while (ofs < flash_sector_size - sizeof(struct block_header)) {
     271             :         struct block_header header;
     272         137 :         if (!flash_read(sector, ofs, (uint8_t *)&header, sizeof(header))) {
     273           2 :             return false;
     274             :         }
     275         137 :         enum BlockState state = (enum BlockState)header.state;
     276             : 
     277         137 :         switch (state) {
     278           2 :         case BLOCK_STATE_AVAILABLE:
     279             :             // we've reached the end
     280           2 :             write_offset = ofs;
     281           2 :             return true;
     282             : 
     283           0 :         case BLOCK_STATE_WRITING: {
     284             :             /*
     285             :               we were interrupted while writing a block. We can't
     286             :               re-use the data in this block as it may have some bits
     287             :               that are not set to 1, so by flash rules can't be set to
     288             :               an arbitrary value. So we skip over this block, leaving
     289             :               a gap. The gap size is limited to (7+1)*8=64 bytes. That
     290             :               gap won't be recovered until we next do an erase of this
     291             :               sector
     292             :              */
     293           0 :             uint16_t block_nbytes = (header.num_blocks_minus_one+1)*block_size;
     294           0 :             ofs += block_nbytes + sizeof(header);
     295           0 :             break;
     296             :         }
     297             :             
     298         135 :         case BLOCK_STATE_VALID: {
     299         135 :             uint16_t block_nbytes = (header.num_blocks_minus_one+1)*block_size;
     300         135 :             uint16_t block_ofs = header.block_num*block_size;
     301         135 :             if (block_ofs + block_nbytes > storage_size) {
     302             :                 // the data is invalid (out of range)
     303           0 :                 return false;
     304             :             }
     305         135 :             if (!flash_read(sector, ofs+sizeof(header), &mem_buffer[block_ofs], block_nbytes)) {
     306           0 :                 return false;
     307             :             }
     308             :             //debug("read at %u for %u\n", block_ofs, block_nbytes);
     309         135 :             ofs += block_nbytes + sizeof(header);
     310         135 :             break;
     311             :         }
     312           0 :         default:
     313             :             // invalid state
     314           0 :             return false;
     315             :         }
     316             : #if AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_H7
     317             :         // offsets must be advanced to a multiple of 32 on H7
     318         135 :         ofs = (ofs + 31U) & ~31U;
     319             : #elif AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_G4
     320             :         // offsets must be advanced to a multiple of 8 on G4
     321             :         ofs = (ofs + 7U) & ~7U;
     322             : #endif
     323             :     }
     324           0 :     write_offset = ofs;
     325           0 :     return true;
     326             : }
     327             : 
     328             : /*
     329             :   erase one sector
     330             :  */
     331           2 : bool AP_FlashStorage::erase_sector(uint8_t sector, bool mark_available)
     332             : {
     333           2 :     if (!flash_erase(sector)) {
     334           0 :         return false;
     335             :     }
     336           2 :     if (!mark_available) {
     337           1 :         return true;
     338             :     }
     339             :     struct sector_header header;
     340           1 :     header.set_state(SECTOR_STATE_AVAILABLE);
     341           1 :     return flash_write(sector, 0, (const uint8_t *)&header, sizeof(header));
     342             : }
     343             : 
     344             : /*
     345             :   erase both sectors
     346             :  */
     347           1 : bool AP_FlashStorage::erase_all(void)
     348             : {
     349           1 :     write_error = false;
     350             : 
     351           1 :     current_sector = 0;
     352           1 :     write_offset = sizeof(struct sector_header);
     353             :     
     354           1 :     if (!erase_sector(0, current_sector!=0)) {
     355           0 :         return false;
     356             :     }
     357           1 :     if (!erase_sector(1, current_sector!=1)) {
     358           0 :         return false;
     359             :     }
     360             :     
     361             :     // mark current sector as in-use
     362             :     struct sector_header header;
     363           1 :     header.set_state(SECTOR_STATE_IN_USE);
     364           1 :     return flash_write(current_sector, 0, (const uint8_t *)&header, sizeof(header));    
     365             : }
     366             : 
     367             : /*
     368             :   write all of mem_buffer to current sector
     369             :  */
     370           0 : bool AP_FlashStorage::write_all()
     371             : {
     372             :     debug("write_all to sector %u at %u with reserved_space=%u\n",
     373             :            current_sector, write_offset, reserved_space);
     374           0 :     for (uint16_t ofs=0; ofs<storage_size; ofs += max_write) {
     375             :         // local variable needed to overcome problem with MIN() macro and -O0
     376           0 :         const uint8_t max_write_local = max_write;
     377           0 :         uint8_t n = MIN(max_write_local, storage_size-ofs);
     378           0 :         if (!all_zero(ofs, n)) {
     379           0 :             if (!write(ofs, n)) {
     380           0 :                 return false;
     381             :             }
     382             :         }
     383             :     }
     384           0 :     return true;
     385             : }
     386             : 
     387             : // return true if all bytes are zero
     388           0 : bool AP_FlashStorage::all_zero(uint16_t ofs, uint16_t size)
     389             : {
     390           0 :     while (size--) {
     391           0 :         if (mem_buffer[ofs++] != 0) {
     392           0 :             return false;
     393             :         }
     394             :     }
     395           0 :     return true;
     396             : }
     397             : 
     398             : // switch to next sector for writing
     399           0 : bool AP_FlashStorage::switch_sectors(void)
     400             : {
     401           0 :     if (reserved_space != 0) {
     402             :         // other sector is already full
     403             :         debug("both sectors are full\n");
     404           0 :         return false;
     405             :     }
     406             : 
     407             :     struct sector_header header;
     408             : 
     409           0 :     uint8_t new_sector = current_sector ^ 1;
     410             :     debug("switching to sector %u\n", new_sector);
     411             :     
     412             :     // check sector is available
     413           0 :     if (!flash_read(new_sector, 0, (uint8_t *)&header, sizeof(header))) {
     414           0 :         return false;
     415             :     }
     416           0 :     if (!header.signature_ok()) {
     417           0 :         write_error = true;
     418           0 :         return false;
     419             :     }
     420           0 :     if (SECTOR_STATE_AVAILABLE != header.get_state()) {
     421           0 :         write_error = true;
     422             :         debug("new sector unavailable; state=0x%02x\n", (unsigned)header.get_state());
     423           0 :         return false;
     424             :     }
     425             : 
     426             :     // mark current sector as full. This needs to be done before we
     427             :     // mark the new sector as in-use so that a power failure between
     428             :     // the two steps doesn't leave us with an erase on the
     429             :     // reboot. Thanks to night-ghost for spotting this.
     430           0 :     header.set_state(SECTOR_STATE_FULL);
     431           0 :     if (!flash_write(current_sector, 0, (const uint8_t *)&header, sizeof(header))) {
     432           0 :         return false;
     433             :     }
     434             : 
     435             :     // mark new sector as in-use
     436           0 :     header.set_state(SECTOR_STATE_IN_USE);
     437           0 :     if (!flash_write(new_sector, 0, (const uint8_t *)&header, sizeof(header))) {
     438           0 :         return false;
     439             :     }
     440             : 
     441             :     // switch sectors
     442           0 :     current_sector = new_sector;
     443             :         
     444             :     // we need to reserve some space in next sector to ensure we can successfully do a
     445             :     // full write out on init()
     446           0 :     reserved_space = reserve_size;
     447             :     
     448           0 :     write_offset = sizeof(header);
     449           0 :     return true;    
     450             : }
     451             : 
     452             : /*
     453             :   re-initialise, using current mem_buffer
     454             :  */
     455           0 : bool AP_FlashStorage::re_initialise(void)
     456             : {
     457           0 :     if (!flash_erase_ok()) {
     458           0 :         return false;
     459             :     }
     460           0 :     if (!erase_all()) {
     461           0 :         return false;        
     462             :     }
     463           0 :     return write_all();
     464             : }
     465             : 
     466             : #if AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_H7
     467             : /*
     468             :   H7 specific sector header functions
     469             :  */
     470           5 : bool AP_FlashStorage::sector_header::signature_ok(void) const
     471             : {
     472          35 :     for (uint8_t i=0; i<ARRAY_SIZE(pad1); i++) {
     473          30 :         if (pad1[i] != 0xFFFFFFFFU || pad2[i] != 0xFFFFFFFFU || pad3[i] != 0xFFFFFFFFU) {
     474           0 :             return false;
     475             :         }
     476             :     }
     477           5 :     return signature1 == signature;
     478             : }
     479             : 
     480           9 : AP_FlashStorage::SectorState AP_FlashStorage::sector_header::get_state(void) const
     481             : {
     482           9 :     if (state1 == 0xFFFFFFF1 &&
     483           8 :         state2 == 0xFFFFFFFF &&
     484           4 :         state3 == 0xFFFFFFFF &&
     485           4 :         signature1 == signature &&
     486           4 :         signature2 == 0xFFFFFFFF &&
     487           4 :         signature3 == 0xFFFFFFFF) {
     488           4 :         return SECTOR_STATE_AVAILABLE;
     489             :     }
     490           5 :     if (state1 == 0xFFFFFFF1 &&
     491           4 :         state2 == 0xFFFFFFF2 &&
     492           4 :         state3 == 0xFFFFFFFF &&
     493           4 :         signature1 == signature &&
     494           4 :         signature2 == signature &&
     495           4 :         signature3 == 0xFFFFFFFF) {
     496           4 :         return SECTOR_STATE_IN_USE;
     497             :     }
     498           1 :     if (state1 == 0xFFFFFFF1 &&
     499           0 :         state2 == 0xFFFFFFF2 &&
     500           0 :         state3 == 0xFFFFFFF3 &&
     501           0 :         signature1 == signature &&
     502           0 :         signature2 == signature &&
     503           0 :         signature3 == signature) {
     504           0 :         return SECTOR_STATE_FULL;
     505             :     }
     506           1 :     return SECTOR_STATE_INVALID;
     507             : }
     508             : 
     509           2 : void AP_FlashStorage::sector_header::set_state(SectorState state)
     510             : {
     511           2 :     memset(pad1, 0xff, sizeof(pad1));
     512           2 :     memset(pad2, 0xff, sizeof(pad2));
     513           2 :     memset(pad3, 0xff, sizeof(pad3));
     514           2 :     switch (state) {
     515           1 :     case SECTOR_STATE_AVAILABLE:
     516           1 :         signature1 = signature;
     517           1 :         signature2 = 0xFFFFFFFF;
     518           1 :         signature3 = 0xFFFFFFFF;
     519           1 :         state1 = 0xFFFFFFF1;
     520           1 :         state2 = 0xFFFFFFFF;
     521           1 :         state3 = 0xFFFFFFFF;
     522           1 :         break;
     523           1 :     case SECTOR_STATE_IN_USE:
     524           1 :         signature1 = signature;
     525           1 :         signature2 = signature;
     526           1 :         signature3 = 0xFFFFFFFF;
     527           1 :         state1 = 0xFFFFFFF1;
     528           1 :         state2 = 0xFFFFFFF2;
     529           1 :         state3 = 0xFFFFFFFF;
     530           1 :         break;
     531           0 :     case SECTOR_STATE_FULL:
     532           0 :         signature1 = signature;
     533           0 :         signature2 = signature;
     534           0 :         signature3 = signature;
     535           0 :         state1 = 0xFFFFFFF1;
     536           0 :         state2 = 0xFFFFFFF2;
     537           0 :         state3 = 0xFFFFFFF3;
     538           0 :         break;
     539           0 :     default:
     540           0 :         break;
     541             :     }
     542           2 : }
     543             : 
     544             : #elif AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_G4
     545             : /*
     546             :   G4 specific sector header functions
     547             :  */
     548             : bool AP_FlashStorage::sector_header::signature_ok(void) const
     549             : {
     550             :     return signature1 == signature;
     551             : }
     552             : 
     553             : AP_FlashStorage::SectorState AP_FlashStorage::sector_header::get_state(void) const
     554             : {
     555             :     if (state1 == 0xFFFFFFF1 &&
     556             :         state2 == 0xFFFFFFFF &&
     557             :         state3 == 0xFFFFFFFF &&
     558             :         signature1 == signature &&
     559             :         signature2 == 0xFFFFFFFF &&
     560             :         signature3 == 0xFFFFFFFF) {
     561             :         return SECTOR_STATE_AVAILABLE;
     562             :     }
     563             :     if (state1 == 0xFFFFFFF1 &&
     564             :         state2 == 0xFFFFFFF2 &&
     565             :         state3 == 0xFFFFFFFF &&
     566             :         signature1 == signature &&
     567             :         signature2 == signature &&
     568             :         signature3 == 0xFFFFFFFF) {
     569             :         return SECTOR_STATE_IN_USE;
     570             :     }
     571             :     if (state1 == 0xFFFFFFF1 &&
     572             :         state2 == 0xFFFFFFF2 &&
     573             :         state3 == 0xFFFFFFF3 &&
     574             :         signature1 == signature &&
     575             :         signature2 == signature &&
     576             :         signature3 == signature) {
     577             :         return SECTOR_STATE_FULL;
     578             :     }
     579             :     return SECTOR_STATE_INVALID;
     580             : }
     581             : 
     582             : void AP_FlashStorage::sector_header::set_state(SectorState state)
     583             : {
     584             :     switch (state) {
     585             :     case SECTOR_STATE_AVAILABLE:
     586             :         signature1 = signature;
     587             :         signature2 = 0xFFFFFFFF;
     588             :         signature3 = 0xFFFFFFFF;
     589             :         state1 = 0xFFFFFFF1;
     590             :         state2 = 0xFFFFFFFF;
     591             :         state3 = 0xFFFFFFFF;
     592             :         break;
     593             :     case SECTOR_STATE_IN_USE:
     594             :         signature1 = signature;
     595             :         signature2 = signature;
     596             :         signature3 = 0xFFFFFFFF;
     597             :         state1 = 0xFFFFFFF1;
     598             :         state2 = 0xFFFFFFF2;
     599             :         state3 = 0xFFFFFFFF;
     600             :         break;
     601             :     case SECTOR_STATE_FULL:
     602             :         signature1 = signature;
     603             :         signature2 = signature;
     604             :         signature3 = signature;
     605             :         state1 = 0xFFFFFFF1;
     606             :         state2 = 0xFFFFFFF2;
     607             :         state3 = 0xFFFFFFF3;
     608             :         break;
     609             :     default:
     610             :         break;
     611             :     }
     612             : }
     613             : 
     614             : #elif AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_F1
     615             : /*
     616             :   F1/F3 specific sector header functions
     617             :  */
     618             : bool AP_FlashStorage::sector_header::signature_ok(void) const
     619             : {
     620             :     return signature1 == signature;
     621             : }
     622             : 
     623             : AP_FlashStorage::SectorState AP_FlashStorage::sector_header::get_state(void) const
     624             : {
     625             :     if (state1 == 0xFFFFFFFF) {
     626             :         return SECTOR_STATE_AVAILABLE;
     627             :     }
     628             :     if (state1 == 0xFFFFFFF1) {
     629             :         return SECTOR_STATE_IN_USE;
     630             :     }
     631             :     if (state1 == 0xFFF2FFF1) {
     632             :         return SECTOR_STATE_FULL;
     633             :     }
     634             :     return SECTOR_STATE_INVALID;
     635             : }
     636             : 
     637             : void AP_FlashStorage::sector_header::set_state(SectorState state)
     638             : {
     639             :     signature1 = signature;
     640             :     switch (state) {
     641             :     case SECTOR_STATE_AVAILABLE:
     642             :         state1 = 0xFFFFFFFF;
     643             :         break;
     644             :     case SECTOR_STATE_IN_USE:
     645             :         state1 = 0xFFFFFFF1;
     646             :         break;
     647             :     case SECTOR_STATE_FULL:
     648             :         state1 = 0xFFF2FFF1;
     649             :         break;
     650             :     default:
     651             :         break;
     652             :     }
     653             : }
     654             : #elif AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_F4
     655             : /*
     656             :   F4 specific sector header functions
     657             :  */
     658             : bool AP_FlashStorage::sector_header::signature_ok(void) const
     659             : {
     660             :     return signature1 == signature;
     661             : }
     662             : 
     663             : AP_FlashStorage::SectorState AP_FlashStorage::sector_header::get_state(void) const
     664             : {
     665             :     if (state1 == 0xFF) {
     666             :         return SECTOR_STATE_AVAILABLE;
     667             :     }
     668             :     if (state1 == 0xFE) {
     669             :         return SECTOR_STATE_IN_USE;
     670             :     }
     671             :     if (state1 == 0xFC) {
     672             :         return SECTOR_STATE_FULL;
     673             :     }
     674             :     return SECTOR_STATE_INVALID;
     675             : }
     676             : 
     677             : void AP_FlashStorage::sector_header::set_state(SectorState state)
     678             : {
     679             :     signature1 = signature;
     680             :     switch (state) {
     681             :     case SECTOR_STATE_AVAILABLE:
     682             :         state1 = 0xFF;
     683             :         break;
     684             :     case SECTOR_STATE_IN_USE:
     685             :         state1 = 0xFE;
     686             :         break;
     687             :     case SECTOR_STATE_FULL:
     688             :         state1 = 0xFC;
     689             :         break;
     690             :     default:
     691             :         break;
     692             :     }
     693             : }
     694             : #endif

Generated by: LCOV version 1.14