Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/libraries/AP_FlashStorage/AP_FlashStorage.h
Views: 1798
/*1Please contribute your ideas! See https://ardupilot.org/dev for details23This program is free software: you can redistribute it and/or modify4it under the terms of the GNU General Public License as published by5the Free Software Foundation, either version 3 of the License, or6(at your option) any later version.78This program is distributed in the hope that it will be useful,9but WITHOUT ANY WARRANTY; without even the implied warranty of10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11GNU General Public License for more details.1213You should have received a copy of the GNU General Public License14along with this program. If not, see <http://www.gnu.org/licenses/>.15*/16/*17a class to allow for FLASH to be used as a memory backed storage18backend for any HAL. The basic methodology is to use a log based19storage system over two flash sectors. Key design elements:2021- erase of sectors only called on init, as erase will lock the flash22and prevent code execution2324- write using log based system2526- read requires scan of all log elements. This is expected to be called rarely2728- assumes flash that erases to 0xFF and where writing can only clear29bits, not set them3031- assumes flash sectors are much bigger than storage size. If they32aren't then caller can aggregate multiple sectors. Designed for33128k flash sectors with 16k storage size.3435- assumes two flash sectors are available36*/37#pragma once3839#include <AP_HAL/AP_HAL.h>4041/*42we support 3 different types of flash which have different restrictions43*/44#define AP_FLASHSTORAGE_TYPE_F1 1 // F1 and F345#define AP_FLASHSTORAGE_TYPE_F4 2 // F4 and F746#define AP_FLASHSTORAGE_TYPE_H7 3 // H747#define AP_FLASHSTORAGE_TYPE_G4 4 // G44849#ifndef AP_FLASHSTORAGE_TYPE50#if defined(STM32F1) || defined(STM32F3)51/*52the STM32F1 and STM32F3 can't change individual bits from 1 to 053unless all bits in the 16 bit word are 154*/55#define AP_FLASHSTORAGE_TYPE AP_FLASHSTORAGE_TYPE_F156#elif defined(STM32H7)57/*58STM32H7 can only write in 32 byte chunks, and must only write when all bits are 159*/60#define AP_FLASHSTORAGE_TYPE AP_FLASHSTORAGE_TYPE_H761#elif defined(STM32G4) || defined(STM32L4) || defined(STM32L4PLUS)62/*63STM32G4 can only write in 8 byte chunks, and must only write when all bits are 164*/65#define AP_FLASHSTORAGE_TYPE AP_FLASHSTORAGE_TYPE_G466#else // F4, F767/*68STM32HF4 and STM32H7 can update bits from 1 to 069*/70#define AP_FLASHSTORAGE_TYPE AP_FLASHSTORAGE_TYPE_F471#endif72#endif7374/*75The StorageManager holds the layout of non-volatile storage76*/77class AP_FlashStorage {78private:79#if AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_H780// need to write in 32 byte chunks, with 2 byte header81static const uint8_t block_size = 30;82static const uint8_t max_write = block_size;83#elif AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_G484// write in 8 byte chunks, with 2 byte header85static const uint8_t block_size = 6;86static const uint8_t max_write = block_size;87#else88static const uint8_t block_size = 8;89static const uint8_t max_write = 64;90#endif91static const uint16_t num_blocks = (HAL_STORAGE_SIZE+(block_size-1)) / block_size;9293public:94// caller provided function to write to a flash sector95FUNCTOR_TYPEDEF(FlashWrite, bool, uint8_t , uint32_t , const uint8_t *, uint16_t );9697// caller provided function to read from a flash sector. Only called on init()98FUNCTOR_TYPEDEF(FlashRead, bool, uint8_t , uint32_t , uint8_t *, uint16_t );99100// caller provided function to erase a flash sector. Only called from init()101FUNCTOR_TYPEDEF(FlashErase, bool, uint8_t );102103// caller provided function to indicate if erasing is allowed104FUNCTOR_TYPEDEF(FlashEraseOK, bool);105106// constructor.107AP_FlashStorage(uint8_t *mem_buffer, // buffer of storage_size bytes108uint32_t flash_sector_size, // size of each flash sector in bytes109FlashWrite flash_write, // function to write to flash110FlashRead flash_read, // function to read from flash111FlashErase flash_erase, // function to erase flash112FlashEraseOK flash_erase_ok); // function to check if erasing allowed113114// initialise storage, filling mem_buffer with current contents115bool init(void);116117// erase sectors and re-initialise118bool erase(void) WARN_IF_UNUSED {119return erase_all();120}121122// re-initialise storage, using current mem_buffer123bool re_initialise(void) WARN_IF_UNUSED;124125// switch full sector - should only be called when safe to have CPU126// offline for considerable periods as an erase will be needed127bool switch_full_sector(void) WARN_IF_UNUSED;128129// write some data to storage from mem_buffer130bool write(uint16_t offset, uint16_t length) WARN_IF_UNUSED;131132// fixed storage size133static const uint16_t storage_size = HAL_STORAGE_SIZE;134135private:136uint8_t *mem_buffer;137const uint32_t flash_sector_size;138FlashWrite flash_write;139FlashRead flash_read;140FlashErase flash_erase;141FlashEraseOK flash_erase_ok;142143uint8_t current_sector;144uint32_t write_offset;145uint32_t reserved_space;146bool write_error;147148// 24 bit signature149#if AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_F4150static const uint32_t signature = 0x51685B;151#elif AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_F1152static const uint32_t signature = 0x51;153#elif AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_H7154static const uint32_t signature = 0x51685B62;155#elif AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_G4156static const uint32_t signature = 0x1586B562;157#else158#error "Unknown AP_FLASHSTORAGE_TYPE"159#endif160161// sector states, representation depends on storage type162enum SectorState {163SECTOR_STATE_AVAILABLE = 1,164SECTOR_STATE_IN_USE = 2,165SECTOR_STATE_FULL = 3,166SECTOR_STATE_INVALID = 4167};168169// header in first word of each sector170struct sector_header {171#if AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_F4172uint32_t state1:8;173uint32_t signature1:24;174#elif AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_F1175uint32_t state1:32;176uint32_t signature1:16;177#elif AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_H7178// needs to be 96 bytes on H7 to support 3 states179uint32_t state1;180uint32_t signature1;181uint32_t pad1[6];182uint32_t state2;183uint32_t signature2;184uint32_t pad2[6];185uint32_t state3;186uint32_t signature3;187uint32_t pad3[6];188#elif AP_FLASHSTORAGE_TYPE == AP_FLASHSTORAGE_TYPE_G4189// needs to be 24 bytes on G4 to support 3 states190uint32_t state1;191uint32_t signature1;192uint32_t state2;193uint32_t signature2;194uint32_t state3;195uint32_t signature3;196#endif197bool signature_ok(void) const;198SectorState get_state() const;199void set_state(SectorState state);200};201202203enum BlockState {204BLOCK_STATE_AVAILABLE = 0x3,205BLOCK_STATE_WRITING = 0x1,206BLOCK_STATE_VALID = 0x0207};208209// header of each block of data210struct block_header {211uint16_t state:2;212uint16_t block_num:11;213uint16_t num_blocks_minus_one:3;214};215216// amount of space needed to write full storage217static const uint32_t reserve_size = (storage_size / max_write) * (sizeof(block_header) + max_write) + max_write;218219// load data from a sector220bool load_sector(uint8_t sector) WARN_IF_UNUSED;221222// erase a sector and write header223bool erase_sector(uint8_t sector, bool mark_available) WARN_IF_UNUSED;224225// erase all sectors and reset226bool erase_all() WARN_IF_UNUSED;227228// write all of mem_buffer to current sector229bool write_all() WARN_IF_UNUSED;230231// return true if all bytes are zero232bool all_zero(uint16_t ofs, uint16_t size) WARN_IF_UNUSED;233234// switch to next sector for writing235bool switch_sectors(void) WARN_IF_UNUSED;236237// _switch_full_sector is protected by switch_full_sector to avoid238// an infinite recursion problem; switch_full_sector calls239// write() which can call switch_full_sector. This has been seen240// in practice.241bool protected_switch_full_sector(void) WARN_IF_UNUSED;242bool in_switch_full_sector;243};244245246