mirror of
https://github.com/goldenfishs/MRobot.git
synced 2026-02-04 18:00:19 +08:00
添加falsh生成
This commit is contained in:
parent
724848a843
commit
3b79dd936d
@ -1376,7 +1376,225 @@ class bsp_pwm(QWidget):
|
||||
if name_widget:
|
||||
name_widget.setText(saved_config['custom_name'])
|
||||
|
||||
# 更新get_bsp_page函数以包含PWM
|
||||
|
||||
class bsp_flash(QWidget):
|
||||
"""Flash BSP配置界面 - 自动识别MCU型号并生成对应的Flash配置"""
|
||||
def __init__(self, project_path):
|
||||
super().__init__()
|
||||
self.project_path = project_path
|
||||
self.mcu_name = None
|
||||
self.flash_config = None
|
||||
# 加载描述
|
||||
describe_path = os.path.join(CodeGenerator.get_assets_dir("User_code/bsp"), "describe.csv")
|
||||
self.descriptions = CodeGenerator.load_descriptions(describe_path)
|
||||
self._detect_mcu()
|
||||
self._init_ui()
|
||||
self._load_config()
|
||||
|
||||
def _detect_mcu(self):
|
||||
"""自动检测MCU型号并获取Flash配置"""
|
||||
ioc_files = [f for f in os.listdir(self.project_path) if f.endswith('.ioc')]
|
||||
if ioc_files:
|
||||
ioc_path = os.path.join(self.project_path, ioc_files[0])
|
||||
self.mcu_name = analyzing_ioc.get_mcu_name_from_ioc(ioc_path)
|
||||
if self.mcu_name:
|
||||
self.flash_config = analyzing_ioc.get_flash_config_from_mcu(self.mcu_name)
|
||||
|
||||
def _init_ui(self):
|
||||
layout = QVBoxLayout(self)
|
||||
|
||||
# 顶部布局
|
||||
top_layout = QHBoxLayout()
|
||||
top_layout.setAlignment(Qt.AlignVCenter)
|
||||
|
||||
self.generate_checkbox = CheckBox("生成 Flash 代码")
|
||||
self.generate_checkbox.stateChanged.connect(self._on_generate_changed)
|
||||
top_layout.addWidget(self.generate_checkbox, alignment=Qt.AlignLeft)
|
||||
|
||||
top_layout.addStretch()
|
||||
|
||||
title = SubtitleLabel("Flash 配置 ")
|
||||
title.setAlignment(Qt.AlignHCenter)
|
||||
top_layout.addWidget(title, alignment=Qt.AlignHCenter)
|
||||
|
||||
top_layout.addStretch()
|
||||
|
||||
layout.addLayout(top_layout)
|
||||
|
||||
desc = self.descriptions.get("flash", "自动根据MCU型号配置Flash扇区")
|
||||
if desc:
|
||||
desc_label = BodyLabel(desc)
|
||||
desc_label.setWordWrap(True)
|
||||
layout.addWidget(desc_label)
|
||||
|
||||
# 内容区域
|
||||
self.content_widget = QWidget()
|
||||
content_layout = QVBoxLayout(self.content_widget)
|
||||
|
||||
if not self.flash_config:
|
||||
no_config_label = BodyLabel("❌ 无法识别MCU型号或不支持的MCU")
|
||||
content_layout.addWidget(no_config_label)
|
||||
else:
|
||||
# 显示检测到的MCU信息
|
||||
mcu_info = BodyLabel(f"✅ 检测到MCU: {self.mcu_name}")
|
||||
content_layout.addWidget(mcu_info)
|
||||
|
||||
flash_size = (self.flash_config['end_address'] - 0x08000000) // 1024
|
||||
flash_type = self.flash_config.get('type', 'sector')
|
||||
|
||||
if flash_type == 'page':
|
||||
# F1系列 - Page模式
|
||||
page_size = self.flash_config.get('page_size', 1)
|
||||
flash_info = BodyLabel(f"Flash容量: {flash_size} KB ({len(self.flash_config['sectors'])} 个页,每页 {page_size}KB)")
|
||||
content_layout.addWidget(flash_info)
|
||||
type_info = BodyLabel(f"📄 Page模式 (F1系列)")
|
||||
content_layout.addWidget(type_info)
|
||||
else:
|
||||
# F4/H7系列 - Sector模式
|
||||
flash_info = BodyLabel(f"Flash容量: {flash_size} KB ({len(self.flash_config['sectors'])} 个扇区)")
|
||||
content_layout.addWidget(flash_info)
|
||||
|
||||
if self.flash_config['dual_bank']:
|
||||
max_sector = len(self.flash_config['sectors']) - 1
|
||||
bank_info = BodyLabel(f"⚠️ 双Bank Flash (Sector 0-{max_sector})")
|
||||
else:
|
||||
max_sector = len(self.flash_config['sectors']) - 1
|
||||
bank_info = BodyLabel(f"单Bank Flash (Sector 0-{max_sector})")
|
||||
content_layout.addWidget(bank_info)
|
||||
|
||||
layout.addWidget(self.content_widget)
|
||||
self.content_widget.setEnabled(False)
|
||||
|
||||
def _on_generate_changed(self, state):
|
||||
self.content_widget.setEnabled(state == 2)
|
||||
|
||||
def is_need_generate(self):
|
||||
return self.generate_checkbox.isChecked() and self.flash_config is not None
|
||||
|
||||
def _generate_bsp_code_internal(self):
|
||||
if not self.is_need_generate():
|
||||
return False
|
||||
|
||||
if not self.flash_config:
|
||||
return False
|
||||
|
||||
# 生成头文件
|
||||
if not self._generate_header_file():
|
||||
return False
|
||||
|
||||
# 生成源文件
|
||||
if not self._generate_source_file():
|
||||
return False
|
||||
|
||||
self._save_config()
|
||||
return True
|
||||
|
||||
def _generate_header_file(self):
|
||||
"""生成flash.h"""
|
||||
periph_folder = "flash"
|
||||
template_base_dir = CodeGenerator.get_assets_dir("User_code/bsp")
|
||||
template_path = os.path.join(template_base_dir, periph_folder, "flash.h")
|
||||
|
||||
if not os.path.exists(template_path):
|
||||
return False
|
||||
|
||||
template_content = CodeGenerator.load_template(template_path)
|
||||
if not template_content:
|
||||
return False
|
||||
|
||||
# 生成Sector/Page定义
|
||||
flash_type = self.flash_config.get('type', 'sector')
|
||||
sector_lines = []
|
||||
|
||||
for item in self.flash_config['sectors']:
|
||||
addr = item['address']
|
||||
size = item['size']
|
||||
item_id = item['id']
|
||||
|
||||
if flash_type == 'page':
|
||||
# F1系列 - Page模式
|
||||
sector_lines.append(
|
||||
f"#define ADDR_FLASH_PAGE_{item_id} ((uint32_t)0x{addr:08X})"
|
||||
)
|
||||
sector_lines.append(
|
||||
f"/* Base address of Page {item_id}, {size} Kbytes */"
|
||||
)
|
||||
else:
|
||||
# F4/H7系列 - Sector模式
|
||||
sector_lines.append(
|
||||
f"#define ADDR_FLASH_SECTOR_{item_id} ((uint32_t)0x{addr:08X})"
|
||||
)
|
||||
sector_lines.append(
|
||||
f"/* Base address of Sector {item_id}, {size} Kbytes */"
|
||||
)
|
||||
|
||||
content = CodeGenerator.replace_auto_generated(
|
||||
template_content, "AUTO GENERATED FLASH_SECTORS", "\n".join(sector_lines)
|
||||
)
|
||||
|
||||
# 生成结束地址
|
||||
end_addr = self.flash_config['end_address']
|
||||
end_line = f"#define ADDR_FLASH_END ((uint32_t)0x{end_addr:08X}) /* End address for flash */"
|
||||
content = CodeGenerator.replace_auto_generated(
|
||||
content, "AUTO GENERATED FLASH_END_ADDRESS", end_line
|
||||
)
|
||||
|
||||
output_path = os.path.join(self.project_path, "User/bsp/flash.h")
|
||||
CodeGenerator.save_with_preserve(output_path, content)
|
||||
return True
|
||||
|
||||
def _generate_source_file(self):
|
||||
"""生成flash.c"""
|
||||
periph_folder = "flash"
|
||||
template_base_dir = CodeGenerator.get_assets_dir("User_code/bsp")
|
||||
template_path = os.path.join(template_base_dir, periph_folder, "flash.c")
|
||||
|
||||
if not os.path.exists(template_path):
|
||||
return False
|
||||
|
||||
template_content = CodeGenerator.load_template(template_path)
|
||||
if not template_content:
|
||||
return False
|
||||
|
||||
# 生成最大Sector数定义
|
||||
max_sector = len(self.flash_config['sectors']) - 1
|
||||
max_sector_line = f"#define BSP_FLASH_MAX_SECTOR {max_sector}"
|
||||
content = CodeGenerator.replace_auto_generated(
|
||||
template_content, "AUTO GENERATED FLASH_MAX_SECTOR", max_sector_line
|
||||
)
|
||||
|
||||
# 生成擦除检查代码
|
||||
erase_check = f" if (sector > 0 && sector <= {max_sector}) {{"
|
||||
content = CodeGenerator.replace_auto_generated(
|
||||
content, "AUTO GENERATED FLASH_ERASE_CHECK", erase_check
|
||||
)
|
||||
|
||||
output_path = os.path.join(self.project_path, "User/bsp/flash.c")
|
||||
CodeGenerator.save_with_preserve(output_path, content)
|
||||
return True
|
||||
|
||||
def _save_config(self):
|
||||
"""保存配置"""
|
||||
config_path = os.path.join(self.project_path, "User/bsp/bsp_config.yaml")
|
||||
config_data = CodeGenerator.load_config(config_path)
|
||||
config_data['flash'] = {
|
||||
'enabled': True,
|
||||
'mcu_name': self.mcu_name,
|
||||
'dual_bank': self.flash_config['dual_bank'],
|
||||
'sectors': len(self.flash_config['sectors'])
|
||||
}
|
||||
CodeGenerator.save_config(config_data, config_path)
|
||||
|
||||
def _load_config(self):
|
||||
"""加载配置"""
|
||||
config_path = os.path.join(self.project_path, "User/bsp/bsp_config.yaml")
|
||||
config_data = CodeGenerator.load_config(config_path)
|
||||
conf = config_data.get('flash', {})
|
||||
if conf.get('enabled', False):
|
||||
self.generate_checkbox.setChecked(True)
|
||||
|
||||
|
||||
# 更新get_bsp_page函数以包含PWM和Flash
|
||||
def get_bsp_page(peripheral_name, project_path):
|
||||
"""根据外设名返回对应的页面类,没有特殊类则返回默认BspSimplePeripheral"""
|
||||
name_lower = peripheral_name.lower()
|
||||
@ -1387,7 +1605,8 @@ def get_bsp_page(peripheral_name, project_path):
|
||||
"spi": bsp_spi,
|
||||
"uart": bsp_uart,
|
||||
"gpio": bsp_gpio,
|
||||
"pwm": bsp_pwm, # 添加PWM
|
||||
"pwm": bsp_pwm,
|
||||
"flash": bsp_flash, # 添加Flash自动配置
|
||||
# 以后可以继续添加特殊外设
|
||||
}
|
||||
if name_lower in special_classes:
|
||||
|
||||
@ -342,3 +342,241 @@ class analyzing_ioc:
|
||||
})
|
||||
|
||||
return pwm_channels
|
||||
|
||||
@staticmethod
|
||||
def get_mcu_name_from_ioc(ioc_path):
|
||||
"""
|
||||
从.ioc文件中获取MCU型号
|
||||
返回格式: 'STM32F407IGHx' 等
|
||||
"""
|
||||
with open(ioc_path, encoding='utf-8', errors='ignore') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if not line or line.startswith('#'):
|
||||
continue
|
||||
if '=' in line:
|
||||
key, value = line.split('=', 1)
|
||||
key = key.strip()
|
||||
value = value.strip()
|
||||
# 查找MCU名称
|
||||
if key == 'Mcu.UserName' or key == 'Mcu.Name':
|
||||
return value
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def get_flash_config_from_mcu(mcu_name):
|
||||
"""
|
||||
根据MCU型号返回Flash配置
|
||||
支持STM32F1/F4/H7系列
|
||||
返回格式: {
|
||||
'sectors': [...], # Sector/Page配置列表
|
||||
'dual_bank': False, # 是否双Bank
|
||||
'end_address': 0x08100000, # Flash结束地址
|
||||
'type': 'sector' or 'page' # Flash类型
|
||||
}
|
||||
"""
|
||||
if not mcu_name:
|
||||
return None
|
||||
|
||||
mcu_upper = mcu_name.upper()
|
||||
|
||||
# STM32F1系列 - 使用Page而不是Sector
|
||||
if mcu_upper.startswith('STM32F1'):
|
||||
return analyzing_ioc._get_stm32f1_flash_config(mcu_upper)
|
||||
|
||||
# STM32F4系列 - 使用Sector
|
||||
elif mcu_upper.startswith('STM32F4'):
|
||||
return analyzing_ioc._get_stm32f4_flash_config(mcu_upper)
|
||||
|
||||
# STM32H7系列 - 使用Sector
|
||||
elif mcu_upper.startswith('STM32H7'):
|
||||
return analyzing_ioc._get_stm32h7_flash_config(mcu_upper)
|
||||
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _get_stm32f1_flash_config(mcu_upper):
|
||||
"""
|
||||
STM32F1系列Flash配置
|
||||
F1使用Page而不是Sector
|
||||
- 小/中容量设备: 1KB/page
|
||||
- 大容量/互联型设备: 2KB/page
|
||||
容量代码: 4/6=16/32KB, 8/B=64/128KB, C=256KB, D/E=384/512KB, F/G=768KB/1MB
|
||||
"""
|
||||
flash_size_map_f1 = {
|
||||
'4': 16, # 16KB
|
||||
'6': 32, # 32KB
|
||||
'8': 64, # 64KB
|
||||
'B': 128, # 128KB
|
||||
'C': 256, # 256KB
|
||||
'D': 384, # 384KB
|
||||
'E': 512, # 512KB
|
||||
'F': 768, # 768KB (互联型)
|
||||
'G': 1024, # 1MB (互联型)
|
||||
}
|
||||
|
||||
# F1命名: STM32F103C8T6, C在索引9
|
||||
if len(mcu_upper) < 10:
|
||||
return None
|
||||
|
||||
flash_code = mcu_upper[9]
|
||||
flash_size = flash_size_map_f1.get(flash_code)
|
||||
|
||||
if not flash_size:
|
||||
return None
|
||||
|
||||
# 判断页大小: <=128KB用1KB页, >128KB用2KB页
|
||||
page_size = 1 if flash_size <= 128 else 2
|
||||
num_pages = flash_size // page_size
|
||||
|
||||
config = {
|
||||
'type': 'page',
|
||||
'dual_bank': False,
|
||||
'sectors': [], # F1中这里存的是Page
|
||||
'page_size': page_size,
|
||||
}
|
||||
|
||||
# 生成所有页
|
||||
current_address = 0x08000000
|
||||
for page_id in range(num_pages):
|
||||
config['sectors'].append({
|
||||
'id': page_id,
|
||||
'address': current_address,
|
||||
'size': page_size
|
||||
})
|
||||
current_address += page_size * 1024
|
||||
|
||||
config['end_address'] = current_address
|
||||
return config
|
||||
|
||||
@staticmethod
|
||||
def _get_stm32f4_flash_config(mcu_upper):
|
||||
"""
|
||||
STM32F4系列Flash配置
|
||||
容量代码: C=256KB, E=512KB, G=1MB, I=2MB
|
||||
"""
|
||||
flash_size_map = {
|
||||
'C': 256, # 256KB
|
||||
'E': 512, # 512KB
|
||||
'G': 1024, # 1MB
|
||||
'I': 2048, # 2MB
|
||||
}
|
||||
|
||||
# F4命名: STM32F407IGHx, I在索引9
|
||||
if len(mcu_upper) < 10:
|
||||
return None
|
||||
|
||||
flash_code = mcu_upper[9]
|
||||
flash_size = flash_size_map.get(flash_code)
|
||||
|
||||
if not flash_size:
|
||||
return None
|
||||
|
||||
config = {
|
||||
'type': 'sector',
|
||||
'dual_bank': False,
|
||||
'sectors': [],
|
||||
}
|
||||
|
||||
# STM32F4系列单Bank Flash布局
|
||||
# Sector 0-3: 16KB each
|
||||
# Sector 4: 64KB
|
||||
# Sector 5-11: 128KB each (如果有)
|
||||
|
||||
base_sectors = [
|
||||
{'id': 0, 'address': 0x08000000, 'size': 16},
|
||||
{'id': 1, 'address': 0x08004000, 'size': 16},
|
||||
{'id': 2, 'address': 0x08008000, 'size': 16},
|
||||
{'id': 3, 'address': 0x0800C000, 'size': 16},
|
||||
{'id': 4, 'address': 0x08010000, 'size': 64},
|
||||
]
|
||||
|
||||
config['sectors'] = base_sectors.copy()
|
||||
current_address = 0x08020000
|
||||
current_id = 5
|
||||
remaining_kb = flash_size - (16 * 4 + 64) # 减去前5个sector
|
||||
|
||||
# 添加128KB的sectors
|
||||
while remaining_kb > 0 and current_id < 12:
|
||||
config['sectors'].append({
|
||||
'id': current_id,
|
||||
'address': current_address,
|
||||
'size': 128
|
||||
})
|
||||
current_address += 0x20000 # 128KB
|
||||
remaining_kb -= 128
|
||||
current_id += 1
|
||||
|
||||
# 设置结束地址
|
||||
config['end_address'] = current_address
|
||||
|
||||
# 2MB Flash需要双Bank (Sector 12-23)
|
||||
if flash_size >= 2048:
|
||||
config['dual_bank'] = True
|
||||
# Bank 2 的sectors (12-15: 16KB, 16: 64KB, 17-23: 128KB)
|
||||
bank2_sectors = [
|
||||
{'id': 12, 'address': 0x08100000, 'size': 16},
|
||||
{'id': 13, 'address': 0x08104000, 'size': 16},
|
||||
{'id': 14, 'address': 0x08108000, 'size': 16},
|
||||
{'id': 15, 'address': 0x0810C000, 'size': 16},
|
||||
{'id': 16, 'address': 0x08110000, 'size': 64},
|
||||
{'id': 17, 'address': 0x08120000, 'size': 128},
|
||||
{'id': 18, 'address': 0x08140000, 'size': 128},
|
||||
{'id': 19, 'address': 0x08160000, 'size': 128},
|
||||
{'id': 20, 'address': 0x08180000, 'size': 128},
|
||||
{'id': 21, 'address': 0x081A0000, 'size': 128},
|
||||
{'id': 22, 'address': 0x081C0000, 'size': 128},
|
||||
{'id': 23, 'address': 0x081E0000, 'size': 128},
|
||||
]
|
||||
config['sectors'].extend(bank2_sectors)
|
||||
config['end_address'] = 0x08200000
|
||||
|
||||
return config
|
||||
|
||||
@staticmethod
|
||||
def _get_stm32h7_flash_config(mcu_upper):
|
||||
"""
|
||||
STM32H7系列Flash配置
|
||||
- 每个Sector 128KB
|
||||
- 单Bank: 8个Sector (1MB)
|
||||
- 双Bank: 16个Sector (2MB), 每个Bank 8个Sector
|
||||
容量代码: B=128KB, G=1MB, I=2MB
|
||||
命名格式: STM32H7 + 23 + V(引脚) + G(容量) + T(封装) + 6
|
||||
"""
|
||||
flash_size_map_h7 = {
|
||||
'B': 128, # 128KB (1个Sector)
|
||||
'G': 1024, # 1MB (8个Sector, 单Bank)
|
||||
'I': 2048, # 2MB (16个Sector, 双Bank)
|
||||
}
|
||||
|
||||
# H7命名: STM32H723VGT6, G在索引10
|
||||
if len(mcu_upper) < 11:
|
||||
return None
|
||||
|
||||
flash_code = mcu_upper[10]
|
||||
flash_size = flash_size_map_h7.get(flash_code)
|
||||
|
||||
if not flash_size:
|
||||
return None
|
||||
|
||||
config = {
|
||||
'type': 'sector',
|
||||
'dual_bank': flash_size >= 2048,
|
||||
'sectors': [],
|
||||
}
|
||||
|
||||
num_sectors = flash_size // 128 # 每个Sector 128KB
|
||||
|
||||
# 生成Sector配置
|
||||
current_address = 0x08000000
|
||||
for sector_id in range(num_sectors):
|
||||
config['sectors'].append({
|
||||
'id': sector_id,
|
||||
'address': current_address,
|
||||
'size': 128,
|
||||
'bank': 1 if sector_id < 8 else 2 # Bank信息
|
||||
})
|
||||
current_address += 0x20000 # 128KB
|
||||
|
||||
config['end_address'] = current_address
|
||||
return config
|
||||
@ -9,4 +9,4 @@ time,获取时间戳函数,需要开启freerots
|
||||
dwt,需要开启dwt,获取时间
|
||||
i2c,请开启i2c的dma和中断
|
||||
pwm,用于选择那些勇于输出pwm
|
||||
|
||||
flash,自动识别MCU型号并配置Flash,支持STM32F1(Page)/F4(Sector)/H7(Sector),自动处理单Bank/双Bank配置
|
||||
|
||||
|
77
assets/User_code/bsp/flash/CHANGELOG.md
Normal file
77
assets/User_code/bsp/flash/CHANGELOG.md
Normal file
@ -0,0 +1,77 @@
|
||||
# Flash BSP 更新日志
|
||||
|
||||
## v2.0 - 2026-01-01
|
||||
|
||||
### 新增功能
|
||||
✨ **多系列MCU支持**
|
||||
- 新增 STM32F1 系列支持(Page模式)
|
||||
- 新增 STM32H7 系列支持(Sector模式)
|
||||
- 保持 STM32F4 系列支持(Sector模式)
|
||||
|
||||
### STM32F1系列详情
|
||||
- **Flash组织**: Page模式(页)
|
||||
- **页大小**:
|
||||
- 小/中容量(≤128KB): 1KB/页
|
||||
- 大容量/互联型(>128KB): 2KB/页
|
||||
- **容量支持**: 16KB - 1MB
|
||||
- **容量代码**: 4/6/8/B/C/D/E/F/G
|
||||
- **生成宏**: `ADDR_FLASH_PAGE_X`
|
||||
|
||||
### STM32H7系列详情
|
||||
- **Flash组织**: Sector模式(扇区)
|
||||
- **扇区大小**: 固定128KB
|
||||
- **容量支持**: 128KB - 2MB
|
||||
- **容量代码**: B/G/I
|
||||
- **Bank支持**:
|
||||
- 单Bank: 1MB (8个Sector)
|
||||
- 双Bank: 2MB (16个Sector)
|
||||
- **生成宏**: `ADDR_FLASH_SECTOR_X`
|
||||
|
||||
### 技术改进
|
||||
- 重构 `get_flash_config_from_mcu()` 函数为多系列架构
|
||||
- 新增 `_get_stm32f1_flash_config()` - F1系列专用配置
|
||||
- 新增 `_get_stm32f4_flash_config()` - F4系列专用配置
|
||||
- 新增 `_get_stm32h7_flash_config()` - H7系列专用配置
|
||||
- 配置中新增 `type` 字段区分 'page' 和 'sector' 模式
|
||||
- 界面自动识别并显示Page或Sector模式
|
||||
- 代码生成支持Page和Sector两种宏定义
|
||||
|
||||
### 示例支持的芯片型号
|
||||
**STM32F1:**
|
||||
- STM32F103C8T6 → 64KB (64 pages × 1KB)
|
||||
- STM32F103RCT6 → 256KB (128 pages × 2KB)
|
||||
- STM32F103ZET6 → 512KB (256 pages × 2KB)
|
||||
|
||||
**STM32F4:**
|
||||
- STM32F407VGT6 → 1MB (Sector 0-11)
|
||||
- STM32F407IGH6 → 2MB (Sector 0-23, 双Bank)
|
||||
- STM32F405RGT6 → 1MB (Sector 0-11)
|
||||
|
||||
**STM32H7:**
|
||||
- STM32H750VBT6 → 128KB (1 sector)
|
||||
- STM32H743VGT6 → 1MB (8 sectors)
|
||||
- STM32H743VIT6 → 2MB (16 sectors, 双Bank)
|
||||
|
||||
### 配置文件变化
|
||||
```yaml
|
||||
# 新增字段
|
||||
flash:
|
||||
type: page # 或 sector
|
||||
page_size: 2 # 仅F1系列有此字段
|
||||
```
|
||||
|
||||
### 文档更新
|
||||
- 更新 README.md 包含三个系列的完整说明
|
||||
- 新增各系列的Flash布局图
|
||||
- 新增各系列的使用示例
|
||||
- 更新注意事项包含擦除时间和寿命信息
|
||||
|
||||
---
|
||||
|
||||
## v1.0 - 初始版本
|
||||
|
||||
### 初始功能
|
||||
- STM32F4 系列支持
|
||||
- 自动识别芯片型号
|
||||
- 单Bank/双Bank配置
|
||||
- 基础API(擦除、读、写)
|
||||
346
assets/User_code/bsp/flash/README.md
Normal file
346
assets/User_code/bsp/flash/README.md
Normal file
@ -0,0 +1,346 @@
|
||||
# Flash BSP 自动配置说明
|
||||
|
||||
## 功能特性
|
||||
|
||||
Flash BSP模块能够自动识别STM32芯片型号并生成对应的Flash配置代码。
|
||||
|
||||
### 支持的芯片系列
|
||||
|
||||
#### STM32F1 系列
|
||||
- 使用**Page**组织方式(而非Sector)
|
||||
- 自动检测Flash容量(16KB - 1MB)
|
||||
- 小/中容量设备:1KB/页
|
||||
- 大容量/互联型设备:2KB/页
|
||||
|
||||
#### STM32F4 系列
|
||||
- 使用**Sector**组织方式
|
||||
- 自动检测Flash容量(256KB/512KB/1MB/2MB)
|
||||
- 自动配置单Bank或双Bank模式
|
||||
- 不同大小的Sector(16KB/64KB/128KB)
|
||||
|
||||
#### STM32H7 系列
|
||||
- 使用**Sector**组织方式
|
||||
- 每个Sector固定128KB
|
||||
- 自动检测Flash容量(128KB/1MB/2MB)
|
||||
- 自动配置单Bank或双Bank模式
|
||||
|
||||
### Flash容量识别规则
|
||||
|
||||
根据STM32命名规则中的第9位字符识别Flash容量:
|
||||
|
||||
**STM32F1系列:**
|
||||
- **4**: 16KB (16 pages × 1KB)
|
||||
- **6**: 32KB (32 pages × 1KB)
|
||||
- **8**: 64KB (64 pages × 1KB)
|
||||
- **B**: 128KB (128 pages × 1KB)
|
||||
- **C**: 256KB (128 pages × 2KB)
|
||||
- **D**: 384KB (192 pages × 2KB)
|
||||
- **E**: 512KB (256 pages × 2KB)
|
||||
- **F**: 768KB (384 pages × 2KB, 互联型)
|
||||
- **G**: 1MB (512 pages × 2KB, 互联型)
|
||||
|
||||
**STM32F4系列:**
|
||||
- **C**: 256KB (单Bank, Sector 0-7)
|
||||
- **E**: 512KB (单Bank, Sector 0-9)
|
||||
- **G**: 1MB (单Bank, Sector 0-11)
|
||||
- **I**: 2MB (双Bank, Sector 0-23)
|
||||
|
||||
**STM32H7系列:**
|
||||
- **B**: 128KB (1个Sector, 单Bank)
|
||||
- **G**: 1MB (8个Sector, 单Bank)
|
||||
- **I**: 2MB (16个Sector, 双Bank)
|
||||
|
||||
例如:
|
||||
- `STM32F103C8T6` → 64KB Flash (64 pages × 1KB)
|
||||
- `STM32F103RCT6` → 256KB Flash (128 pages × 2KB)
|
||||
- `STM32F103ZET6` → 512KB Flash (256 pages × 2KB)
|
||||
- `STM32F407VGT6` → 1MB Flash (Sector 0-11)
|
||||
- `STM32F407IGH6` → 2MB Flash (Sector 0-23, 双Bank)
|
||||
- `STM32F405RGT6` → 1MB Flash (Sector 0-11)
|
||||
- `STM32H743VIT6` → 2MB Flash (16 sectors × 128KB, 双Bank)
|
||||
- `STM32H750VBT6` → 128KB Flash (1 sector × 128KB)
|
||||
|
||||
## Flash布局
|
||||
|
||||
### STM32F1 Page模式 (16KB - 1MB)
|
||||
```
|
||||
小/中容量 (≤128KB): 每页1KB
|
||||
Page 0: 0x08000000 - 0x080003FF (1KB)
|
||||
Page 1: 0x08000400 - 0x080007FF (1KB)
|
||||
...
|
||||
|
||||
大容量/互联型 (>128KB): 每页2KB
|
||||
Page 0: 0x08000000 - 0x080007FF (2KB)
|
||||
Page 1: 0x08000800 - 0x08000FFF (2KB)
|
||||
...
|
||||
```
|
||||
|
||||
### STM32F4 单Bank模式 (256KB - 1MB)
|
||||
```
|
||||
Sector 0-3: 16KB each (0x08000000 - 0x0800FFFF)
|
||||
Sector 4: 64KB (0x08010000 - 0x0801FFFF)
|
||||
Sector 5-11: 128KB each (0x08020000 - 0x080FFFFF)
|
||||
```
|
||||
|
||||
### STM32F4 双Bank模式 (2MB)
|
||||
```
|
||||
Bank 1:
|
||||
Sector 0-3: 16KB each (0x08000000 - 0x0800FFFF)
|
||||
Sector 4: 64KB (0x08010000 - 0x0801FFFF)
|
||||
Sector 5-11: 128KB each (0x08020000 - 0x080FFFFF)
|
||||
|
||||
Bank 2:
|
||||
Sector 12-15: 16KB each (0x08100000 - 0x0810FFFF)
|
||||
Sector 16: 64KB (0x08110000 - 0x0811FFFF)
|
||||
Sector 17-23: 128KB each (0x08120000 - 0x081FFFFF)
|
||||
```
|
||||
|
||||
### STM32H7 Sector模式
|
||||
```
|
||||
单Bank (1MB):
|
||||
Sector 0-7: 128KB each (0x08000000 - 0x080FFFFF)
|
||||
|
||||
双Bank (2MB):
|
||||
Bank 1:
|
||||
Sector 0-7: 128KB each (0x08000000 - 0x080FFFFF)
|
||||
Bank 2:
|
||||
Sector 8-15: 128KB each (0x08100000 - 0x081FFFFF)
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 1. 在BSP配置界面启用Flash
|
||||
在代码生成界面的BSP标签中,勾选"生成 Flash 代码"选项。
|
||||
|
||||
### 2. 自动检测
|
||||
系统会自动:
|
||||
- 读取项目中的`.ioc`文件
|
||||
- 提取MCU型号信息
|
||||
- 计算Flash扇区配置
|
||||
- 生成对应的宏定义
|
||||
|
||||
### 3. 生成的代码示例
|
||||
|
||||
**STM32F1系列** (以STM32F103RCT6为例 - 256KB):
|
||||
```c
|
||||
// flash.h
|
||||
#define ADDR_FLASH_PAGE_0 ((uint32_t)0x08000000)
|
||||
/* Base address of Page 0, 2 Kbytes */
|
||||
#define ADDR_FLASH_PAGE_1 ((uint32_t)0x08000800)
|
||||
/* Base address of Page 1, 2 Kbytes */
|
||||
...
|
||||
#define ADDR_FLASH_PAGE_127 ((uint32_t)0x0803F800)
|
||||
/* Base address of Page 127, 2 Kbytes */
|
||||
#define ADDR_FLASH_END ((uint32_t)0x08040000)
|
||||
|
||||
// flash.c
|
||||
#define BSP_FLASH_MAX_PAGE 127
|
||||
if (page >= 0 && page <= 127) {
|
||||
// 擦除代码...
|
||||
}
|
||||
```
|
||||
|
||||
**STM32F4系列** (以STM32F407IGH6为例 - 2MB):
|
||||
```c
|
||||
// flash.h
|
||||
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000)
|
||||
/* Base address of Sector 0, 16 Kbytes */
|
||||
...
|
||||
#define ADDR_FLASH_SECTOR_23 ((uint32_t)0x081E0000)
|
||||
/* Base address of Sector 23, 128 Kbytes */
|
||||
|
||||
#define ADDR_FLASH_END ((uint32_t)0x08200000)
|
||||
/* End address for flash */
|
||||
```
|
||||
|
||||
**flash.c**:
|
||||
```c
|
||||
#define BSP_FLASH_MAX_SECTOR 23
|
||||
|
||||
void BSP_Flash_EraseSector(uint32_t sector) {
|
||||
if (sector > 0 && sector <= 23) {
|
||||
// 擦除代码...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**STM32H7系列** (以STM32H743VIT6为例 - 2MB):
|
||||
```c
|
||||
// flash.h
|
||||
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000)
|
||||
/* Base address of Sector 0, 128 Kbytes */
|
||||
...
|
||||
#define ADDR_FLASH_SECTOR_15 ((uint32_t)0x081E0000)
|
||||
/* Base address of Sector 15, 128 Kbytes */
|
||||
|
||||
#define ADDR_FLASH_END ((uint32_t)0x08200000)
|
||||
|
||||
// flash.c
|
||||
#define BSP_FLASH_MAX_SECTOR 15
|
||||
if (sector > 0 && sector <= 15) {
|
||||
// 擦除代码...
|
||||
}
|
||||
```
|
||||
|
||||
## API接口
|
||||
|
||||
### BSP_Flash_EraseSector (F4/H7) / BSP_Flash_ErasePage (F1)
|
||||
擦除指定扇区或页
|
||||
```c
|
||||
// F4/H7系列
|
||||
void BSP_Flash_EraseSector(uint32_t sector);
|
||||
// F1系列
|
||||
void BSP_Flash_ErasePage(uint32_t page);
|
||||
```
|
||||
- **参数**:
|
||||
- sector/page - 扇区号或页号
|
||||
- F1: 0 到 (页数-1)
|
||||
- F4: 0-11 或 0-23(根据芯片型号)
|
||||
- H7: 0-7 或 0-15(根据芯片型号)
|
||||
|
||||
### BSP_Flash_WriteBytes
|
||||
写入数据到Flash
|
||||
```c
|
||||
void BSP_Flash_WriteBytes(uint32_t address, const uint8_t *buf, size_t len);
|
||||
```
|
||||
- **参数**:
|
||||
- address - Flash地址
|
||||
- buf - 数据缓冲区
|
||||
- len - 数据长度
|
||||
|
||||
### BSP_Flash_ReadBytes
|
||||
从Flash读取数据
|
||||
```c
|
||||
void BSP_Flash_ReadBytes(uint32_t address, void *buf, size_t len);
|
||||
```
|
||||
- **参数**:
|
||||
- address - Flash地址
|
||||
- buf - 接收缓冲区
|
||||
- len - 读取长度
|
||||
|
||||
## 使用示例
|
||||
|
||||
### STM32F1系列示例
|
||||
```c
|
||||
#include "bsp/flash.h"
|
||||
|
||||
void save_config_f1(void) {
|
||||
// 擦除Page 127 (最后一页,通常用于存储用户数据)
|
||||
BSP_Flash_ErasePage(127);
|
||||
|
||||
// 写入配置数据
|
||||
uint8_t config[100] = {/* 配置数据 */};
|
||||
BSP_Flash_WriteBytes(ADDR_FLASH_PAGE_127, config, sizeof(config));
|
||||
}
|
||||
|
||||
void load_config_f1(void) {
|
||||
// 读取配置数据
|
||||
uint8_t config[100];
|
||||
BSP_Flash_ReadBytes(ADDR_FLASH_PAGE_127, config, sizeof(config));
|
||||
}
|
||||
```
|
||||
|
||||
### STM32F4系列示例
|
||||
```c
|
||||
#include "bsp/flash.h"
|
||||
|
||||
void save_config_f4(void) {
|
||||
// 擦除Sector 11 (通常用于存储用户数据)
|
||||
BSP_Flash_EraseSector(11);
|
||||
|
||||
// 写入配置数据
|
||||
uint8_t config[100] = {/* 配置数据 */};
|
||||
BSP_Flash_WriteBytes(ADDR_FLASH_SECTOR_11, config, sizeof(config));
|
||||
}
|
||||
|
||||
void load_config_f4(void) {
|
||||
// 读取配置数据
|
||||
uint8_t config[100];
|
||||
BSP_Flash_ReadBytes(ADDR_FLASH_SECTOR_11, config, sizeof(config));
|
||||
}
|
||||
```
|
||||
|
||||
### STM32H7系列示例
|
||||
|
||||
### STM32H7系列示例
|
||||
```c
|
||||
#include "bsp/flash.h"
|
||||
|
||||
void save_config(void) {
|
||||
// 擦除Sector 11 (通常用于存储用户数据)
|
||||
BSP_Flash_EraseSector(11);
|
||||
|
||||
// 写入配置数据
|
||||
uint8_t config[100] = {/* 配置数据 */};
|
||||
BSP_Flash_WriteBytes(ADDR_FLASH_SECTOR_11, config, sizeof(config));
|
||||
}
|
||||
|
||||
void load_config(void) {
|
||||
// 读取配置数据
|
||||
uint8_t config[100];
|
||||
BSP_Flash_ReadBytes(ADDR_FLASH_SECTOR_11, config, sizeof(config));
|
||||
}
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **擦除时间**: Flash擦除需要一定时间,注意不要在中断中执行
|
||||
- F1 Page擦除: ~20ms
|
||||
- F4 Sector擦除: 16KB~100ms, 64KB~300ms, 128KB~500ms
|
||||
- H7 Sector擦除: ~200ms
|
||||
2. **写入前擦除**:
|
||||
- F1: 必须先擦除整页才能写入
|
||||
- F4/H7: 必须先擦除整个扇区才能写入
|
||||
3. **区域选择**: 避免擦除包含程序代码的扇区/页
|
||||
- F1: 通常最后几页用于存储数据
|
||||
- F4: Sector 11 或 23 常用于存储数据
|
||||
- H7: Sector 7 或 15 常用于存储数据
|
||||
4. **写入对齐**: 建议按字节写入,HAL库会处理对齐
|
||||
5. **断电保护**: 写入过程中断电可能导致数据丢失
|
||||
6. **擦写次数限制**:
|
||||
- F1: 典型10,000次
|
||||
- F4/H7: 典型10,000-100,000次
|
||||
|
||||
## 配置文件
|
||||
|
||||
配置信息保存在 `bsp_config.yaml`:
|
||||
|
||||
**STM32F1:**
|
||||
```yaml
|
||||
flash:
|
||||
enabled: true
|
||||
mcu_name: STM32F103RCT6
|
||||
dual_bank: false
|
||||
sectors: 128 # 实际是128个页
|
||||
type: page
|
||||
page_size: 2
|
||||
```
|
||||
|
||||
**STM32F4:**
|
||||
```yaml
|
||||
flash:
|
||||
enabled: true
|
||||
mcu_name: STM32F407IGHx
|
||||
dual_bank: true
|
||||
sectors: 24
|
||||
type: sector
|
||||
```
|
||||
|
||||
**STM32H7:**
|
||||
```yaml
|
||||
flash:
|
||||
enabled: true
|
||||
mcu_name: STM32H743VIT6
|
||||
dual_bank: true
|
||||
sectors: 16
|
||||
type: sector
|
||||
```
|
||||
|
||||
## 扩展支持
|
||||
|
||||
当前支持的系列:
|
||||
- ✅ STM32F1 (Page模式)
|
||||
- ✅ STM32F4 (Sector模式)
|
||||
- ✅ STM32H7 (Sector模式)
|
||||
|
||||
如需支持其他STM32系列(如F2/F3/L4/G4等),可在 `analyzing_ioc.py` 的 `get_flash_config_from_mcu()` 函数中添加相应的配置规则。
|
||||
55
assets/User_code/bsp/flash/flash.c
Normal file
55
assets/User_code/bsp/flash/flash.c
Normal file
@ -0,0 +1,55 @@
|
||||
/* Includes ----------------------------------------------------------------- */
|
||||
#include "bsp/flash.h"
|
||||
|
||||
#include <main.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Private define ----------------------------------------------------------- */
|
||||
/* USER CODE BEGIN FLASH_MAX_SECTOR */
|
||||
/* AUTO GENERATED FLASH_MAX_SECTOR */
|
||||
/* USER CODE END FLASH_MAX_SECTOR */
|
||||
|
||||
/* Private macro ------------------------------------------------------------ */
|
||||
/* Private typedef ---------------------------------------------------------- */
|
||||
/* Private variables -------------------------------------------------------- */
|
||||
/* Private function -------------------------------------------------------- */
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
void BSP_Flash_EraseSector(uint32_t sector) {
|
||||
FLASH_EraseInitTypeDef flash_erase;
|
||||
uint32_t sector_error;
|
||||
|
||||
/* USER CODE BEGIN FLASH_ERASE_CHECK */
|
||||
/* AUTO GENERATED FLASH_ERASE_CHECK */
|
||||
/* USER CODE END FLASH_ERASE_CHECK */
|
||||
flash_erase.Sector = sector;
|
||||
flash_erase.TypeErase = FLASH_TYPEERASE_SECTORS;
|
||||
flash_erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
|
||||
flash_erase.NbSectors = 1;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
while (FLASH_WaitForLastOperation(50) != HAL_OK)
|
||||
;
|
||||
HAL_FLASHEx_Erase(&flash_erase, §or_error);
|
||||
HAL_FLASH_Lock();
|
||||
}
|
||||
/* USER CODE BEGIN FLASH_ERASE_END */
|
||||
/* USER CODE END FLASH_ERASE_END */
|
||||
}
|
||||
|
||||
void BSP_Flash_WriteBytes(uint32_t address, const uint8_t *buf, size_t len) {
|
||||
HAL_FLASH_Unlock();
|
||||
while (len > 0) {
|
||||
while (FLASH_WaitForLastOperation(50) != HAL_OK)
|
||||
;
|
||||
HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, address, *buf);
|
||||
address++;
|
||||
buf++;
|
||||
len--;
|
||||
}
|
||||
HAL_FLASH_Lock();
|
||||
}
|
||||
|
||||
void BSP_Flash_ReadBytes(uint32_t address, void *buf, size_t len) {
|
||||
memcpy(buf, (void *)address, len);
|
||||
}
|
||||
31
assets/User_code/bsp/flash/flash.h
Normal file
31
assets/User_code/bsp/flash/flash.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------ */
|
||||
#include <main.h>
|
||||
|
||||
#include "bsp/bsp.h"
|
||||
|
||||
/* Exported constants -------------------------------------------------------- */
|
||||
/* Base address of the Flash sectors */
|
||||
/* USER CODE BEGIN FLASH_SECTOR_DEFINES */
|
||||
/* AUTO GENERATED FLASH_SECTORS */
|
||||
/* USER CODE END FLASH_SECTOR_DEFINES */
|
||||
|
||||
/* USER CODE BEGIN FLASH_END_ADDRESS */
|
||||
/* AUTO GENERATED FLASH_END_ADDRESS */
|
||||
/* USER CODE END FLASH_END_ADDRESS */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------ */
|
||||
/* Exported types ------------------------------------------------------------ */
|
||||
/* Exported functions prototypes --------------------------------------------- */
|
||||
void BSP_Flash_EraseSector(uint32_t sector);
|
||||
void BSP_Flash_WriteBytes(uint32_t address, const uint8_t *buf, size_t len);
|
||||
void BSP_Flash_ReadBytes(uint32_t address, void *buf, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -1,4 +1,4 @@
|
||||
bsp,can,fdcan,dwt,gpio,i2c,mm,spi,uart,pwm,time
|
||||
bsp,can,fdcan,dwt,gpio,i2c,mm,spi,uart,pwm,time,flash
|
||||
component,ahrs,capacity,cmd,crc8,crc16,error_detect,filter,FreeRTOS_CLI,limiter,mixer,pid,ui,user_math
|
||||
device,dr16,bmi088,ist8310,motor,motor_rm,motor_dm,motor_vesc,motor_lk,motor_lz,motor_odrive,dm_imu,rc_can,servo,buzzer,led,ws2812,vofa,ops9,oid,lcd_driver
|
||||
module,config,
|
||||
|
Loading…
Reference in New Issue
Block a user