Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1 | // Copyright 2020 The Pigweed Authors |
| 2 | // |
| 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 |
| 5 | // the License at |
| 6 | // |
| 7 | // https://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 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 |
| 13 | // the License. |
| 14 | #pragma once |
| 15 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 16 | #include <cstddef> |
| 17 | #include <cstdint> |
| 18 | #include <initializer_list> |
Wyatt Hepler | e2cbadf | 2020-06-22 11:21:45 -0700 | [diff] [blame] | 19 | #include <span> |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 20 | |
Wyatt Hepler | f298de4 | 2021-03-19 15:06:36 -0700 | [diff] [blame] | 21 | #include "pw_assert/assert.h" |
Wyatt Hepler | 1927c28 | 2020-02-11 16:45:02 -0800 | [diff] [blame] | 22 | #include "pw_kvs/alignment.h" |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 23 | #include "pw_status/status.h" |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 24 | #include "pw_status/status_with_size.h" |
| 25 | |
Rob Oliver | f61adbd | 2020-12-09 13:46:46 -0500 | [diff] [blame] | 26 | namespace pw { |
| 27 | namespace kvs { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 28 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 29 | enum class PartitionPermission : bool { |
| 30 | kReadOnly, |
| 31 | kReadAndWrite, |
| 32 | }; |
| 33 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 34 | class FlashMemory { |
| 35 | public: |
| 36 | // The flash address is in the range of: 0 to FlashSize. |
| 37 | typedef uint32_t Address; |
Armando Montanez | 28ec237 | 2020-08-17 16:31:41 -0700 | [diff] [blame] | 38 | |
| 39 | // TODO(pwbug/246): This can be constexpr when tokenized asserts are fixed. |
| 40 | FlashMemory(size_t sector_size, |
| 41 | size_t sector_count, |
| 42 | size_t alignment, |
| 43 | uint32_t start_address = 0, |
| 44 | uint32_t sector_start = 0, |
Rob Oliver | f61adbd | 2020-12-09 13:46:46 -0500 | [diff] [blame] | 45 | std::byte erased_memory_content = std::byte(0xFF)) |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 46 | : sector_size_(sector_size), |
| 47 | flash_sector_count_(sector_count), |
| 48 | alignment_(alignment), |
| 49 | start_address_(start_address), |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 50 | start_sector_(sector_start), |
Wyatt Hepler | 116d116 | 2020-02-06 09:42:59 -0800 | [diff] [blame] | 51 | erased_memory_content_(erased_memory_content) { |
Wyatt Hepler | ae222dc | 2020-10-14 10:46:27 -0700 | [diff] [blame] | 52 | PW_ASSERT(alignment_ != 0u); |
Wyatt Hepler | 116d116 | 2020-02-06 09:42:59 -0800 | [diff] [blame] | 53 | } |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 54 | |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 55 | virtual ~FlashMemory() = default; |
| 56 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 57 | virtual Status Enable() = 0; |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 58 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 59 | virtual Status Disable() = 0; |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 60 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 61 | virtual bool IsEnabled() const = 0; |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 62 | |
Wyatt Hepler | d78f7c6 | 2020-09-28 14:27:32 -0700 | [diff] [blame] | 63 | virtual Status SelfTest() { return Status::Unimplemented(); } |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 64 | |
| 65 | // Erase num_sectors starting at a given address. Blocking call. |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 66 | // Address should be on a sector boundary. Returns: |
Wyatt Hepler | cdd6dfc | 2020-02-18 12:04:04 -0800 | [diff] [blame] | 67 | // |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 68 | // OK - success |
| 69 | // DEADLINE_EXCEEDED - timeout |
| 70 | // INVALID_ARGUMENT - address is not sector-aligned |
| 71 | // OUT_OF_RANGE - erases past the end of the memory |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 72 | virtual Status Erase(Address flash_address, size_t num_sectors) = 0; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 73 | |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 74 | // Reads bytes from flash into buffer. Blocking call. Returns: |
Wyatt Hepler | cdd6dfc | 2020-02-18 12:04:04 -0800 | [diff] [blame] | 75 | // |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 76 | // OK - success |
| 77 | // DEADLINE_EXCEEDED - timeout |
| 78 | // OUT_OF_RANGE - write does not fit in the flash memory |
Wyatt Hepler | e2cbadf | 2020-06-22 11:21:45 -0700 | [diff] [blame] | 79 | virtual StatusWithSize Read(Address address, std::span<std::byte> output) = 0; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 80 | |
Wyatt Hepler | bab0e20 | 2020-02-04 07:40:08 -0800 | [diff] [blame] | 81 | StatusWithSize Read(Address address, void* buffer, size_t len) { |
Rob Oliver | f61adbd | 2020-12-09 13:46:46 -0500 | [diff] [blame] | 82 | return Read(address, |
| 83 | std::span<std::byte>(static_cast<std::byte*>(buffer), len)); |
Wyatt Hepler | bab0e20 | 2020-02-04 07:40:08 -0800 | [diff] [blame] | 84 | } |
| 85 | |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 86 | // Writes bytes to flash. Blocking call. Returns: |
Wyatt Hepler | cdd6dfc | 2020-02-18 12:04:04 -0800 | [diff] [blame] | 87 | // |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 88 | // OK - success |
| 89 | // DEADLINE_EXCEEDED - timeout |
| 90 | // INVALID_ARGUMENT - address or data size are not aligned |
| 91 | // OUT_OF_RANGE - write does not fit in the memory |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 92 | virtual StatusWithSize Write(Address destination_flash_address, |
Wyatt Hepler | e2cbadf | 2020-06-22 11:21:45 -0700 | [diff] [blame] | 93 | std::span<const std::byte> data) = 0; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 94 | |
Alexei Frolov | f0c2cdd | 2020-02-03 15:44:04 -0800 | [diff] [blame] | 95 | StatusWithSize Write(Address destination_flash_address, |
| 96 | const void* data, |
| 97 | size_t len) { |
Rob Oliver | f61adbd | 2020-12-09 13:46:46 -0500 | [diff] [blame] | 98 | return Write( |
| 99 | destination_flash_address, |
| 100 | std::span<const std::byte>(static_cast<const std::byte*>(data), len)); |
Alexei Frolov | f0c2cdd | 2020-02-03 15:44:04 -0800 | [diff] [blame] | 101 | } |
| 102 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 103 | // Convert an Address to an MCU pointer, this can be used for memory |
| 104 | // mapped reads. Return NULL if the memory is not memory mapped. |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 105 | virtual std::byte* FlashAddressToMcuAddress(Address) const { return nullptr; } |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 106 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 107 | // start_sector() is useful for FlashMemory instances where the |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 108 | // sector start is not 0. (ex.: cases where there are portions of flash |
| 109 | // that should be handled independently). |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 110 | constexpr uint32_t start_sector() const { return start_sector_; } |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 111 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 112 | constexpr size_t sector_size_bytes() const { return sector_size_; } |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 113 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 114 | constexpr size_t sector_count() const { return flash_sector_count_; } |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 115 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 116 | constexpr size_t alignment_bytes() const { return alignment_; } |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 117 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 118 | constexpr size_t size_bytes() const { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 119 | return sector_size_ * flash_sector_count_; |
| 120 | } |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 121 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 122 | // Address of the start of flash (the address of sector 0) |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 123 | constexpr uint32_t start_address() const { return start_address_; } |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 124 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 125 | constexpr std::byte erased_memory_content() const { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 126 | return erased_memory_content_; |
| 127 | } |
| 128 | |
| 129 | private: |
| 130 | const uint32_t sector_size_; |
| 131 | const uint32_t flash_sector_count_; |
David Rogers | ca59296 | 2020-07-01 09:21:54 -0700 | [diff] [blame] | 132 | const uint32_t alignment_; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 133 | const uint32_t start_address_; |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 134 | const uint32_t start_sector_; |
| 135 | const std::byte erased_memory_content_; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 136 | }; |
| 137 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 138 | class FlashPartition { |
| 139 | public: |
| 140 | // The flash address is in the range of: 0 to PartitionSize. |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 141 | using Address = uint32_t; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 142 | |
Wyatt Hepler | 1927c28 | 2020-02-11 16:45:02 -0800 | [diff] [blame] | 143 | // Implement Output for the Write method. |
| 144 | class Output final : public pw::Output { |
| 145 | public: |
| 146 | constexpr Output(FlashPartition& flash, FlashPartition::Address address) |
| 147 | : flash_(flash), address_(address) {} |
| 148 | |
Wyatt Hepler | ee6fd76 | 2020-03-09 08:32:19 -0700 | [diff] [blame] | 149 | private: |
Wyatt Hepler | e2cbadf | 2020-06-22 11:21:45 -0700 | [diff] [blame] | 150 | StatusWithSize DoWrite(std::span<const std::byte> data) override; |
Wyatt Hepler | ee6fd76 | 2020-03-09 08:32:19 -0700 | [diff] [blame] | 151 | |
| 152 | FlashPartition& flash_; |
| 153 | FlashPartition::Address address_; |
| 154 | }; |
| 155 | |
| 156 | // Implement Input for the Read method. |
| 157 | class Input final : public pw::Input { |
| 158 | public: |
| 159 | constexpr Input(FlashPartition& flash, FlashPartition::Address address) |
| 160 | : flash_(flash), address_(address) {} |
Wyatt Hepler | 1927c28 | 2020-02-11 16:45:02 -0800 | [diff] [blame] | 161 | |
| 162 | private: |
Wyatt Hepler | e2cbadf | 2020-06-22 11:21:45 -0700 | [diff] [blame] | 163 | StatusWithSize DoRead(std::span<std::byte> data) override; |
Wyatt Hepler | ee6fd76 | 2020-03-09 08:32:19 -0700 | [diff] [blame] | 164 | |
Wyatt Hepler | 1927c28 | 2020-02-11 16:45:02 -0800 | [diff] [blame] | 165 | FlashPartition& flash_; |
| 166 | FlashPartition::Address address_; |
| 167 | }; |
| 168 | |
Armando Montanez | 28ec237 | 2020-08-17 16:31:41 -0700 | [diff] [blame] | 169 | FlashPartition( |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 170 | FlashMemory* flash, |
| 171 | uint32_t start_sector_index, |
| 172 | uint32_t sector_count, |
Wyatt Hepler | 116d116 | 2020-02-06 09:42:59 -0800 | [diff] [blame] | 173 | uint32_t alignment_bytes = 0, // Defaults to flash alignment |
Paul Mathieu | 9a9ed13 | 2020-10-12 19:15:34 -0700 | [diff] [blame] | 174 | PartitionPermission permission = PartitionPermission::kReadAndWrite); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 175 | |
Wyatt Hepler | cdd6dfc | 2020-02-18 12:04:04 -0800 | [diff] [blame] | 176 | // Creates a FlashPartition that uses the entire flash with its alignment. |
Armando Montanez | 28ec237 | 2020-08-17 16:31:41 -0700 | [diff] [blame] | 177 | FlashPartition(FlashMemory* flash) |
Wyatt Hepler | cdd6dfc | 2020-02-18 12:04:04 -0800 | [diff] [blame] | 178 | : FlashPartition( |
| 179 | flash, 0, flash->sector_count(), flash->alignment_bytes()) {} |
| 180 | |
Ewout van Bekkum | 6ee135f | 2020-08-07 09:38:49 -0700 | [diff] [blame] | 181 | FlashPartition(FlashPartition&&) = default; |
Wyatt Hepler | e541e07 | 2020-02-14 09:10:53 -0800 | [diff] [blame] | 182 | FlashPartition(const FlashPartition&) = delete; |
| 183 | FlashPartition& operator=(const FlashPartition&) = delete; |
| 184 | |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 185 | virtual ~FlashPartition() = default; |
| 186 | |
Alexei Frolov | d5aa1c0 | 2020-02-03 17:23:51 -0800 | [diff] [blame] | 187 | // Performs any required partition or flash-level initialization. |
Wyatt Hepler | 1b3da3a | 2021-01-07 13:26:57 -0800 | [diff] [blame] | 188 | virtual Status Init() { return OkStatus(); } |
Alexei Frolov | d5aa1c0 | 2020-02-03 17:23:51 -0800 | [diff] [blame] | 189 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 190 | // Erase num_sectors starting at a given address. Blocking call. |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 191 | // Address must be on a sector boundary. Returns: |
| 192 | // |
| 193 | // OK - success. |
| 194 | // TIMEOUT - on timeout. |
| 195 | // INVALID_ARGUMENT - address or sector count is invalid. |
| 196 | // PERMISSION_DENIED - partition is read only. |
| 197 | // UNKNOWN - HAL error |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 198 | virtual Status Erase(Address address, size_t num_sectors); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 199 | |
Keir Mierle | 8c352dc | 2020-02-02 13:58:19 -0800 | [diff] [blame] | 200 | Status Erase() { return Erase(0, this->sector_count()); } |
| 201 | |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 202 | // Reads bytes from flash into buffer. Blocking call. Returns: |
| 203 | // |
| 204 | // OK - success. |
| 205 | // TIMEOUT - on timeout. |
| 206 | // INVALID_ARGUMENT - address or length is invalid. |
| 207 | // UNKNOWN - HAL error |
Wyatt Hepler | e2cbadf | 2020-06-22 11:21:45 -0700 | [diff] [blame] | 208 | virtual StatusWithSize Read(Address address, std::span<std::byte> output); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 209 | |
| 210 | StatusWithSize Read(Address address, size_t length, void* output) { |
Rob Oliver | f61adbd | 2020-12-09 13:46:46 -0500 | [diff] [blame] | 211 | return Read(address, |
| 212 | std::span<std::byte>(static_cast<std::byte*>(output), length)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 213 | } |
| 214 | |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 215 | // Writes bytes to flash. Address and data.size_bytes() must both be a |
| 216 | // multiple of alignment_bytes(). Blocking call. Returns: |
| 217 | // |
| 218 | // OK - success. |
| 219 | // TIMEOUT - on timeout. |
| 220 | // INVALID_ARGUMENT - address or length is invalid. |
| 221 | // PERMISSION_DENIED - partition is read only. |
| 222 | // UNKNOWN - HAL error |
Wyatt Hepler | e2cbadf | 2020-06-22 11:21:45 -0700 | [diff] [blame] | 223 | virtual StatusWithSize Write(Address address, |
| 224 | std::span<const std::byte> data); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 225 | |
David Rogers | 6a6dae6 | 2020-07-10 01:13:38 -0700 | [diff] [blame] | 226 | // Check to see if chunk of flash partition is erased. Address and len need to |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 227 | // be aligned with FlashMemory. Returns: |
| 228 | // |
| 229 | // OK - success. |
| 230 | // TIMEOUT - on timeout. |
| 231 | // INVALID_ARGUMENT - address or length is invalid. |
| 232 | // UNKNOWN - HAL error |
Wyatt Hepler | e3288e1 | 2020-02-26 13:05:07 -0800 | [diff] [blame] | 233 | // TODO: Result<bool> |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 234 | virtual Status IsRegionErased(Address source_flash_address, |
David Rogers | 3f12bff | 2021-04-13 21:59:26 -0700 | [diff] [blame] | 235 | size_t length, |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 236 | bool* is_erased); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 237 | |
David Rogers | 6a6dae6 | 2020-07-10 01:13:38 -0700 | [diff] [blame] | 238 | // Check if the entire partition is erased. |
| 239 | // Returns: same as IsRegionErased(). |
| 240 | Status IsErased(bool* is_erased) { |
| 241 | return IsRegionErased(0, this->size_bytes(), is_erased); |
| 242 | } |
| 243 | |
Wyatt Hepler | e541e07 | 2020-02-14 09:10:53 -0800 | [diff] [blame] | 244 | // Checks to see if the data appears to be erased. No reads or writes occur; |
| 245 | // the FlashPartition simply compares the data to |
| 246 | // flash_.erased_memory_content(). |
Wyatt Hepler | e2cbadf | 2020-06-22 11:21:45 -0700 | [diff] [blame] | 247 | bool AppearsErased(std::span<const std::byte> data) const; |
Wyatt Hepler | e541e07 | 2020-02-14 09:10:53 -0800 | [diff] [blame] | 248 | |
David Rogers | a12786b | 2020-01-31 16:02:33 -0800 | [diff] [blame] | 249 | // Overridden by derived classes. The reported sector size is space available |
| 250 | // to users of FlashPartition. It accounts for space reserved in the sector |
| 251 | // for FlashPartition to store metadata. |
Keir Mierle | 8c352dc | 2020-02-02 13:58:19 -0800 | [diff] [blame] | 252 | virtual size_t sector_size_bytes() const { |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 253 | return flash_.sector_size_bytes(); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 254 | } |
| 255 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 256 | size_t size_bytes() const { return sector_count() * sector_size_bytes(); } |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 257 | |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 258 | // Alignment required for write address and write size. |
Wyatt Hepler | 116d116 | 2020-02-06 09:42:59 -0800 | [diff] [blame] | 259 | size_t alignment_bytes() const { return alignment_bytes_; } |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 260 | |
Wyatt Hepler | 116d116 | 2020-02-06 09:42:59 -0800 | [diff] [blame] | 261 | size_t sector_count() const { return sector_count_; } |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 262 | |
| 263 | // Convert a FlashMemory::Address to an MCU pointer, this can be used for |
| 264 | // memory mapped reads. Return NULL if the memory is not memory mapped. |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 265 | std::byte* PartitionAddressToMcuAddress(Address address) const { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 266 | return flash_.FlashAddressToMcuAddress(PartitionToFlashAddress(address)); |
| 267 | } |
| 268 | |
Alexei Frolov | 82dae2d | 2020-01-31 17:36:41 -0800 | [diff] [blame] | 269 | // Converts an address from the partition address space to the flash address |
| 270 | // space. If the partition reserves additional space in the sector, the flash |
| 271 | // address space may not be contiguous, and this conversion accounts for that. |
| 272 | virtual FlashMemory::Address PartitionToFlashAddress(Address address) const { |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 273 | return flash_.start_address() + |
| 274 | (start_sector_index_ - flash_.start_sector()) * sector_size_bytes() + |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 275 | address; |
| 276 | } |
| 277 | |
Alexei Frolov | cb7ae1a | 2020-02-03 15:00:05 -0800 | [diff] [blame] | 278 | bool writable() const { |
| 279 | return permission_ == PartitionPermission::kReadAndWrite; |
| 280 | } |
| 281 | |
David Rogers | d833dff | 2020-09-22 13:10:25 -0700 | [diff] [blame] | 282 | constexpr std::byte erased_memory_content() const { |
| 283 | return flash_.erased_memory_content(); |
| 284 | } |
| 285 | |
Alexei Frolov | da95eda | 2020-02-03 16:40:12 -0800 | [diff] [blame] | 286 | uint32_t start_sector_index() const { return start_sector_index_; } |
| 287 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 288 | protected: |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 289 | Status CheckBounds(Address address, size_t len) const; |
David Rogers | 907570b | 2020-08-06 12:44:27 -0700 | [diff] [blame] | 290 | |
Alexei Frolov | cb7ae1a | 2020-02-03 15:00:05 -0800 | [diff] [blame] | 291 | FlashMemory& flash() const { return flash_; } |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 292 | |
| 293 | private: |
| 294 | FlashMemory& flash_; |
| 295 | const uint32_t start_sector_index_; |
| 296 | const uint32_t sector_count_; |
Wyatt Hepler | 116d116 | 2020-02-06 09:42:59 -0800 | [diff] [blame] | 297 | const uint32_t alignment_bytes_; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 298 | const PartitionPermission permission_; |
| 299 | }; |
| 300 | |
Rob Oliver | f61adbd | 2020-12-09 13:46:46 -0500 | [diff] [blame] | 301 | } // namespace kvs |
Alexei Frolov | 5a0450d | 2020-10-28 21:10:47 -0700 | [diff] [blame] | 302 | } // namespace pw |