libxr 1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_flash.hpp
1#pragma once
2
3#include <algorithm>
4#include <cstdint>
5#include <cstring>
6
7#include "flash.hpp"
8#include "libxr_def.hpp"
9#include "libxr_type.hpp"
10#include "main.h"
11
12namespace LibXR
13{
14
20{
21 uint32_t address;
22 uint32_t size;
23};
24
25template <typename, typename = void>
26struct HasFlashPage : std::false_type
27{
28};
29
30template <typename, typename = void>
31struct HasFlashBank : std::false_type
32{
33};
34
35template <typename T>
36struct HasFlashPage<T, std::void_t<decltype(std::declval<T>().Page)>> : std::true_type
37{
38};
39
40template <typename T>
41struct HasFlashBank<T, std::void_t<decltype(std::declval<T>().Banks)>> : std::true_type
42{
43};
44
45template <typename T>
46// NOLINTNEXTLINE
47typename std::enable_if<!HasFlashPage<T>::value>::type SetNbPages(T& init, uint32_t addr,
48 uint32_t page)
49{
50 UNUSED(page);
51 init.PageAddress = addr;
52}
53
54template <typename T>
55// NOLINTNEXTLINE
56typename std::enable_if<HasFlashPage<T>::value>::type SetNbPages(T& init, uint32_t addr,
57 uint32_t page)
58{
59 UNUSED(addr);
60 init.Page = page;
61}
62
63template <typename T>
64// NOLINTNEXTLINE
65typename std::enable_if<!HasFlashBank<T>::value>::type SetBanks(T& init)
66{
67 UNUSED(init);
68}
69
70template <typename T>
71// NOLINTNEXTLINE
72typename std::enable_if<HasFlashBank<T>::value>::type SetBanks(T& init)
73{
74 init.Banks = 1;
75}
76
82template <size_t SECTOR_COUNT, size_t START_SECTOR>
83class STM32Flash : public Flash
84{
85 public:
91 STM32Flash(const FlashSector (&sectors)[SECTOR_COUNT])
92 : Flash(sectors[START_SECTOR - 1].size, DetermineMinWriteSize(),
93 {reinterpret_cast<void*>(sectors[START_SECTOR - 1].address),
94 sectors[SECTOR_COUNT - 1].address - sectors[START_SECTOR - 1].address +
95 sectors[SECTOR_COUNT - 1].size}),
96 sectors_(sectors),
97 base_address_(sectors[START_SECTOR - 1].address),
98 program_type_(DetermineProgramType())
99 {
100 }
101
102 ErrorCode Erase(size_t offset, size_t size) override
103 {
104 if (size == 0)
105 {
106 return ErrorCode::ARG_ERR;
107 }
108
109 uint32_t start_addr = base_address_ + offset;
110 uint32_t end_addr = start_addr + size;
111
112 HAL_FLASH_Unlock();
113
114 for (size_t i = 0; i < SECTOR_COUNT; ++i)
115 {
116 const auto& sector = sectors_[i];
117 if (sector.address + sector.size <= start_addr)
118 {
119 continue;
120 }
121 if (sector.address >= end_addr)
122 {
123 break;
124 }
125 FLASH_EraseInitTypeDef erase_init = {};
126
127#if defined(FLASH_TYPEERASE_PAGES) && defined(FLASH_PAGE_SIZE) // STM32F1/G4... series
128 erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
129 SetNbPages(erase_init, sector.address, i);
130 erase_init.NbPages = 1;
131 SetBanks(erase_init);
132#elif defined(FLASH_TYPEERASE_SECTORS) // STM32F4/F7/H7... series
133 erase_init.TypeErase = FLASH_TYPEERASE_SECTORS;
134 erase_init.Sector = static_cast<uint32_t>(i);
135 erase_init.NbSectors = 1;
136 erase_init.Banks = FLASH_BANK_1;
137#else
138 return ErrorCode::NOT_SUPPORT;
139#endif
140
141 uint32_t error = 0;
142 HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase_init, &error);
143 if (status != HAL_OK || error != 0xFFFFFFFFU)
144 {
145 HAL_FLASH_Lock();
146 return ErrorCode::FAILED;
147 }
148 }
149
150 HAL_FLASH_Lock();
151 return ErrorCode::OK;
152 }
153
154 ErrorCode Write(size_t offset, ConstRawData data) override
155 {
156 if (!data.addr_ || data.size_ == 0)
157 {
158 return ErrorCode::ARG_ERR;
159 }
160
161 uint32_t addr = base_address_ + offset;
162 if (!IsInRange(addr, data.size_))
163 {
164 return ErrorCode::OUT_OF_RANGE;
165 }
166
167 HAL_FLASH_Unlock();
168
169 const uint8_t* src = reinterpret_cast<const uint8_t*>(data.addr_);
170 size_t written = 0;
171
172#if defined(STM32H7) || defined(STM32H5)
173 alignas(32) uint32_t flash_word_buffer[8] = {0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
174 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
175 0xFFFFFFFFu, 0xFFFFFFFFu};
176 while (written < data.size_)
177 {
178 size_t chunk_size = std::min<size_t>(min_write_size_, data.size_ - written);
179
180 std::memcpy(flash_word_buffer, src + written, chunk_size);
181
182 if (memcmp(reinterpret_cast<const uint8_t*>(addr + written), src + written,
183 chunk_size) == 0)
184 {
186 continue;
187 }
188
189 if (HAL_FLASH_Program(program_type_, addr + written,
190 reinterpret_cast<uint32_t>(flash_word_buffer)) != HAL_OK)
191 {
193 return ErrorCode::FAILED;
194 }
195
197 }
198
199#else
200 while (written < data.size_)
201 {
202 size_t chunk_size = std::min<size_t>(min_write_size_, data.size_ - written);
203
204 if (memcmp(reinterpret_cast<const uint8_t*>(addr + written), src + written,
205 chunk_size) == 0)
206 {
208 continue;
209 }
210
211 uint64_t word = 0xFFFFFFFFFFFFFFFF;
212 std::memcpy(&word, src + written, chunk_size);
213
214 if (HAL_FLASH_Program(program_type_, addr + written, word) != HAL_OK)
215 {
217 return ErrorCode::FAILED;
218 }
219
221 }
222#endif
223
225 return ErrorCode::OK;
226 }
227
228 private:
229 const FlashSector* sectors_;
230 uint32_t base_address_;
231 uint32_t program_type_;
232
233 static constexpr uint32_t DetermineProgramType()
234 {
235#ifdef FLASH_TYPEPROGRAM_BYTE
237#elif defined(FLASH_TYPEPROGRAM_HALFWORD)
239#elif defined(FLASH_TYPEPROGRAM_WORD)
241#elif defined(FLASH_TYPEPROGRAM_DOUBLEWORD)
243#elif defined(FLASH_TYPEPROGRAM_FLASHWORD)
245#else
246#error "No supported FLASH_TYPEPROGRAM_xxx defined"
247#endif
248 }
249
250 static constexpr size_t DetermineMinWriteSize()
251 {
252#ifdef FLASH_TYPEPROGRAM_BYTE
253 return 1;
254#elif defined(FLASH_TYPEPROGRAM_HALFWORD)
255 return 2;
256#elif defined(FLASH_TYPEPROGRAM_WORD)
257 return 4;
258#elif defined(FLASH_TYPEPROGRAM_DOUBLEWORD)
259 return 8;
260#elif defined(FLASH_TYPEPROGRAM_FLASHWORD)
262#else
263#error "No supported FLASH_TYPEPROGRAM_xxx defined"
264#endif
265 }
266
267 bool IsInRange(uint32_t addr, size_t size) const
268 {
269 uint32_t end = addr + size;
270 for (size_t i = 0; i < SECTOR_COUNT; ++i)
271 {
272 const auto& s = sectors_[i];
273 if (addr >= s.address && end <= s.address + s.size)
274 {
275 return true;
276 }
277 }
278 return false;
279 }
280};
281
282} // namespace LibXR
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
Abstract base class representing a flash memory interface. 抽象基类,表示闪存接口。
Definition flash.hpp:16
size_t min_write_size_
Minimum writable block size in bytes. 最小可写块大小(字节)。
Definition flash.hpp:36
STM32Flash 通用类,构造时传入扇区列表,自动判断编程粒度。
ErrorCode Erase(size_t offset, size_t size) override
Erases a section of the flash memory. 擦除闪存的指定区域。
STM32Flash(const FlashSector(&sectors)[SECTOR_COUNT])
STM32Flash 类,构造时传入扇区列表,自动判断编程粒度。
ErrorCode Write(size_t offset, ConstRawData data) override
Writes data to the flash memory. 向闪存写入数据。
LibXR Color Control Library / LibXR终端颜色控制库
constexpr auto min(T1 a, T2 b) -> typename std::common_type< T1, T2 >::type
计算两个数的最小值
STM32Flash 通用类,构造时传入扇区列表,自动判断编程粒度。