1#include "stm32_flash.hpp"
3#ifdef HAL_FLASH_MODULE_ENABLED
11class FlashOperationGuard
16#if defined(ICACHE) && defined(ICACHE_CR_EN) && defined(ICACHE_SR_BUSYF)
17 standalone_enabled_ = (ICACHE->CR & ICACHE_CR_EN) != 0U;
18 if (standalone_enabled_)
23 CLEAR_BIT(ICACHE->CR, ICACHE_CR_EN);
26 const uint32_t start = HAL_GetTick();
27 while ((ICACHE->CR & ICACHE_CR_EN) != 0U || (ICACHE->SR & ICACHE_SR_BUSYF) != 0U)
29 if (
static_cast<uint32_t
>(HAL_GetTick() - start) > 1U)
33 REQUIRE((ICACHE->CR & ICACHE_CR_EN) == 0U &&
34 (ICACHE->SR & ICACHE_SR_BUSYF) == 0U);
39#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
40 i_cache_enabled_ = (SCB->CCR & SCB_CCR_IC_Msk) != 0U;
41 if (i_cache_enabled_) SCB_DisableICache();
43#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
44 d_cache_enabled_ = (SCB->CCR & SCB_CCR_DC_Msk) != 0U;
45 if (d_cache_enabled_) SCB_DisableDCache();
50 ~FlashOperationGuard()
53#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
54 if (i_cache_enabled_) SCB_EnableICache();
56#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
57 if (d_cache_enabled_) SCB_EnableDCache();
59#if defined(ICACHE) && defined(ICACHE_CR_EN) && defined(ICACHE_SR_BUSYF)
60 if (standalone_enabled_)
63 SET_BIT(ICACHE->CR, ICACHE_CR_EN);
70 FlashOperationGuard(
const FlashOperationGuard&) =
delete;
71 FlashOperationGuard& operator=(
const FlashOperationGuard&) =
delete;
74#if defined(ICACHE) && defined(ICACHE_CR_EN) && defined(ICACHE_SR_BUSYF)
75 bool standalone_enabled_ =
false;
77#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
78 bool i_cache_enabled_ =
false;
80#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
81 bool d_cache_enabled_ =
false;
86uint32_t TableEnd(
const FlashRegion* regions,
size_t region_count)
88 const auto& last = regions[region_count - 1];
89 return last.
address + last.sector_size * last.sector_count;
93uint32_t SectorSizeAt(
const FlashRegion* regions,
size_t region_count, uint32_t address)
95 for (
size_t i = 0; i < region_count; ++i)
97 const auto& region = regions[i];
98 if (address >= region.address &&
99 address - region.address < region.sector_size * region.sector_count)
101 ASSERT((address - region.address) % region.sector_size == 0U);
102 return region.sector_size;
110uint32_t SecondToLastSector(
const FlashRegion* regions,
size_t region_count)
112 const auto& last = regions[region_count - 1];
113 if (last.sector_count >= 2U)
115 return last.address + last.sector_size * (last.sector_count - 2U);
117 ASSERT(region_count >= 2U);
118 const auto& previous = regions[region_count - 2];
119 return previous.
address + previous.sector_size * (previous.sector_count - 1U);
124 uint32_t start_address)
125 :
Flash(SectorSizeAt(regions, region_count, start_address), MIN_WRITE_SIZE,
126 {
reinterpret_cast<void*
>(start_address),
127 TableEnd(regions, region_count) - start_address}),
129 base_address_(start_address),
130 program_type_(DetermineProgramType()),
131 region_count_(region_count)
136 :
STM32Flash(regions, region_count, SecondToLastSector(regions, region_count))
147 uint32_t start_addr = base_address_ + offset;
148 uint32_t end_addr = start_addr + size;
150 FlashOperationGuard operation;
159 uint32_t bank_entries[2] = {0U, 0U};
160 [[maybe_unused]] uint32_t index = 0U;
161 for (
size_t r = 0; r < region_count_; ++r)
163 const auto& region = regions_[r];
164 for (uint32_t k = 0; k < region.sector_count; ++k, ++index)
166 const uint32_t address = region.address + region.sector_size * k;
167#if defined(FLASH_BANK_2)
168 const size_t bank_slot = (STM32FlashBankOf(address) == FLASH_BANK_2) ? 1U : 0U;
170 const size_t bank_slot = 0U;
172 [[maybe_unused]]
const uint32_t number_in_bank = bank_entries[bank_slot]++;
173 if (address + region.sector_size <= start_addr)
177 if (address >= end_addr)
181 FLASH_EraseInitTypeDef erase_init = {};
183#if defined(FLASH_TYPEERASE_PAGES) && defined(FLASH_PAGE_SIZE)
187 erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
188 SetNbPages(erase_init, address, number_in_bank);
189 erase_init.NbPages = 1;
190 SetBanks(erase_init, address);
191#elif defined(FLASH_TYPEERASE_SECTORS)
192 erase_init.TypeErase = FLASH_TYPEERASE_SECTORS;
193#if defined(FLASH_SECTOR_SIZE)
196 erase_init.Sector = number_in_bank;
197#elif defined(FLASH_SECTOR_TOTAL)
200 erase_init.Sector = index;
202#error "No supported Flash sector numbering defined"
204 erase_init.NbSectors = 1;
205#if defined(FLASH_BANK_1)
206 erase_init.Banks = STM32FlashBankOf(address);
208#if defined(FLASH_CR_PSIZE)
209 erase_init.VoltageRange = FLASH_VOLTAGE_RANGE_1;
216 HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase_init, &error);
217 if (status != HAL_OK || error != 0xFFFFFFFFU)
234 uint32_t addr = base_address_ + offset;
235 if (!IsInRange(addr, data.
size_))
240 FlashOperationGuard operation;
242 const uint8_t* src =
reinterpret_cast<const uint8_t*
>(data.
addr_);
245#if defined(FLASH_TYPEPROGRAM_FLASHWORD) || defined(FLASH_TYPEPROGRAM_QUADWORD)
248 while (written < data.
size_)
255 if (
Memory::FastCmp(
reinterpret_cast<const uint8_t*
>(addr + written), src + written,
258 written += chunk_size;
262 if (HAL_FLASH_Program(program_type_, addr + written,
263 reinterpret_cast<uint32_t
>(flash_word_buffer)) != HAL_OK)
268 written += chunk_size;
272 while (written < data.
size_)
276 if (
Memory::FastCmp(
reinterpret_cast<const uint8_t*
>(addr + written), src + written,
279 written += chunk_size;
283 uint64_t word = 0xFFFFFFFFFFFFFFFF;
286 if (HAL_FLASH_Program(program_type_, addr + written, word) != HAL_OK)
291 written += chunk_size;
298bool STM32Flash::IsInRange(uint32_t addr,
size_t size)
const
300 const uint32_t BEGIN = base_address_;
301 const uint32_t LIMIT = TableEnd(regions_, region_count_);
302 const uint32_t END = addr + size;
303 return (addr >= BEGIN) && (END <= LIMIT) && (END >= addr);
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
抽象基类,表示闪存接口。 Abstract base class representing a flash memory interface.
size_t MinWriteSize() const
获取最小可写块大小(字节) / Returns the minimum writable block size in bytes.
static void FastSet(void *dst, uint8_t value, size_t size)
快速内存填充 / Fast memory fill
static int FastCmp(const void *a, const void *b, size_t size)
快速内存比较 / Fast memory comparison
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
STM32 闪存驱动实现 / STM32 flash driver implementation.
STM32Flash(const FlashRegion *regions, size_t region_count, uint32_t start_address)
构造闪存对象 / Construct flash object
static constexpr size_t MIN_WRITE_SIZE
最小写入单位(字节),由 HAL 的 FLASH_TYPEPROGRAM_* 宏确定;可直接作为 DatabaseRaw 的模板参数 / Minimum write unit in bytes,...
ErrorCode Write(size_t offset, ConstRawData data) override
向闪存写入数据 / Writes data to the flash memory.
ErrorCode Erase(size_t offset, size_t size) override
擦除闪存的指定区域 / Erases a section of the flash memory.
LibXR 命名空间 / LibXR namespace.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ OUT_OF_RANGE
超出范围 / Out of range
@ NOT_SUPPORT
不支持 / Not supported
@ FAILED
操作失败 / Operation failed
@ OK
操作成功 / Operation successful
@ ARG_ERR
参数错误 / Argument error
constexpr auto min(LeftType a, RightType b) -> std::common_type_t< LeftType, RightType >
计算两个数的最小值 / Computes the minimum of two numbers
constexpr size_t HW_CACHE_LINE_SIZE
真实硬件缓存行大小(用于 DMA / cache coherency) / Hardware cache-line size used for DMA/cache-coherency boundarie...
一段连续、大小相同的扇区 / A run of contiguous sectors of equal size
uint32_t address
第一个扇区的地址 / Address of the first sector