libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_flash.cpp
1#include "stm32_flash.hpp"
2
3using namespace LibXR;
4
5STM32Flash::STM32Flash(const FlashSector* sectors, size_t sector_count,
6 size_t start_sector)
7 : Flash(sectors[start_sector - 1].size, DetermineMinWriteSize(),
8 {reinterpret_cast<void*>(sectors[start_sector - 1].address),
9 sectors[sector_count - 1].address - sectors[start_sector - 1].address +
10 sectors[sector_count - 1].size}),
11 sectors_(sectors),
12 base_address_(sectors[start_sector - 1].address),
13 program_type_(DetermineProgramType()),
14 sector_count_(sector_count)
15{
16}
17
18ErrorCode STM32Flash::Erase(size_t offset, size_t size)
19{
20 if (size == 0)
21 {
22 return ErrorCode::ARG_ERR;
23 }
24
25 uint32_t start_addr = base_address_ + offset;
26 uint32_t end_addr = start_addr + size;
27
28#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
29 bool i_cache_enabled = ((SCB->CCR & SCB_CCR_IC_Msk) != 0U);
30 if (i_cache_enabled)
31 {
32 SCB_DisableICache();
33 }
34#endif
35
36#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
37 bool d_cache_enabled = ((SCB->CCR & SCB_CCR_DC_Msk) != 0U);
38 if (d_cache_enabled)
39 {
40 SCB_DisableDCache();
41 }
42#endif
43
44 HAL_FLASH_Unlock();
45
46 for (size_t i = 0; i < sector_count_; ++i)
47 {
48 const auto& sector = sectors_[i];
49 if (sector.address + sector.size <= start_addr)
50 {
51 continue;
52 }
53 if (sector.address >= end_addr)
54 {
55 break;
56 }
57 FLASH_EraseInitTypeDef erase_init = {};
58
59#if defined(FLASH_TYPEERASE_PAGES) && defined(FLASH_PAGE_SIZE) // STM32F1/G4... series
60 erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
61 SetNbPages(erase_init, sector.address, i);
62 erase_init.NbPages = 1;
63 SetBanks(erase_init, sector.address);
64#elif defined(FLASH_TYPEERASE_SECTORS) // STM32F4/F7/H7... series
65 erase_init.TypeErase = FLASH_TYPEERASE_SECTORS;
66 erase_init.Sector = static_cast<uint32_t>(i) % FLASH_SECTOR_TOTAL;
67 erase_init.NbSectors = 1;
68#if defined(FLASH_BANK_1)
69 erase_init.Banks = STM32FlashBankOf(sector.address);
70#endif
71#if defined(FLASH_CR_PSIZE)
72 erase_init.VoltageRange = FLASH_VOLTAGE_RANGE_1;
73#endif
74#else
75 return ErrorCode::NOT_SUPPORT;
76#endif
77
78 uint32_t error = 0;
79 HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase_init, &error);
80 if (status != HAL_OK || error != 0xFFFFFFFFU)
81 {
82 HAL_FLASH_Lock();
83 return ErrorCode::FAILED;
84 }
85 }
86
87 HAL_FLASH_Lock();
88
89#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
90 if (i_cache_enabled)
91 {
92 SCB_EnableICache();
93 }
94#endif
95
96#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
97
98 if (d_cache_enabled)
99 {
100 SCB_EnableDCache();
101 }
102#endif
103
104 return ErrorCode::OK;
105}
106
107ErrorCode STM32Flash::Write(size_t offset, ConstRawData data)
108{
109 if (!data.addr_ || data.size_ == 0)
110 {
111 return ErrorCode::ARG_ERR;
112 }
113
114 uint32_t addr = base_address_ + offset;
115 if (!IsInRange(addr, data.size_))
116 {
117 return ErrorCode::OUT_OF_RANGE;
118 }
119
120#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
121 bool i_cache_enabled = ((SCB->CCR & SCB_CCR_IC_Msk) != 0U);
122 if (i_cache_enabled)
123 {
124 SCB_DisableICache();
125 }
126#endif
127
128#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
129 bool d_cache_enabled = ((SCB->CCR & SCB_CCR_DC_Msk) != 0U);
130 if (d_cache_enabled)
131 {
132 SCB_DisableDCache();
133 }
134#endif
135
136 HAL_FLASH_Unlock();
137
138 const uint8_t* src = reinterpret_cast<const uint8_t*>(data.addr_);
139 size_t written = 0;
140
141#if defined(STM32H7) || defined(STM32H5)
142 alignas(32) uint32_t flash_word_buffer[8] = {0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
143 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
144 0xFFFFFFFFu, 0xFFFFFFFFu};
145 while (written < data.size_)
146 {
147 size_t chunk_size = LibXR::min<size_t>(MinWriteSize(), data.size_ - written);
148
149 std::memset(flash_word_buffer, 0xFF, sizeof(flash_word_buffer));
150 std::memcpy(flash_word_buffer, src + written, chunk_size);
151
152 if (memcmp(reinterpret_cast<const uint8_t*>(addr + written), src + written,
153 chunk_size) == 0)
154 {
155 written += chunk_size;
156 continue;
157 }
158
159 if (HAL_FLASH_Program(program_type_, addr + written,
160 reinterpret_cast<uint32_t>(flash_word_buffer)) != HAL_OK)
161 {
162 HAL_FLASH_Lock();
163 return ErrorCode::FAILED;
164 }
165
166 written += chunk_size;
167 }
168
169#else
170 while (written < data.size_)
171 {
172 size_t chunk_size = LibXR::min<size_t>(MinWriteSize(), data.size_ - written);
173
174 if (memcmp(reinterpret_cast<const uint8_t*>(addr + written), src + written,
175 chunk_size) == 0)
176 {
177 written += chunk_size;
178 continue;
179 }
180
181 uint64_t word = 0xFFFFFFFFFFFFFFFF;
182 std::memcpy(&word, src + written, chunk_size);
183
184 if (HAL_FLASH_Program(program_type_, addr + written, word) != HAL_OK)
185 {
186 HAL_FLASH_Lock();
187 return ErrorCode::FAILED;
188 }
189
190 written += chunk_size;
191 }
192#endif
193
194 HAL_FLASH_Lock();
195
196#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
197 if (i_cache_enabled)
198 {
199 SCB_EnableICache();
200 }
201#endif
202
203#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
204 if (d_cache_enabled)
205 {
206 SCB_EnableDCache();
207 }
208#endif
209
210 return ErrorCode::OK;
211}
212
213bool STM32Flash::IsInRange(uint32_t addr, size_t size) const
214{
215 const uint32_t BEGIN = base_address_;
216 const uint32_t LIMIT =
217 sectors_[sector_count_ - 1].address + sectors_[sector_count_ - 1].size;
218 const uint32_t END = addr + size;
219 return (addr >= BEGIN) && (END <= LIMIT) && (END >= addr); // 最后一项防溢出
220}
常量原始数据封装类。 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:19
size_t MinWriteSize() const
Returns the minimum writable block size in bytes. 获取最小可写块大小(字节)。
Definition flash.hpp:73
ErrorCode Write(size_t offset, ConstRawData data) override
Writes data to the flash memory. 向闪存写入数据。
STM32Flash(const FlashSector *sectors, size_t sector_count, size_t start_sector)
STM32Flash 类,构造时传入扇区列表,自动判断编程粒度。
ErrorCode Erase(size_t offset, size_t size) override
Erases a section of the flash memory. 擦除闪存的指定区域。
LibXR 命名空间
Definition ch32_gpio.hpp:9
constexpr auto min(T1 a, T2 b) -> typename std::common_type< T1, T2 >::type
计算两个数的最小值
STM32Flash 通用类,构造时传入扇区列表,自动判断编程粒度。