1 // Copyright 2020 The Pigweed Authors
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
7 // https://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
19 #include "pw_containers/vector.h"
20 #include "pw_kvs/flash_memory.h"
21 #include "pw_kvs/key_value_store.h"
22 #include "pw_status/status.h"
24 #ifndef PW_KVS_RECORD_PARTITION_STATS
25 // PW_KVS_RECORD_PARTITION_STATS enables saving stats.
26 #define PW_KVS_RECORD_PARTITION_STATS 0
27 #endif // PW_KVS_RECORD_PARTITION_STATS
31 class FlashPartitionWithStats : public FlashPartition {
33 // Save flash partition and KVS storage stats. Does not save if
34 // sector_counters_ is zero.
35 Status SaveStorageStats(const KeyValueStore& kvs, const char* label);
37 using FlashPartition::Erase;
39 Status Erase(Address address, size_t num_sectors) override;
41 std::span<size_t> sector_erase_counters() {
42 return std::span(sector_counters_.data(), sector_counters_.size());
45 size_t min_erase_count() const {
46 if (sector_counters_.empty()) {
49 return *std::min_element(sector_counters_.begin(), sector_counters_.end());
52 size_t max_erase_count() const {
53 if (sector_counters_.empty()) {
56 return *std::max_element(sector_counters_.begin(), sector_counters_.end());
59 size_t average_erase_count() const {
60 return sector_counters_.empty()
62 : total_erase_count() / sector_counters_.size();
65 size_t total_erase_count() const {
66 return std::accumulate(sector_counters_.begin(), sector_counters_.end(), 0);
69 void ResetCounters() { sector_counters_.assign(sector_count(), 0); }
72 FlashPartitionWithStats(
73 Vector<size_t>& sector_counters,
75 uint32_t start_sector_index,
76 uint32_t sector_count,
77 uint32_t alignment_bytes = 0, // Defaults to flash alignment
78 PartitionPermission permission = PartitionPermission::kReadAndWrite)
79 : FlashPartition(flash,
84 sector_counters_(sector_counters) {
85 sector_counters_.assign(FlashPartition::sector_count(), 0);
89 Vector<size_t>& sector_counters_;
92 template <size_t kMaxSectors>
93 class FlashPartitionWithStatsBuffer : public FlashPartitionWithStats {
95 FlashPartitionWithStatsBuffer(
97 uint32_t start_sector_index,
98 uint32_t sector_count,
99 uint32_t alignment_bytes = 0, // Defaults to flash alignment
100 PartitionPermission permission = PartitionPermission::kReadAndWrite)
101 : FlashPartitionWithStats(sector_counters_,
108 FlashPartitionWithStatsBuffer(FlashMemory* flash)
109 : FlashPartitionWithStatsBuffer(
110 flash, 0, flash->sector_count(), flash->alignment_bytes()) {}
113 // If PW_KVS_RECORD_PARTITION_STATS is not set, use zero size vector which
114 // will not save any stats.
115 Vector<size_t, PW_KVS_RECORD_PARTITION_STATS ? kMaxSectors : 0>
119 } // namespace pw::kvs