2#include "ch32_flash.hpp"
7static void flash_set_access_clock_half_sysclk(
void)
10 FLASH->CTLR &= ~(1u << 25);
15static void flash_set_access_clock_sysclk(
void)
18 FLASH->CTLR |= (1u << 25);
22static inline void flash_exit_enhanced_read_if_enabled()
24 if (FLASH->STATR & (1u << 7))
27 FLASH->CTLR &= ~(1u << 24);
28 FLASH->CTLR |= (1u << 22);
33static inline void flash_fast_unlock()
37 FLASH->MODEKEYR = 0x45670123u;
38 FLASH->MODEKEYR = 0xCDEF89ABu;
41static inline void flash_fast_lock()
44 FLASH->CTLR |= (1u << 15);
48static bool flash_wait_busy_clear(uint32_t spin = 1000000u)
50 while (FLASH->STATR & 0x1u)
60inline void CH32Flash::ClearFlashFlagsOnce()
63 FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR);
65 FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR);
70 :
Flash(sectors[start_sector - 1].size, MinWriteSize(),
71 {
reinterpret_cast<void*
>(sectors[start_sector - 1].
address),
72 sectors[sector_count - 1].
address - sectors[start_sector - 1].
address +
73 sectors[sector_count - 1].
size}),
75 base_address_(sectors[start_sector - 1].address),
76 sector_count_(sector_count)
84 return ErrorCode::ARG_ERR;
87 ASSERT(SystemCoreClock <= 120000000);
89 const uint32_t START_ADDR = base_address_ +
static_cast<uint32_t
>(offset);
90 if (!IsInRange(START_ADDR, size))
92 return ErrorCode::OUT_OF_RANGE;
94 const uint32_t END_ADDR = START_ADDR +
static_cast<uint32_t
>(size);
97 flash_exit_enhanced_read_if_enabled();
100 flash_set_access_clock_half_sysclk();
104 ClearFlashFlagsOnce();
107 const uint32_t FAST_SZ = 256u;
108 const uint32_t ERASE_BEGIN = START_ADDR & ~(FAST_SZ - 1u);
109 const uint32_t ERASE_END = (END_ADDR + FAST_SZ - 1u) & ~(FAST_SZ - 1u);
110 if (ERASE_END <= ERASE_BEGIN)
113 flash_set_access_clock_sysclk();
114 return ErrorCode::OK;
118 FLASH->CTLR |= (1u << 17);
121 for (uint32_t adr = ERASE_BEGIN; adr < ERASE_END; adr += FAST_SZ)
127 FLASH->CTLR |= (1u << 6);
130 if (!flash_wait_busy_clear())
133 FLASH->CTLR &= ~(1u << 17);
135 flash_set_access_clock_sysclk();
136 return ErrorCode::FAILED;
140 if (FLASH->STATR & (1u << 4))
142 FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR);
143 FLASH->CTLR &= ~(1u << 17);
145 flash_set_access_clock_sysclk();
146 return ErrorCode::FAILED;
150 FLASH_ClearFlag(FLASH_FLAG_EOP);
154 FLASH->CTLR &= ~(1u << 17);
156 flash_set_access_clock_sysclk();
158 return ErrorCode::OK;
163 ASSERT(SystemCoreClock <= 120000000);
166 flash_exit_enhanced_read_if_enabled();
169 flash_set_access_clock_half_sysclk();
173 flash_set_access_clock_sysclk();
175 return ErrorCode::ARG_ERR;
178 const uint32_t START_ADDR = base_address_ +
static_cast<uint32_t
>(offset);
179 if (!IsInRange(START_ADDR, data.
size_))
181 flash_set_access_clock_sysclk();
183 return ErrorCode::OUT_OF_RANGE;
186 const uint8_t* src =
reinterpret_cast<const uint8_t*
>(data.
addr_);
187 const uint32_t END_ADDR = START_ADDR +
static_cast<uint32_t
>(data.
size_);
190 ClearFlashFlagsOnce();
192 const uint32_t HW_BEGIN = START_ADDR & ~1u;
193 const uint32_t HW_END = (END_ADDR + 1u) & ~1u;
195 for (uint32_t hw = HW_BEGIN; hw < HW_END; hw += 2u)
197 volatile uint16_t* p =
reinterpret_cast<volatile uint16_t*
>(hw);
198 volatile uint16_t orig = *p;
199 volatile uint16_t val = orig;
201 if (hw >= START_ADDR && hw < END_ADDR)
203 uint8_t b0 = src[hw - START_ADDR];
204 val =
static_cast<uint16_t
>((val & 0xFF00u) | b0);
206 if ((hw + 1u) >= START_ADDR && (hw + 1u) < END_ADDR)
208 uint8_t b1 = src[(hw + 1u) - START_ADDR];
209 val =
static_cast<uint16_t
>((val & 0x00FFu) | (
static_cast<uint16_t
>(b1) << 8));
218 if (((~orig) & val) != 0u && orig != 0xE339u)
221 flash_set_access_clock_sysclk();
223 return ErrorCode::FAILED;
226 if (FLASH_ProgramHalfWord(hw, val) != FLASH_COMPLETE)
229 flash_set_access_clock_sysclk();
231 return ErrorCode::FAILED;
236 FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR);
240 flash_set_access_clock_sysclk();
241 return ErrorCode::OK;
244bool CH32Flash::IsInRange(uint32_t addr,
size_t size)
const
246 const uint32_t BEGIN = base_address_;
247 const uint32_t LIMIT =
248 sectors_[sector_count_ - 1].
address + sectors_[sector_count_ - 1].
size;
249 const uint32_t END = addr +
static_cast<uint32_t
>(size);
250 return (addr >= BEGIN) && (END <= LIMIT) && (END >= addr);
CH32Flash(const FlashSector *sectors, size_t sector_count, size_t start_sector)
构造闪存对象 / Construct flash object
ErrorCode Erase(size_t offset, size_t size) override
Erases a section of the flash memory. 擦除闪存的指定区域。
ErrorCode Write(size_t offset, ConstRawData data) override
Writes data to the flash memory. 向闪存写入数据。
常量原始数据封装类。 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. 抽象基类,表示闪存接口。
闪存扇区描述 / Flash sector descriptor
uint32_t size
扇区大小(字节) / Sector size in bytes
uint32_t address
扇区起始地址 / Sector base address