1#include "ch32_flash.hpp"
6static void Flash_SetAccessClock_HalfSysclk(
void)
9 FLASH->CTLR &= ~(1u << 25);
14static void Flash_SetAccessClock_Sysclk(
void)
17 FLASH->CTLR |= (1u << 25);
21static inline void Flash_ExitEnhancedReadIfEnabled()
23 if (FLASH->STATR & (1u << 7))
26 FLASH->CTLR &= ~(1u << 24);
27 FLASH->CTLR |= (1u << 22);
32static inline void Flash_FastUnlock()
36 FLASH->MODEKEYR = 0x45670123u;
37 FLASH->MODEKEYR = 0xCDEF89ABu;
40static inline void Flash_FastLock()
43 FLASH->CTLR |= (1u << 15);
47static bool Flash_WaitBusyClear(uint32_t spin = 1000000u)
49 while (FLASH->STATR & 0x1u)
51 if (spin-- == 0)
return false;
56inline void CH32Flash::ClearFlashFlagsOnce()
59 FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR);
61 FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR);
65CH32Flash::CH32Flash(
const FlashSector* sectors,
size_t sector_count,
size_t start_sector)
66 :
Flash(sectors[start_sector - 1].size, MinWriteSize(),
67 {
reinterpret_cast<void*
>(sectors[start_sector - 1].address),
68 sectors[sector_count - 1].address - sectors[start_sector - 1].address +
69 sectors[sector_count - 1].size}),
71 base_address_(sectors[start_sector - 1].address),
72 sector_count_(sector_count)
78 if (size == 0)
return ErrorCode::ARG_ERR;
80 ASSERT(SystemCoreClock <= 120000000);
82 const uint32_t start_addr = base_address_ +
static_cast<uint32_t
>(offset);
83 if (!IsInRange(start_addr, size))
return ErrorCode::OUT_OF_RANGE;
84 const uint32_t end_addr = start_addr +
static_cast<uint32_t
>(size);
87 Flash_ExitEnhancedReadIfEnabled();
90 Flash_SetAccessClock_HalfSysclk();
94 ClearFlashFlagsOnce();
97 const uint32_t FAST_SZ = 256u;
98 const uint32_t erase_begin = start_addr & ~(FAST_SZ - 1u);
99 const uint32_t erase_end = (end_addr + FAST_SZ - 1u) & ~(FAST_SZ - 1u);
100 if (erase_end <= erase_begin)
103 Flash_SetAccessClock_Sysclk();
104 return ErrorCode::OK;
108 FLASH->CTLR |= (1u << 17);
111 for (uint32_t adr = erase_begin; adr < erase_end; adr += FAST_SZ)
117 FLASH->CTLR |= (1u << 6);
120 if (!Flash_WaitBusyClear())
123 FLASH->CTLR &= ~(1u << 17);
125 Flash_SetAccessClock_Sysclk();
126 return ErrorCode::FAILED;
130 if (FLASH->STATR & (1u << 4))
132 FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR);
133 FLASH->CTLR &= ~(1u << 17);
135 Flash_SetAccessClock_Sysclk();
136 return ErrorCode::FAILED;
140 FLASH_ClearFlag(FLASH_FLAG_EOP);
144 FLASH->CTLR &= ~(1u << 17);
146 Flash_SetAccessClock_Sysclk();
148 return ErrorCode::OK;
153 ASSERT(SystemCoreClock <= 120000000);
156 Flash_ExitEnhancedReadIfEnabled();
159 Flash_SetAccessClock_HalfSysclk();
163 Flash_SetAccessClock_Sysclk();
165 return ErrorCode::ARG_ERR;
168 const uint32_t start_addr = base_address_ +
static_cast<uint32_t
>(offset);
169 if (!IsInRange(start_addr, data.
size_))
171 Flash_SetAccessClock_Sysclk();
173 return ErrorCode::OUT_OF_RANGE;
176 const uint8_t* src =
reinterpret_cast<const uint8_t*
>(data.
addr_);
177 const uint32_t end_addr = start_addr +
static_cast<uint32_t
>(data.
size_);
180 ClearFlashFlagsOnce();
182 const uint32_t hw_begin = start_addr & ~1u;
183 const uint32_t hw_end = (end_addr + 1u) & ~1u;
185 for (uint32_t hw = hw_begin; hw < hw_end; hw += 2u)
187 volatile uint16_t* p =
reinterpret_cast<volatile uint16_t*
>(hw);
188 volatile uint16_t orig = *p;
189 volatile uint16_t val = orig;
191 if (hw >= start_addr && hw < end_addr)
193 uint8_t b0 = src[hw - start_addr];
194 val =
static_cast<uint16_t
>((val & 0xFF00u) | b0);
196 if ((hw + 1u) >= start_addr && (hw + 1u) < end_addr)
198 uint8_t b1 = src[(hw + 1u) - start_addr];
199 val =
static_cast<uint16_t
>((val & 0x00FFu) | (
static_cast<uint16_t
>(b1) << 8));
202 if (val == orig)
continue;
205 if (((~orig) & val) != 0u && orig != 0xE339u)
208 Flash_SetAccessClock_Sysclk();
210 return ErrorCode::FAILED;
213 if (FLASH_ProgramHalfWord(hw, val) != FLASH_COMPLETE)
216 Flash_SetAccessClock_Sysclk();
218 return ErrorCode::FAILED;
223 FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR);
227 Flash_SetAccessClock_Sysclk();
228 return ErrorCode::OK;
231bool CH32Flash::IsInRange(uint32_t addr,
size_t size)
const
233 const uint32_t BEGIN = base_address_;
234 const uint32_t LIMIT =
235 sectors_[sector_count_ - 1].address + sectors_[sector_count_ - 1].size;
236 const uint32_t END = addr +
static_cast<uint32_t
>(size);
237 return (addr >= BEGIN) && (END <= LIMIT) && (END >= addr);
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. 抽象基类,表示闪存接口。
STM32Flash 通用类,构造时传入扇区列表,自动判断编程粒度。