mirror of
https://github.com/goldenfishs/MRobot.git
synced 2026-03-31 21:07:14 +08:00
Merge fdcan-feature into main
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -803,6 +803,92 @@ class bsp_spi(BspPeripheralBase):
|
||||
)
|
||||
|
||||
|
||||
class bsp_fdcan(BspPeripheralBase):
|
||||
def __init__(self, project_path):
|
||||
super().__init__(
|
||||
project_path,
|
||||
"FDCAN",
|
||||
{'header': 'fdcan.h', 'source': 'fdcan.c'},
|
||||
"BSP_FDCAN",
|
||||
"hfdcan",
|
||||
"fdcan",
|
||||
get_available_fdcan
|
||||
)
|
||||
|
||||
def _generate_header_file(self, configs, template_dir):
|
||||
"""生成FDCAN头文件,包含动态宏定义"""
|
||||
template_path = os.path.join(template_dir, self.template_names['header'])
|
||||
template_content = CodeGenerator.load_template(template_path)
|
||||
if not template_content:
|
||||
return False
|
||||
|
||||
# 生成枚举
|
||||
enum_lines = [f" {self.enum_prefix}_{name}," for name, _ in configs]
|
||||
content = CodeGenerator.replace_auto_generated(
|
||||
template_content, f"AUTO GENERATED {self.enum_prefix}_NAME", "\n".join(enum_lines)
|
||||
)
|
||||
|
||||
# 生成FDCAN实例使能宏定义
|
||||
macro_lines = []
|
||||
for name, instance in configs:
|
||||
fdcan_num = ''.join(filter(str.isdigit, instance)) # 提取数字,如FDCAN1 -> 1
|
||||
macro_lines.append(f"#define {instance}_EN")
|
||||
|
||||
# 替换宏定义区域
|
||||
content = CodeGenerator.replace_auto_generated(
|
||||
content, "AUTO GENERATED FDCAN_EN", "\n".join(macro_lines)
|
||||
)
|
||||
|
||||
# 生成FIFO配置宏定义
|
||||
fifo_lines = []
|
||||
fdcan_count = len(configs)
|
||||
for idx, (name, instance) in enumerate(configs):
|
||||
fdcan_num = ''.join(filter(str.isdigit, instance))
|
||||
# FDCAN1使用FIFO0,其他使用FIFO1
|
||||
if instance == 'FDCAN1':
|
||||
fifo_lines.append(f"#define {instance}_RX_FIFO 0")
|
||||
else:
|
||||
fifo_lines.append(f"#define {instance}_RX_FIFO 1")
|
||||
|
||||
content = CodeGenerator.replace_auto_generated(
|
||||
content, "AUTO GENERATED FDCAN_RX_FIFO", "\n".join(fifo_lines)
|
||||
)
|
||||
|
||||
output_path = os.path.join(self.project_path, f"User/bsp/{self.template_names['header']}")
|
||||
CodeGenerator.save_with_preserve(output_path, content)
|
||||
return True
|
||||
|
||||
def _generate_source_file(self, configs, template_dir):
|
||||
"""生成FDCAN源文件"""
|
||||
template_path = os.path.join(template_dir, self.template_names['source'])
|
||||
template_content = CodeGenerator.load_template(template_path)
|
||||
if not template_content:
|
||||
return False
|
||||
|
||||
# Get函数
|
||||
get_lines = []
|
||||
for idx, (name, instance) in enumerate(configs):
|
||||
get_lines.append(f" case {idx}: return {self.enum_prefix}_{name};")
|
||||
content = CodeGenerator.replace_auto_generated(
|
||||
template_content, "AUTO GENERATED FDCAN_GET", "\n".join(get_lines)
|
||||
)
|
||||
|
||||
# Handle函数
|
||||
handle_lines = []
|
||||
for name, instance in configs:
|
||||
fdcan_num = ''.join(filter(str.isdigit, instance))
|
||||
handle_lines.append(f"#ifdef {instance}_EN")
|
||||
handle_lines.append(f" case {self.enum_prefix}_{name}: return &{self.handle_prefix}{fdcan_num};")
|
||||
handle_lines.append(f"#endif")
|
||||
content = CodeGenerator.replace_auto_generated(
|
||||
content, f"AUTO GENERATED {self.enum_prefix}_GET_HANDLE", "\n".join(handle_lines)
|
||||
)
|
||||
|
||||
output_path = os.path.join(self.project_path, f"User/bsp/{self.template_names['source']}")
|
||||
CodeGenerator.save_with_preserve(output_path, content)
|
||||
return True
|
||||
|
||||
|
||||
def patch_uart_interrupts(project_path, uart_instances):
|
||||
"""自动修改 stm32f4xx_it.c,插入 UART BSP 相关代码"""
|
||||
it_path = os.path.join(project_path, "Core/Src/stm32f4xx_it.c")
|
||||
|
||||
@@ -5,10 +5,20 @@ import sys
|
||||
import os
|
||||
|
||||
def resource_path(relative_path):
|
||||
"""获取资源文件的绝对路径,兼容打包和开发环境"""
|
||||
if hasattr(sys, '_MEIPASS'):
|
||||
# PyInstaller 打包后的临时目录
|
||||
return os.path.join(sys._MEIPASS, relative_path)
|
||||
"""获取资源文件的绝对路径,兼容打包和开发环境
|
||||
对于 logo 文件,使用打包的临时目录(只有 logo 被打包)
|
||||
对于其他资源,使用可执行文件所在目录
|
||||
"""
|
||||
if getattr(sys, 'frozen', False):
|
||||
# 打包环境
|
||||
if 'logo' in relative_path:
|
||||
# logo 文件使用打包的临时目录
|
||||
if hasattr(sys, '_MEIPASS'):
|
||||
return os.path.join(sys._MEIPASS, relative_path)
|
||||
# 其他资源使用可执行文件所在目录
|
||||
exe_dir = os.path.dirname(sys.executable)
|
||||
return os.path.join(exe_dir, relative_path)
|
||||
# 开发环境
|
||||
return os.path.join(os.path.abspath("."), relative_path)
|
||||
|
||||
class HomeInterface(QWidget):
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -71,7 +71,7 @@ class analyzing_ioc:
|
||||
@staticmethod
|
||||
def get_enabled_can_from_ioc(ioc_path):
|
||||
"""
|
||||
获取已启用的CAN列表
|
||||
获取已启用的CAN列表(不包括FDCAN)
|
||||
返回格式: ['CAN1', 'CAN2'] 等
|
||||
"""
|
||||
enabled_can = []
|
||||
@@ -84,6 +84,7 @@ class analyzing_ioc:
|
||||
key, value = line.split('=', 1)
|
||||
key = key.strip()
|
||||
value = value.strip()
|
||||
# 只匹配CAN,不包括FDCAN
|
||||
if key.startswith('Mcu.IP') and value.startswith('CAN') and not value.startswith('FDCAN'):
|
||||
can_name = value.split('.')[0] if '.' in value else value
|
||||
if can_name not in enabled_can:
|
||||
|
||||
@@ -97,44 +97,19 @@ class CodeGenerator:
|
||||
assets_dir = ""
|
||||
|
||||
if getattr(sys, 'frozen', False):
|
||||
# 打包后的环境
|
||||
print("检测到打包环境")
|
||||
|
||||
# 优先使用可执行文件所在目录(支持更新后的文件)
|
||||
# 打包后的环境 - 始终使用可执行文件所在目录
|
||||
# 这样可以使用安装目录下的文件,而不是打包进去的文件
|
||||
exe_dir = os.path.dirname(sys.executable)
|
||||
exe_assets = os.path.join(exe_dir, "assets")
|
||||
assets_dir = os.path.join(exe_dir, "assets")
|
||||
print(f"打包环境:使用可执行文件目录: {assets_dir}")
|
||||
|
||||
# 如果exe目录下不存在assets,但_MEIPASS中有,则首次复制过去
|
||||
if not os.path.exists(exe_assets) and hasattr(sys, '_MEIPASS'):
|
||||
base_path = getattr(sys, '_MEIPASS')
|
||||
meipass_assets = os.path.join(base_path, "assets")
|
||||
if os.path.exists(meipass_assets):
|
||||
try:
|
||||
import shutil
|
||||
print(f"首次运行:从 {meipass_assets} 复制到 {exe_assets}")
|
||||
shutil.copytree(meipass_assets, exe_assets)
|
||||
print("初始资源复制成功")
|
||||
except Exception as e:
|
||||
print(f"复制初始资源失败: {e}")
|
||||
|
||||
# 优先使用exe目录下的assets(这样可以读取更新后的文件)
|
||||
if os.path.exists(exe_assets):
|
||||
assets_dir = exe_assets
|
||||
print(f"使用可执行文件目录: {assets_dir}")
|
||||
# 后备方案:使用PyInstaller的临时解包目录
|
||||
elif hasattr(sys, '_MEIPASS'):
|
||||
base_path = getattr(sys, '_MEIPASS')
|
||||
assets_dir = os.path.join(base_path, "assets")
|
||||
print(f"后备:使用PyInstaller临时目录: {assets_dir}")
|
||||
# 最后尝试工作目录
|
||||
else:
|
||||
cwd_assets = os.path.join(os.getcwd(), "assets")
|
||||
if os.path.exists(cwd_assets):
|
||||
assets_dir = cwd_assets
|
||||
print(f"从工作目录找到assets: {assets_dir}")
|
||||
else:
|
||||
assets_dir = exe_assets # 即使不存在也使用exe目录,后续会创建
|
||||
print(f"使用默认路径(将创建): {assets_dir}")
|
||||
# 如果assets目录不存在,创建它
|
||||
if not os.path.exists(assets_dir):
|
||||
try:
|
||||
os.makedirs(assets_dir, exist_ok=True)
|
||||
print(f"创建assets目录: {assets_dir}")
|
||||
except Exception as e:
|
||||
print(f"创建assets目录失败: {e}")
|
||||
else:
|
||||
# 开发环境
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
Reference in New Issue
Block a user