From bebfbd716c67f88707d6b7a32a63182a44577b12 Mon Sep 17 00:00:00 2001 From: Robofish <1683502971@qq.com> Date: Tue, 5 Aug 2025 03:47:11 +0800 Subject: [PATCH] =?UTF-8?q?bsp=E5=86=99=E7=9A=84=E5=B7=AE=E4=B8=8D?= =?UTF-8?q?=E5=A4=9A=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/code_generate_interface.py | 151 +++++- app/code_page/bsp_interface.py | 453 ++++++++++++++++++ .../component_interface.py} | 0 app/code_page/device_interface.py | 0 app/code_page/module_interface.py | 0 app/tools/analyzing_ioc.py | 149 +++++- app/tools/code_generator.py | 75 +++ assets/User_code/.DS_Store | Bin 10244 -> 6148 bytes assets/User_code/bsp/buzzer_gpio.c | 32 -- assets/User_code/bsp/can.c | 10 +- assets/User_code/bsp/can.h | 3 +- assets/User_code/bsp/delay.c | 114 +---- assets/User_code/bsp/delay.h | 44 +- assets/User_code/bsp/dependencies.csv | 2 - assets/User_code/bsp/describe.csv | 4 +- assets/User_code/bsp/gpio.c | 53 ++ assets/User_code/bsp/{gpio_exti.h => gpio.h} | 24 +- assets/User_code/bsp/gpio_exti.c | 72 --- assets/User_code/bsp/i2c.c | 10 +- assets/User_code/bsp/i2c.h | 6 +- assets/User_code/bsp/led_gpio.c | 50 -- assets/User_code/bsp/led_gpio.h | 36 -- assets/User_code/bsp/mm.c | 14 + assets/User_code/bsp/{buzzer_gpio.h => mm.h} | 20 +- assets/User_code/bsp/spi.c | 14 +- assets/User_code/bsp/spi.h | 3 +- assets/User_code/bsp/uart.c | 10 +- assets/User_code/bsp/uart.h | 3 +- assets/User_code/config.csv | 4 + 29 files changed, 946 insertions(+), 410 deletions(-) create mode 100644 app/code_page/bsp_interface.py rename app/{tools/code_generate.py => code_page/component_interface.py} (100%) create mode 100644 app/code_page/device_interface.py create mode 100644 app/code_page/module_interface.py create mode 100644 app/tools/code_generator.py delete mode 100644 assets/User_code/bsp/buzzer_gpio.c delete mode 100644 assets/User_code/bsp/dependencies.csv create mode 100644 assets/User_code/bsp/gpio.c rename assets/User_code/bsp/{gpio_exti.h => gpio.h} (53%) delete mode 100644 assets/User_code/bsp/gpio_exti.c delete mode 100644 assets/User_code/bsp/led_gpio.c delete mode 100644 assets/User_code/bsp/led_gpio.h create mode 100644 assets/User_code/bsp/mm.c rename assets/User_code/bsp/{buzzer_gpio.h => mm.h} (71%) create mode 100644 assets/User_code/config.csv diff --git a/app/code_generate_interface.py b/app/code_generate_interface.py index eb754d6..9a354bd 100644 --- a/app/code_generate_interface.py +++ b/app/code_generate_interface.py @@ -1,6 +1,12 @@ -from PyQt5.QtWidgets import QWidget, QVBoxLayout +from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QSizePolicy, QTreeWidget, QTreeWidgetItem, QStackedWidget from PyQt5.QtCore import Qt -from qfluentwidgets import TitleLabel, BodyLabel +from qfluentwidgets import TitleLabel, BodyLabel, PushButton +from app.tools.analyzing_ioc import analyzing_ioc +from app.code_page.bsp_interface import bsp + +import os +import csv +import importlib class CodeGenerateInterface(QWidget): def __init__(self, project_path, parent=None): @@ -8,14 +14,137 @@ class CodeGenerateInterface(QWidget): self.setObjectName("CodeGenerateInterface") self.project_path = project_path - layout = QVBoxLayout(self) - layout.setAlignment(Qt.AlignTop) - layout.setContentsMargins(10, 10, 10, 10) + self._init_ui() - title = TitleLabel("代码生成页面") - title.setAlignment(Qt.AlignCenter) - layout.addWidget(title) + def _init_ui(self): + """初始化界面布局""" + main_layout = QVBoxLayout(self) + main_layout.setAlignment(Qt.AlignTop) + main_layout.setContentsMargins(10, 10, 10, 10) - desc = BodyLabel(f"当前工程路径: {self.project_path}") - desc.setAlignment(Qt.AlignCenter) - layout.addWidget(desc) \ No newline at end of file + top_layout = self._create_top_layout() + main_layout.addLayout(top_layout) + + # 下方主区域,左右分栏 + content_layout = QHBoxLayout() + content_layout.setContentsMargins(0, 10, 0, 0) + main_layout.addLayout(content_layout) + + # 左侧树形列表 + self.tree = QTreeWidget() + self.tree.setHeaderHidden(True) + self.tree.setMaximumWidth(250) + content_layout.addWidget(self.tree) + + # 右侧内容区 + self.stack = QStackedWidget() + content_layout.addWidget(self.stack) + + self._load_csv_and_build_tree() + self.tree.itemClicked.connect(self.on_tree_item_clicked) + + def _create_top_layout(self): + """创建顶部横向布局""" + top_layout = QHBoxLayout() + top_layout.setAlignment(Qt.AlignTop) + + # 项目名称标签 + project_name = os.path.basename(self.project_path) + name_label = BodyLabel(f"项目名称: {project_name}") + name_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) + top_layout.addWidget(name_label) + + # FreeRTOS状态标签 + freertos_label = BodyLabel(f"FreeRTOS: {self._get_freertos_status()}") + freertos_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) + top_layout.addWidget(freertos_label) + + # 生成代码按钮 + generate_btn = PushButton("Generate Code") + generate_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + generate_btn.clicked.connect(self.generate_code) + top_layout.addWidget(generate_btn, alignment=Qt.AlignRight) + + return top_layout + + def generate_code(self): + """生成代码逻辑""" + # 收集所有已加载的页面对象 + pages = [] + for i in range(self.stack.count()): + widget = self.stack.widget(i) + pages.append(widget) + bsp.generate_bsp(self.project_path, pages) + # component.generate_component(self.project_path) + # device.generate_device(self.project_path) + + + def _get_freertos_status(self): + """获取FreeRTOS状态""" + 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]) + return "开启" if analyzing_ioc.is_freertos_enabled_from_ioc(ioc_path) else "未开启" + return "未找到.ioc文件" + + def _load_csv_and_build_tree(self): + # 获取脚本目录 + script_dir = os.path.dirname(os.path.abspath(__file__)) + csv_path = os.path.join(script_dir, "../assets/User_code/config.csv") + csv_path = os.path.abspath(csv_path) + print(f"加载CSV路径: {csv_path}") + if not os.path.exists(csv_path): + print(f"配置文件未找到: {csv_path}") + return + self.tree.clear() + with open(csv_path, newline='', encoding='utf-8') as f: + reader = csv.reader(f) + for row in reader: + row = [cell.strip() for cell in row if cell.strip()] + if not row: + continue + main_title = row[0] + main_item = QTreeWidgetItem([main_title]) + for sub in row[1:]: + sub_item = QTreeWidgetItem([sub]) + main_item.addChild(sub_item) + self.tree.addTopLevelItem(main_item) + self.tree.repaint() + + def on_tree_item_clicked(self, item, column): + if item.parent(): + main_title = item.parent().text(0) + sub_title = item.text(0) + class_name = f"{main_title}_{sub_title}".replace("-", "_") + widget = self._get_or_create_page(class_name) + if widget: + self.stack.setCurrentWidget(widget) + + def _get_or_create_page(self, class_name): + for i in range(self.stack.count()): + w = self.stack.widget(i) + if w.objectName() == class_name: + return w + try: + module_name = f"app.code_page.{class_name.split('_')[0]}_interface" + module = importlib.import_module(module_name) + cls = getattr(module, class_name) + widget = cls(self.project_path) + widget.setObjectName(class_name) + self.stack.addWidget(widget) + print(f"加载页面类: {class_name} 来自模块: {module_name}") + return widget + except Exception as e: + # 自动识别通用外设页面 + from app.code_page.bsp_interface import BspSimplePeripheral + peripheral_name = class_name.split('_')[1] if '_' in class_name else class_name + # 模板文件名自动推断 + template_names = { + 'header': f"{peripheral_name.lower()}.h", + 'source': f"{peripheral_name.lower()}.c" + } + widget = BspSimplePeripheral(self.project_path, peripheral_name, template_names) + widget.setObjectName(class_name) + self.stack.addWidget(widget) + print(f"自动加载通用外设页面: {class_name}") + return widget \ No newline at end of file diff --git a/app/code_page/bsp_interface.py b/app/code_page/bsp_interface.py new file mode 100644 index 0000000..8de4dcc --- /dev/null +++ b/app/code_page/bsp_interface.py @@ -0,0 +1,453 @@ +from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLineEdit, QCheckBox, QComboBox, QTableWidget, QHeaderView, QMessageBox +from qfluentwidgets import TitleLabel, BodyLabel, PushButton +from app.tools.analyzing_ioc import analyzing_ioc +from app.tools.code_generator import CodeGenerator +import os +import csv + +class BspSimplePeripheral(QWidget): + def __init__(self, project_path, peripheral_name, template_names): + super().__init__() + self.project_path = project_path + self.peripheral_name = peripheral_name + self.template_names = template_names + # 加载描述 + describe_path = os.path.join(os.path.dirname(__file__), "../../assets/User_code/bsp/describe.csv") + self.descriptions = load_descriptions(describe_path) + self._init_ui() + self._load_config() + + def _init_ui(self): + layout = QVBoxLayout(self) + layout.addWidget(TitleLabel(f"{self.peripheral_name} 配置")) + desc = self.descriptions.get(self.peripheral_name.lower(), "") + if desc: + layout.addWidget(BodyLabel(f"功能说明:{desc}")) + self.generate_checkbox = QCheckBox(f"启用 {self.peripheral_name}") + layout.addWidget(self.generate_checkbox) + + def is_need_generate(self): + return self.generate_checkbox.isChecked() + + def _generate_bsp_code_internal(self): + if not self.is_need_generate(): + return False + template_dir = CodeGenerator.get_template_dir() + # 直接拷贝模板,无需特殊处理 + for key, filename in self.template_names.items(): + template_path = os.path.join(template_dir, filename) + template_content = CodeGenerator.load_template(template_path) + if not template_content: + return False + output_path = os.path.join(self.project_path, f"User/bsp/{filename}") + if not CodeGenerator.save_file(template_content, output_path): + return False + self._save_config() + 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[self.peripheral_name.lower()] = {'enabled': True} + 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(self.peripheral_name.lower(), {}) + if conf.get('enabled', False): + self.generate_checkbox.setChecked(True) + + +class BspPeripheralBase(QWidget): + def __init__(self, project_path, peripheral_name, template_names, enum_prefix, handle_prefix, yaml_key, get_available_func): + super().__init__() + self.project_path = project_path + self.peripheral_name = peripheral_name + self.template_names = template_names + self.enum_prefix = enum_prefix + self.handle_prefix = handle_prefix + self.yaml_key = yaml_key + self.get_available_func = get_available_func + self.available_list = [] + # 新增:加载描述 + describe_path = os.path.join(os.path.dirname(__file__), "../../assets/User_code/bsp/describe.csv") + self.descriptions = load_descriptions(describe_path) + self._init_ui() + self._load_config() + + def _init_ui(self): + layout = QVBoxLayout(self) + layout.addWidget(TitleLabel(f"{self.peripheral_name} 配置")) + desc = self.descriptions.get(self.peripheral_name.lower(), "") + if desc: + layout.addWidget(BodyLabel(f"功能说明:{desc}")) + self.generate_checkbox = QCheckBox(f"生成 {self.peripheral_name} 代码") + self.generate_checkbox = QCheckBox(f"生成 {self.peripheral_name} 代码") + self.generate_checkbox.stateChanged.connect(self._on_generate_changed) + layout.addWidget(self.generate_checkbox) + self.content_widget = QWidget() + content_layout = QVBoxLayout(self.content_widget) + self._get_available_list() + if not self.available_list: + content_layout.addWidget(BodyLabel(f"在 .ioc 文件中未找到已启用的 {self.peripheral_name}")) + else: + content_layout.addWidget(BodyLabel(f"可用的 {self.peripheral_name}: {', '.join(self.available_list)}")) + self.table = QTableWidget(0, 3) + self.table.setHorizontalHeaderLabels(["设备名称", f"{self.peripheral_name}选择", "操作"]) + self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) + content_layout.addWidget(self.table) + add_btn = PushButton(f"添加 {self.peripheral_name} 设备") + add_btn.clicked.connect(self._add_device) + content_layout.addWidget(add_btn) + layout.addWidget(self.content_widget) + self.content_widget.setEnabled(False) + + def _get_available_list(self): + self.available_list = self.get_available_func(self.project_path) + + def _on_generate_changed(self, state): + self.content_widget.setEnabled(state == 2) + + def _add_device(self): + row = self.table.rowCount() + self.table.insertRow(row) + name_edit = QLineEdit() + name_edit.setPlaceholderText(f"输入设备名称") + self.table.setCellWidget(row, 0, name_edit) + combo = QComboBox() + combo.addItems(self.available_list) + self.table.setCellWidget(row, 1, combo) + del_btn = PushButton("删除") + del_btn.clicked.connect(lambda: self._delete_device(row)) + self.table.setCellWidget(row, 2, del_btn) + + def _delete_device(self, row): + self.table.removeRow(row) + + def _collect_configs(self): + configs = [] + for row in range(self.table.rowCount()): + name_widget = self.table.cellWidget(row, 0) + sel_widget = self.table.cellWidget(row, 1) + if name_widget and sel_widget: + name = name_widget.text().strip() + sel = sel_widget.currentText() + if name and sel: + configs.append((name.upper(), sel)) + return configs + + def is_need_generate(self): + return self.generate_checkbox.isChecked() and bool(self._collect_configs()) + + def generate_bsp_code(self): + if not self.is_need_generate(): + return False + configs = self._collect_configs() + if not configs: + return False + template_dir = CodeGenerator.get_template_dir() + if not self._generate_header_file(configs, template_dir): + return False + if not self._generate_source_file(configs, template_dir): + return False + self._save_config(configs) + QMessageBox.information(self, "成功", f"{self.peripheral_name} 代码生成成功!") + return True + + def _generate_header_file(self, configs, template_dir): + 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) + ) + output_path = os.path.join(self.project_path, f"User/bsp/{self.template_names['header']}") + return CodeGenerator.save_file(content, output_path) + + def _generate_source_file(self, configs, template_dir): + 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): + if idx == 0: + get_lines.append(f" if ({self.handle_prefix}->Instance == {instance})") + else: + get_lines.append(f" else if ({self.handle_prefix}->Instance == {instance})") + get_lines.append(f" return {self.enum_prefix}_{name};") + content = CodeGenerator.replace_auto_generated( + template_content, f"AUTO GENERATED {self.enum_prefix.split('_')[1]}_GET", "\n".join(get_lines) + ) + # Handle函数 + handle_lines = [] + for name, instance in configs: + handle_lines.append(f" case {self.enum_prefix}_{name}:") + handle_lines.append(f" return &h{instance.lower()};") + 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']}") + return CodeGenerator.save_file(content, output_path) + + def _save_config(self, configs): + config_path = os.path.join(self.project_path, "User/bsp/bsp_config.yaml") + config_data = CodeGenerator.load_config(config_path) + config_data[self.yaml_key] = { + 'enabled': True, + 'devices': [{'name': name, 'instance': instance} for name, instance in configs] + } + 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(self.yaml_key, {}) + if conf.get('enabled', False): + self.generate_checkbox.setChecked(True) + devices = conf.get('devices', []) + for device in devices: + if self.available_list: + self._add_device() + row = self.table.rowCount() - 1 + name_widget = self.table.cellWidget(row, 0) + sel_widget = self.table.cellWidget(row, 1) + if name_widget: + name_widget.setText(device.get('name', '')) + if sel_widget: + instance = device.get('instance', '') + if instance in self.available_list: + sel_widget.setCurrentText(instance) + + def _generate_bsp_code_internal(self): + if not self.is_need_generate(): + return False + configs = self._collect_configs() + if not configs: + return False + template_dir = CodeGenerator.get_template_dir() + if not self._generate_header_file(configs, template_dir): + return False + if not self._generate_source_file(configs, template_dir): + return False + self._save_config(configs) + return True + +def load_descriptions(csv_path): + descriptions = {} + if os.path.exists(csv_path): + with open(csv_path, encoding='utf-8') as f: + reader = csv.reader(f) + for row in reader: + if len(row) >= 2: + key, desc = row[0].strip(), row[1].strip() + descriptions[key.lower()] = desc + return descriptions + +# 各外设的可用列表获取函数 +def get_available_i2c(project_path): + ioc_files = [f for f in os.listdir(project_path) if f.endswith('.ioc')] + if ioc_files: + ioc_path = os.path.join(project_path, ioc_files[0]) + return analyzing_ioc.get_enabled_i2c_from_ioc(ioc_path) + return [] + +def get_available_can(project_path): + ioc_files = [f for f in os.listdir(project_path) if f.endswith('.ioc')] + if ioc_files: + ioc_path = os.path.join(project_path, ioc_files[0]) + return analyzing_ioc.get_enabled_can_from_ioc(ioc_path) + return [] + +def get_available_spi(project_path): + ioc_files = [f for f in os.listdir(project_path) if f.endswith('.ioc')] + if ioc_files: + ioc_path = os.path.join(project_path, ioc_files[0]) + return analyzing_ioc.get_enabled_spi_from_ioc(ioc_path) + return [] + +def get_available_uart(project_path): + ioc_files = [f for f in os.listdir(project_path) if f.endswith('.ioc')] + if ioc_files: + ioc_path = os.path.join(project_path, ioc_files[0]) + return analyzing_ioc.get_enabled_uart_from_ioc(ioc_path) + return [] + +def get_available_gpio(project_path): + ioc_files = [f for f in os.listdir(project_path) if f.endswith('.ioc')] + if ioc_files: + ioc_path = os.path.join(project_path, ioc_files[0]) + return analyzing_ioc.get_enabled_gpio_from_ioc(ioc_path) + return [] + +# 具体外设类 +class bsp_i2c(BspPeripheralBase): + def __init__(self, project_path): + super().__init__( + project_path, + "I2C", + {'header': 'i2c.h', 'source': 'i2c.c'}, + "BSP_I2C", + "hi2c", + "i2c", + get_available_i2c + ) + +class bsp_can(BspPeripheralBase): + def __init__(self, project_path): + super().__init__( + project_path, + "CAN", + {'header': 'can.h', 'source': 'can.c'}, + "BSP_CAN", + "hcan", + "can", + get_available_can + ) + +class bsp_spi(BspPeripheralBase): + def __init__(self, project_path): + super().__init__( + project_path, + "SPI", + {'header': 'spi.h', 'source': 'spi.c'}, + "BSP_SPI", + "hspi", + "spi", + get_available_spi + ) + +class bsp_uart(BspPeripheralBase): + def __init__(self, project_path): + super().__init__( + project_path, + "UART", + {'header': 'uart.h', 'source': 'uart.c'}, + "BSP_UART", + "huart", + "uart", + get_available_uart + ) + +class bsp_gpio(QWidget): + def __init__(self, project_path): + super().__init__() + self.project_path = project_path + self.available_list = get_available_gpio(project_path) + # 新增:加载描述 + describe_path = os.path.join(os.path.dirname(__file__), "../../assets/User_code/bsp/describe.csv") + self.descriptions = load_descriptions(describe_path) + self._init_ui() + + def _init_ui(self): + layout = QVBoxLayout(self) + layout.addWidget(TitleLabel("GPIO 配置")) + # 新增:显示描述 + desc = self.descriptions.get("gpio", "") + if desc: + layout.addWidget(BodyLabel(f"功能说明:{desc}")) + self.generate_checkbox = QCheckBox("生成 GPIO 代码") + layout.addWidget(self.generate_checkbox) + if not self.available_list: + layout.addWidget(BodyLabel("在 .ioc 文件中未找到可用的 GPIO")) + else: + self.table = QTableWidget(len(self.available_list), 1) + self.table.setHorizontalHeaderLabels(["Label"]) + self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) + for row, item in enumerate(self.available_list): + from PyQt5.QtWidgets import QTableWidgetItem + self.table.setItem(row, 0, QTableWidgetItem(item['label'])) + self.table.setEditTriggers(QTableWidget.NoEditTriggers) + layout.addWidget(self.table) + + def is_need_generate(self): + return self.generate_checkbox.isChecked() and bool(self.available_list) + + def _generate_bsp_code_internal(self): + if not self.is_need_generate(): + return False + template_dir = CodeGenerator.get_template_dir() + if not self._generate_header_file(template_dir): + return False + if not self._generate_source_file(template_dir): + return False + self._save_config() + return True + + def _generate_header_file(self, template_dir): + template_path = os.path.join(template_dir, "gpio.h") + template_content = CodeGenerator.load_template(template_path) + if not template_content: + return False + # 如有需要可在此处插入自动生成内容 + output_path = os.path.join(self.project_path, "User/bsp/gpio.h") + return CodeGenerator.save_file(template_content, output_path) + + def _generate_source_file(self, template_dir): + template_path = os.path.join(template_dir, "gpio.c") + template_content = CodeGenerator.load_template(template_path) + if not template_content: + return False + # 生成 IRQ 使能/禁用代码 + enable_lines = [] + disable_lines = [] + for item in self.available_list: + label = item['label'] + enable_lines.append(f" case {label}_Pin:") + enable_lines.append(f" HAL_NVIC_EnableIRQ({label}_EXTI_IRQn);") + enable_lines.append(f" break;") + disable_lines.append(f" case {label}_Pin:") + disable_lines.append(f" HAL_NVIC_DisableIRQ({label}_EXTI_IRQn);") + disable_lines.append(f" break;") + content = CodeGenerator.replace_auto_generated( + template_content, "AUTO GENERATED BSP_GPIO_ENABLE_IRQ", "\n".join(enable_lines) + ) + content = CodeGenerator.replace_auto_generated( + content, "AUTO GENERATED BSP_GPIO_DISABLE_IRQ", "\n".join(disable_lines) + ) + output_path = os.path.join(self.project_path, "User/bsp/gpio.c") + return CodeGenerator.save_file(content, output_path) + + 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['gpio'] = { + 'enabled': True, + 'labels': [item['label'] for item in self.available_list] + } + CodeGenerator.save_config(config_data, config_path) + + +class bsp(QWidget): + def __init__(self, project_path): + super().__init__() + self.project_path = project_path + + @staticmethod + def generate_bsp(project_path, pages): + total = 0 + success_count = 0 + fail_count = 0 + fail_list = [] + for page in pages: + name = page.objectName() if hasattr(page, "objectName") else str(page) + if hasattr(page, "is_need_generate") and page.is_need_generate(): + total += 1 + try: + result = page._generate_bsp_code_internal() + if result: + success_count += 1 + else: + fail_count += 1 + fail_list.append(name) + except Exception as e: + fail_count += 1 + fail_list.append(f"{name} (异常: {e})") + msg = f"总共尝试生成 {total} 项,成功 {success_count} 项,失败 {fail_count} 项。" + if fail_list: + msg += "\n失败项:\n" + "\n".join(fail_list) + QMessageBox.information(None, "代码生成结果", msg) \ No newline at end of file diff --git a/app/tools/code_generate.py b/app/code_page/component_interface.py similarity index 100% rename from app/tools/code_generate.py rename to app/code_page/component_interface.py diff --git a/app/code_page/device_interface.py b/app/code_page/device_interface.py new file mode 100644 index 0000000..e69de29 diff --git a/app/code_page/module_interface.py b/app/code_page/module_interface.py new file mode 100644 index 0000000..e69de29 diff --git a/app/tools/analyzing_ioc.py b/app/tools/analyzing_ioc.py index e629679..c92517a 100644 --- a/app/tools/analyzing_ioc.py +++ b/app/tools/analyzing_ioc.py @@ -1,7 +1,146 @@ - - class analyzing_ioc: - def __init__(self, ioc_data): # 初始化方法,接收IOC数据 - self.ioc_data = ioc_data # 存储IOC数据 + @staticmethod + def is_freertos_enabled_from_ioc(ioc_path): + """ + 检查指定 .ioc 文件是否开启了 FreeRTOS + """ + config = {} + with open(ioc_path, encoding='utf-8') as f: + for line in f: + line = line.strip() + if not line or line.startswith('#'): + continue + if '=' in line: + key, value = line.split('=', 1) + config[key.strip()] = value.strip() + ip_keys = [k for k in config if k.startswith('Mcu.IP')] + for k in ip_keys: + if config[k] == 'FREERTOS': + return True + for k in config: + if k.startswith('FREERTOS.'): + return True + return False - \ No newline at end of file + @staticmethod + def get_enabled_i2c_from_ioc(ioc_path): + """ + 从.ioc文件中获取已启用的I2C列表 + 返回格式: ['I2C1', 'I2C3'] 等 + """ + enabled_i2c = [] + 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() + # 检查是否启用了I2C + if key.startswith('Mcu.IP') and value.startswith('I2C'): + # 提取I2C编号,如I2C1, I2C2等 + i2c_name = value.split('.')[0] if '.' in value else value + if i2c_name not in enabled_i2c: + enabled_i2c.append(i2c_name) + return sorted(enabled_i2c) + + @staticmethod + def get_enabled_spi_from_ioc(ioc_path): + """ + 获取已启用的SPI列表 + 返回格式: ['SPI1', 'SPI2'] 等 + """ + enabled_spi = [] + 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() + if key.startswith('Mcu.IP') and value.startswith('SPI'): + spi_name = value.split('.')[0] if '.' in value else value + if spi_name not in enabled_spi: + enabled_spi.append(spi_name) + return sorted(enabled_spi) + + @staticmethod + def get_enabled_can_from_ioc(ioc_path): + """ + 获取已启用的CAN列表 + 返回格式: ['CAN1', 'CAN2'] 等 + """ + enabled_can = [] + 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() + if key.startswith('Mcu.IP') and value.startswith('CAN'): + can_name = value.split('.')[0] if '.' in value else value + if can_name not in enabled_can: + enabled_can.append(can_name) + return sorted(enabled_can) + + @staticmethod + def get_enabled_uart_from_ioc(ioc_path): + """ + 获取已启用的UART/USART列表 + 返回格式: ['USART1', 'USART2', 'UART4'] 等 + """ + enabled_uart = [] + 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() + # 检查是否启用了UART或USART + if key.startswith('Mcu.IP') and (value.startswith('USART') or value.startswith('UART')): + uart_name = value.split('.')[0] if '.' in value else value + if uart_name not in enabled_uart: + enabled_uart.append(uart_name) + return sorted(enabled_uart) + + @staticmethod + def get_enabled_gpio_from_ioc(ioc_path): + """ + 获取所有带 EXTI 且有 Label 的 GPIO,返回 [{'pin': 'PC4', 'label': 'ACCL_INT'}, ...] + """ + gpio_list = [] + gpio_params = {} + 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() + if '.GPIOParameters' in key: + gpio_params[key.split('.')[0]] = value + elif '.GPIO_Label' in key: + pin = key.split('.')[0] + gpio_params[f"{pin}_label"] = value + elif '.GPIO_ModeDefaultEXTI' in key: + pin = key.split('.')[0] + gpio_params[f"{pin}_exti"] = value + for pin in gpio_params: + if not pin.endswith('_label') and not pin.endswith('_exti'): + label = gpio_params.get(f"{pin}_label", None) + exti = gpio_params.get(f"{pin}_exti", None) + if label and exti: + gpio_list.append({'pin': pin, 'label': label}) + return gpio_list \ No newline at end of file diff --git a/app/tools/code_generator.py b/app/tools/code_generator.py new file mode 100644 index 0000000..8b41d68 --- /dev/null +++ b/app/tools/code_generator.py @@ -0,0 +1,75 @@ +import os +import yaml +import shutil +from typing import Dict, List, Tuple + +class CodeGenerator: + """通用代码生成器""" + + @staticmethod + def load_template(template_path: str) -> str: + """加载代码模板""" + try: + with open(template_path, 'r', encoding='utf-8') as f: + return f.read() + except Exception as e: + print(f"加载模板失败: {template_path}, 错误: {e}") + return "" + + @staticmethod + def replace_auto_generated(content: str, marker: str, replacement: str) -> str: + """替换自动生成的代码标记""" + marker_line = f"/* {marker} */" + if marker_line in content: + return content.replace(marker_line, replacement) + return content + + @staticmethod + def save_file(content: str, file_path: str) -> bool: + """保存文件""" + try: + os.makedirs(os.path.dirname(file_path), exist_ok=True) + with open(file_path, 'w', encoding='utf-8') as f: + f.write(content) + return True + except Exception as e: + print(f"保存文件失败: {file_path}, 错误: {e}") + return False + + @staticmethod + def load_config(config_path: str) -> Dict: + """加载配置文件""" + if os.path.exists(config_path): + try: + with open(config_path, 'r', encoding='utf-8') as f: + return yaml.safe_load(f) or {} + except Exception as e: + print(f"加载配置失败: {config_path}, 错误: {e}") + return {} + + @staticmethod + def save_config(config: Dict, config_path: str) -> bool: + """保存配置文件""" + try: + os.makedirs(os.path.dirname(config_path), exist_ok=True) + with open(config_path, 'w', encoding='utf-8') as f: + yaml.safe_dump(config, f, allow_unicode=True, default_flow_style=False) + return True + except Exception as e: + print(f"保存配置失败: {config_path}, 错误: {e}") + return False + + @staticmethod + def get_template_dir(): + """获取模板文件目录""" + # 从当前文件向上找到 MRobot 目录,然后定位到模板目录 + current_dir = os.path.dirname(os.path.abspath(__file__)) + # 向上找到 MRobot 根目录 + while os.path.basename(current_dir) != 'MRobot' and current_dir != '/': + current_dir = os.path.dirname(current_dir) + + if os.path.basename(current_dir) == 'MRobot': + return os.path.join(current_dir, "assets/User_code/bsp") + else: + # 如果找不到,使用相对路径作为备选 + return os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "assets/User_code/bsp") \ No newline at end of file diff --git a/assets/User_code/.DS_Store b/assets/User_code/.DS_Store index 3e04fe280a207ca05877c8c00fe34f3cde1f1e83..038a9973cdfc977f2bf0be31ee0780e9de8af44d 100644 GIT binary patch delta 107 zcmZn(XfcprU|?W$DortDU=RQ@Ie-{MGjdEU6q~50$jCM^U^gS%WFvw0$w|UGlh=uH zPVN^o*;vBOwwRrRLy#G$76=5mfrKka+s4B0%#-<5EGPS@NV9?rXV@IiGlv-fI^7hV literal 10244 zcmeHMPjAyO6n}2Zno@=;0fGxsG%g&f(rq1M;!?WxFbO!U0}g;n)08b*np91@GF6kx zaqu1Z3LN2UaDeZ^34V6Gk+>O1Ft#21B>N@y`}xn$&o8x0M65Qn=ZQ=rGLX0~Ttb#0 zyq>2iNy(BqXa+p_ZOip7ycMQwb%AC;GoTsJ3}^;41LuPQe6zV2`B3XzGoTsJ3>-1Q zs??KEqXfc2D0B#A@`%CY*@1;{)K{hb zB-A0CnCKbp$ex)zp)h&$V5Tr9Rt>ezH3OP~X$Iy{l%{zqQG4Bup5IenQB(RMM8MKy zQ9!-86+KX_a?~cDy3|ANQ3q+DAU-OH8M0xwOAe5oxGlS>*yiaqxik#hg?2FR9_{@B zm4;oHwiK)PO54)P8U;Ohi}Bg&xlS-Bm%p)8I&)zrYh;bQ@v^b)j~av4U>MX|{pb8` z)AwEL@VR9@bvmPF;p(dI4O))Z=?j2kcVP13nd901sOAqnI}q4LSYhOhT(fXvJYHH^ zD4L6l_x6kCcx9nnG%I&2`};ZL+O0eHH<~+c*Yn?D(IFoQ)l{T??b* zb+Tx;(f3^6+d>I%AWIKvomQz%kEua*g{1GWh&q7*B0E^9ZE9j69J1o}gvDi-BTh4A zf7bL?D$7N4VY&Q|^iIu7VRZ&P`EcwZSW=x@b-au8h&I6ICJ;XClU$mw!-oj3d9>dL zW*{-mL>I^QiLFN1laGz;16cwlpdh}245N!-a$!G%GJ@{8b)46UtO}}eDWO;Te&pm)K`P82y{^0pFT9f;)U{ff5jrW%zXJ--PSqab-z- z2YwT?4loJGv7ZF~$w-)3l+lE0Wx=vdYJ53(>(&w-9h)i^2KaciXa+O`ngPv#W -#include "bsp/bsp.h" -#include "bsp/buzzer_gpio.h" -/* Private define ----------------------------------------------------------- */ -#define BSP_BUZZER_GPIO GPIOA -#define BSP_BUZZER_PIN GPIO_PIN_1 -/* Private macro ------------------------------------------------------------ */ -/* Private typedef ---------------------------------------------------------- */ -/* Private variables -------------------------------------------------------- */ -/* Private function --------------------------------------------------------- */ -/* Exported functions ------------------------------------------------------- */ -int8_t BSP_Buzzer_Set(BSP_Buzzer_Status_t s) -{ - switch (s) - { - case BSP_BUZZER_ON: - HAL_GPIO_WritePin(BSP_BUZZER_GPIO, BSP_BUZZER_PIN, GPIO_PIN_SET); // 打开蜂鸣器 - break; - case BSP_BUZZER_OFF: - HAL_GPIO_WritePin(BSP_BUZZER_GPIO, BSP_BUZZER_PIN, GPIO_PIN_RESET); // 关闭蜂鸣器 - break; - case BSP_BUZZER_TAGGLE: - HAL_GPIO_TogglePin(BSP_BUZZER_GPIO, BSP_BUZZER_PIN); // 切换蜂鸣器状态 - break; - default: - return BSP_ERR; - } - return BSP_OK; -} \ No newline at end of file diff --git a/assets/User_code/bsp/can.c b/assets/User_code/bsp/can.c index 20a9c66..f887116 100644 --- a/assets/User_code/bsp/can.c +++ b/assets/User_code/bsp/can.c @@ -9,10 +9,7 @@ static void (*CAN_Callback[BSP_CAN_NUM][BSP_CAN_CB_NUM])(void); /* Private function -------------------------------------------------------- */ static BSP_CAN_t CAN_Get(CAN_HandleTypeDef *hcan) { - if (hcan->Instance == CAN2) - return BSP_CAN_2; - else if (hcan->Instance == CAN1) - return BSP_CAN_1; +/* AUTO GENERATED CAN_GET */ else return BSP_CAN_ERR; } @@ -124,10 +121,7 @@ void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) { /* Exported functions ------------------------------------------------------- */ CAN_HandleTypeDef *BSP_CAN_GetHandle(BSP_CAN_t can) { switch (can) { - case BSP_CAN_2: - return &hcan2; - case BSP_CAN_1: - return &hcan1; +/* AUTO GENERATED BSP_CAN_GET_HANDLE */ default: return NULL; } diff --git a/assets/User_code/bsp/can.h b/assets/User_code/bsp/can.h index 47bb9a2..4cfe168 100644 --- a/assets/User_code/bsp/can.h +++ b/assets/User_code/bsp/can.h @@ -13,8 +13,7 @@ extern "C" { /* Exported macro ----------------------------------------------------------- */ /* Exported types ----------------------------------------------------------- */ typedef enum { - BSP_CAN_1, - BSP_CAN_2, +/* AUTO GENERATED BSP_CAN_NAME */ BSP_CAN_NUM, BSP_CAN_ERR, } BSP_CAN_t; diff --git a/assets/User_code/bsp/delay.c b/assets/User_code/bsp/delay.c index d906c4a..d63fb61 100644 --- a/assets/User_code/bsp/delay.c +++ b/assets/User_code/bsp/delay.c @@ -1,118 +1,34 @@ -#include "bsp_delay.h" +/* Includes ----------------------------------------------------------------- */ +#include "bsp/delay.h" -#include "cmsis_os.h" -#include "main.h" +#include +#include /* Private define ----------------------------------------------------------- */ /* Private macro ------------------------------------------------------------ */ /* Private typedef ---------------------------------------------------------- */ /* Private variables -------------------------------------------------------- */ -static uint8_t fac_us = 0; -static uint32_t fac_ms = 0; /* Private function -------------------------------------------------------- */ -static void delay_ticks(uint32_t ticks) -{ - uint32_t told = SysTick->VAL; - uint32_t tnow = 0; - uint32_t tcnt = 0; - uint32_t reload = SysTick->LOAD; - while (1) - { - tnow = SysTick->VAL; - if (tnow != told) - { - if (tnow < told) - { - tcnt += told - tnow; - } - else - { - tcnt += reload - tnow + told; - } - told = tnow; - if (tcnt >= ticks) - { - break; - } - } - } -} /* Exported functions ------------------------------------------------------- */ +int8_t BSP_Delay(uint32_t ms) { + uint32_t tick_period = 1000u / osKernelGetTickFreq(); + uint32_t ticks = ms / tick_period; -/** - * @brief 毫秒延时函数 - * @param ms - * @return - */ -int8_t BSP_Delay(uint32_t ms) -{ - uint32_t tick_period = 1000u / osKernelGetTickFreq(); - uint32_t ticks = ms / tick_period; - - switch (osKernelGetState()) - { + switch (osKernelGetState()) { case osKernelError: case osKernelReserved: case osKernelLocked: case osKernelSuspended: - return BSP_ERR; + return BSP_ERR; case osKernelRunning: - osDelay(ticks ? ticks : 1); - break; + osDelay(ticks ? ticks : 1); + break; case osKernelInactive: case osKernelReady: - HAL_Delay(ms); - break; - } - return BSP_OK; -} - -/** - * @brief 延时初始化 - * @param - * @return - */ -int8_t BSP_Delay_Init(void) -{ - if (SystemCoreClock == 0) - { - return BSP_ERR; - } - fac_us = SystemCoreClock / 1000000; - fac_ms = SystemCoreClock / 1000; - return BSP_OK; -} - -/** - * @brief 微秒延时,注意:此函数会阻塞当前线程,直到延时结束,并且会被中断打断 - * @param us - * @return - */ -int8_t BSP_Delay_us(uint32_t us) -{ - if (fac_us == 0) - { - return BSP_ERR; - } - uint32_t ticks = us * fac_us; - delay_ticks(ticks); - return BSP_OK; -} - -/** - * @brief 毫秒延时,注意:此函数会阻塞当前线程,直到延时结束,并且会被中断打断 - * @param ms - * @return - */ -int8_t BSP_Delay_ms(uint32_t ms) -{ - if (fac_ms == 0) - { - return BSP_ERR; - } - uint32_t ticks = ms * fac_ms; - delay_ticks(ticks); - return BSP_OK; + HAL_Delay(ms); + break; + } + return BSP_OK; } diff --git a/assets/User_code/bsp/delay.h b/assets/User_code/bsp/delay.h index 1a95039..82e730f 100644 --- a/assets/User_code/bsp/delay.h +++ b/assets/User_code/bsp/delay.h @@ -1,34 +1,20 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + /* Includes ----------------------------------------------------------------- */ -#include "bsp\delay.h" +#include -#include -#include +#include "bsp/bsp.h" -/* Private define ----------------------------------------------------------- */ -/* Private macro ------------------------------------------------------------ */ -/* Private typedef ---------------------------------------------------------- */ -/* Private variables -------------------------------------------------------- */ -/* Private function -------------------------------------------------------- */ -/* Exported functions ------------------------------------------------------- */ -int8_t BSP_Delay(uint32_t ms) { - uint32_t tick_period = 1000u / osKernelGetTickFreq(); - uint32_t ticks = ms / tick_period; +/* Exported constants ------------------------------------------------------- */ +/* Exported macro ----------------------------------------------------------- */ +/* Exported types ----------------------------------------------------------- */ +/* Exported functions prototypes -------------------------------------------- */ +int8_t BSP_Delay(uint32_t ms); - switch (osKernelGetState()) { - case osKernelError: - case osKernelReserved: - case osKernelLocked: - case osKernelSuspended: - return BSP_ERR; - - case osKernelRunning: - osDelay(ticks ? ticks : 1); - break; - - case osKernelInactive: - case osKernelReady: - HAL_Delay(ms); - break; - } - return BSP_OK; +#ifdef __cplusplus } +#endif diff --git a/assets/User_code/bsp/dependencies.csv b/assets/User_code/bsp/dependencies.csv deleted file mode 100644 index 2f81068..0000000 --- a/assets/User_code/bsp/dependencies.csv +++ /dev/null @@ -1,2 +0,0 @@ -i2c,I2C -uart,USART,UART \ No newline at end of file diff --git a/assets/User_code/bsp/describe.csv b/assets/User_code/bsp/describe.csv index 2788534..b54ab16 100644 --- a/assets/User_code/bsp/describe.csv +++ b/assets/User_code/bsp/describe.csv @@ -1,3 +1,5 @@ uart,要求开启dma和中断 can,要求开启can的中断 -delay,暂时只有delay_ms函数 \ No newline at end of file +gpio,要求设置label开启中断 +spi,要求开启spi中断 +i2c,要求开始spi中断 \ No newline at end of file diff --git a/assets/User_code/bsp/gpio.c b/assets/User_code/bsp/gpio.c new file mode 100644 index 0000000..19fd446 --- /dev/null +++ b/assets/User_code/bsp/gpio.c @@ -0,0 +1,53 @@ +/* Includes ----------------------------------------------------------------- */ +#include "bsp/gpio.h" + +#include +#include + +/* Private define ----------------------------------------------------------- */ +/* Private macro ------------------------------------------------------------ */ +/* Private typedef ---------------------------------------------------------- */ +/* Private variables -------------------------------------------------------- */ +static void (*GPIO_Callback[16])(void); + +/* Private function -------------------------------------------------------- */ +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { + for (uint8_t i = 0; i < 16; i++) { + if (GPIO_Pin & (1 << i)) { + if (GPIO_Callback[i]) { + GPIO_Callback[i](); + } + } + } +} + +/* Exported functions ------------------------------------------------------- */ +int8_t BSP_GPIO_RegisterCallback(uint16_t pin, void (*callback)(void)) { + if (callback == NULL) return BSP_ERR_NULL; + + for (uint8_t i = 0; i < 16; i++) { + if (pin & (1 << i)) { + GPIO_Callback[i] = callback; + break; + } + } + return BSP_OK; +} + +int8_t BSP_GPIO_EnableIRQ(uint16_t pin) { + switch (pin) { + /* AUTO GENERATED BSP_GPIO_ENABLE_IRQ */ + default: + return BSP_ERR; + } + return BSP_OK; +} + +int8_t BSP_GPIO_DisableIRQ(uint16_t pin) { + switch (pin) { + /* AUTO GENERATED BSP_GPIO_DISABLE_IRQ */ + default: + return BSP_ERR; + } + return BSP_OK; +} \ No newline at end of file diff --git a/assets/User_code/bsp/gpio_exti.h b/assets/User_code/bsp/gpio.h similarity index 53% rename from assets/User_code/bsp/gpio_exti.h rename to assets/User_code/bsp/gpio.h index 03f431b..d2eeae8 100644 --- a/assets/User_code/bsp/gpio_exti.h +++ b/assets/User_code/bsp/gpio.h @@ -12,26 +12,12 @@ extern "C" { /* Exported constants ------------------------------------------------------- */ /* Exported macro ----------------------------------------------------------- */ /* Exported types ----------------------------------------------------------- */ - -/* GPIO设备枚举,与设备对应 */ -typedef enum { - BSP_GPIO_USER_KEY, - /* BSP_GPIO_XXX, */ - BSP_GPIO_NUM, - BSP_GPIO_ERR, -} BSP_GPIO_t; - -/* GPIO支持的中断回调函数类型 */ -typedef enum { - BSP_GPIO_EXTI_CB, - BSP_GPIO_CB_NUM, -} BSP_GPIO_Callback_t; - /* Exported functions prototypes -------------------------------------------- */ -int8_t BSP_GPIO_RegisterCallback(BSP_GPIO_t gpio, BSP_GPIO_Callback_t type, void (*callback)(void)); -int8_t BSP_GPIO_EnableIRQ(BSP_GPIO_t gpio); -int8_t BSP_GPIO_DisableIRQ(BSP_GPIO_t gpio); +int8_t BSP_GPIO_RegisterCallback(uint16_t pin, void (*callback)(void)); + +int8_t BSP_GPIO_EnableIRQ(uint16_t pin); +int8_t BSP_GPIO_DisableIRQ(uint16_t pin); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/assets/User_code/bsp/gpio_exti.c b/assets/User_code/bsp/gpio_exti.c deleted file mode 100644 index d260fe1..0000000 --- a/assets/User_code/bsp/gpio_exti.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Includes ----------------------------------------------------------------- */ -#include "bsp\gpio.h" - -#include -#include - -/* Private define ----------------------------------------------------------- */ -/* Private macro ------------------------------------------------------------ */ -/* Private typedef ---------------------------------------------------------- */ -/* Private variables -------------------------------------------------------- */ -static void (*GPIO_Callback[BSP_GPIO_NUM][BSP_GPIO_CB_NUM])(void); - -/* Private function -------------------------------------------------------- */ -static BSP_GPIO_t GPIO_Get(uint16_t pin) { - switch (pin) { - case USER_KEY_Pin: - return BSP_GPIO_USER_KEY; - /* case XXX_Pin: - return BSP_GPIO_XXX; */ - default: - return BSP_GPIO_ERR; - } -} - -void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { - BSP_GPIO_t gpio = GPIO_Get(GPIO_Pin); - if (gpio != BSP_GPIO_ERR) { - if (GPIO_Callback[gpio][BSP_GPIO_EXTI_CB]) { - GPIO_Callback[gpio][BSP_GPIO_EXTI_CB](); - } - } -} - -/* Exported functions ------------------------------------------------------- */ -int8_t BSP_GPIO_RegisterCallback(BSP_GPIO_t gpio, BSP_GPIO_Callback_t type, void (*callback)(void)) { - if (callback == NULL || gpio >= BSP_GPIO_NUM || type >= BSP_GPIO_CB_NUM) return BSP_ERR_NULL; - - GPIO_Callback[gpio][type] = callback; - return BSP_OK; -} - -int8_t BSP_GPIO_EnableIRQ(BSP_GPIO_t gpio) { - switch (gpio) { - case BSP_GPIO_USER_KEY: - HAL_NVIC_EnableIRQ(USER_KEY_EXTI_IRQn); - break; - - /* case BSP_GPIO_XXX: - HAL_NVIC_EnableIRQ(XXX_IRQn); - break; */ - - default: - return BSP_ERR; - } - return BSP_OK; -} - -int8_t BSP_GPIO_DisableIRQ(BSP_GPIO_t gpio) { - switch (gpio) { - case BSP_GPIO_USER_KEY: - HAL_NVIC_DisableIRQ(USER_KEY_EXTI_IRQn); - break; - - /* case BSP_GPIO_XXX: - HAL_NVIC_DisableIRQ(XXX_IRQn); - break; */ - - default: - return BSP_ERR; - } - return BSP_OK; -} \ No newline at end of file diff --git a/assets/User_code/bsp/i2c.c b/assets/User_code/bsp/i2c.c index 6feb849..de66db3 100644 --- a/assets/User_code/bsp/i2c.c +++ b/assets/User_code/bsp/i2c.c @@ -9,10 +9,7 @@ static void (*I2C_Callback[BSP_I2C_NUM][BSP_I2C_CB_NUM])(void); /* Private function -------------------------------------------------------- */ static BSP_I2C_t I2C_Get(I2C_HandleTypeDef *hi2c) { - if (hi2c->Instance == I2C1) - return BSP_I2C_EXAMPLE; - // else if (hi2c->Instance == I2CX) - // return BSP_I2C_XXX; +/* AUTO GENERATED I2C_GET */ else return BSP_I2C_ERR; } @@ -92,10 +89,7 @@ void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c) { /* Exported functions ------------------------------------------------------- */ I2C_HandleTypeDef *BSP_I2C_GetHandle(BSP_I2C_t i2c) { switch (i2c) { - case BSP_I2C_EXAMPLE: - return &hi2c1; - // case BSP_I2C_XXX: - // return &hi2cX; +/* AUTO GENERATED BSP_I2C_GET_HANDLE */ default: return NULL; } diff --git a/assets/User_code/bsp/i2c.h b/assets/User_code/bsp/i2c.h index 9a34a37..c88fa87 100644 --- a/assets/User_code/bsp/i2c.h +++ b/assets/User_code/bsp/i2c.h @@ -17,8 +17,10 @@ extern "C" { /* I2C实体枚举,与设备对应 */ typedef enum { - BSP_I2C_EXAMPLE, - /* BSP_I2C_XXX,*/ +/* AUTO GENERATED BSP_I2C_NAME */ + /* USER BSP_I2C END*/ + /* USER_I2C_XXX */ + /* USER BSP_I2C END */ BSP_I2C_NUM, BSP_I2C_ERR, } BSP_I2C_t; diff --git a/assets/User_code/bsp/led_gpio.c b/assets/User_code/bsp/led_gpio.c deleted file mode 100644 index c34b179..0000000 --- a/assets/User_code/bsp/led_gpio.c +++ /dev/null @@ -1,50 +0,0 @@ -/* Includes ----------------------------------------------------------------- */ -#include "bsp/led_gpio.h" -#include "bsp/bsp.h" -#include - -/* Private define ----------------------------------------------------------- */ -/* Private macro ------------------------------------------------------------ */ -/* Private typedef ---------------------------------------------------------- */ - -/* Private variables -------------------------------------------------------- */ -static uint32_t led_stats; // 使用位掩码记录每个通道的状态,最多支持32LED - -// 定义 LED 引脚和端口映射表:需要根据自己的修改,添加,或删减。 -static const BSP_LED_Config_t LED_CONFIGS[] = { - {GPIOA, GPIO_PIN_2}, // BSP_LED_1 - {GPIOA, GPIO_PIN_3}, // BSP_LED_2 - {GPIOA, GPIO_PIN_4}, // BSP_LED_3 -}; - -#define LED_CHANNEL_COUNT (sizeof(LED_CONFIGS) / sizeof(LED_CONFIGS[0])) // 通道数量 - -/* Private function --------------------------------------------------------- */ -/* Exported functions ------------------------------------------------------- */ -int8_t BSP_LED_Set(BSP_LED_Channel_t ch, BSP_LED_Status_t s) -{ - if (ch < LED_CHANNEL_COUNT) - { - GPIO_TypeDef *port = LED_CONFIGS[ch].port; - uint16_t pin = LED_CONFIGS[ch].pin; - switch (s) - { - case BSP_LED_ON: - led_stats |= (1 << ch); - HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET); // 点亮LED - break; - case BSP_LED_OFF: - led_stats &= ~(1 << ch); - HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET); // 熄灭LED - break; - case BSP_LED_TAGGLE: - led_stats ^= (1 << ch); - HAL_GPIO_TogglePin(port, pin); // 切换LED状态 - break; - default: - return BSP_ERR; - } - return BSP_OK; - } - return BSP_ERR; -} \ No newline at end of file diff --git a/assets/User_code/bsp/led_gpio.h b/assets/User_code/bsp/led_gpio.h deleted file mode 100644 index 2d413b9..0000000 --- a/assets/User_code/bsp/led_gpio.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -/* Includes ----------------------------------------------------------------- */ -#include -#include "gpio.h" -/* Exported constants ------------------------------------------------------- */ -/* Exported macro ----------------------------------------------------------- */ -/* Exported types ----------------------------------------------------------- */ - -/* LED灯状态,设置用 */ -typedef enum -{ - BSP_LED_ON, - BSP_LED_OFF, - BSP_LED_TAGGLE, -} BSP_LED_Status_t; - -/* LED通道 */ -typedef enum -{ - BSP_LED_1, - BSP_LED_2, - BSP_LED_3, - /*BSP_LED_XXX*/ -} BSP_LED_Channel_t; - -/* LED GPIO 配置 */ -typedef struct -{ - GPIO_TypeDef *port; // GPIO 端口 (如 GPIOA, GPIOB) - uint16_t pin; // GPIO 引脚 -} BSP_LED_Config_t; - -/* Exported functions prototypes -------------------------------------------- */ - -int8_t BSP_LED_Set(BSP_LED_Channel_t ch, BSP_LED_Status_t s); \ No newline at end of file diff --git a/assets/User_code/bsp/mm.c b/assets/User_code/bsp/mm.c new file mode 100644 index 0000000..b78e3c4 --- /dev/null +++ b/assets/User_code/bsp/mm.c @@ -0,0 +1,14 @@ +/* Includes ----------------------------------------------------------------- */ +#include "bsp\mm.h" + +#include "FreeRTOS.h" + +/* Private define ----------------------------------------------------------- */ +/* Private macro ------------------------------------------------------------ */ +/* Private typedef ---------------------------------------------------------- */ +/* Private variables -------------------------------------------------------- */ +/* Private function -------------------------------------------------------- */ +/* Exported functions ------------------------------------------------------- */ +inline void *BSP_Malloc(size_t size) { return pvPortMalloc(size); } + +inline void BSP_Free(void *pv) { vPortFree(pv); } diff --git a/assets/User_code/bsp/buzzer_gpio.h b/assets/User_code/bsp/mm.h similarity index 71% rename from assets/User_code/bsp/buzzer_gpio.h rename to assets/User_code/bsp/mm.h index 7a5f548..57bdcac 100644 --- a/assets/User_code/bsp/buzzer_gpio.h +++ b/assets/User_code/bsp/mm.h @@ -1,20 +1,20 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + /* Includes ----------------------------------------------------------------- */ +#include #include /* Exported constants ------------------------------------------------------- */ /* Exported macro ----------------------------------------------------------- */ /* Exported types ----------------------------------------------------------- */ - -/* 设置BUZZER状态 */ -typedef enum -{ - BSP_BUZZER_ON, - BSP_BUZZER_OFF, - BSP_BUZZER_TAGGLE, -} BSP_Buzzer_Status_t; - /* Exported functions prototypes -------------------------------------------- */ +void *BSP_Malloc(size_t size); +void BSP_Free(void *pv); -int8_t BSP_Buzzer_Set(BSP_Buzzer_Status_t s); +#ifdef __cplusplus +} +#endif diff --git a/assets/User_code/bsp/spi.c b/assets/User_code/bsp/spi.c index 1e4fe86..7560f3f 100644 --- a/assets/User_code/bsp/spi.c +++ b/assets/User_code/bsp/spi.c @@ -9,12 +9,7 @@ static void (*SPI_Callback[BSP_SPI_NUM][BSP_SPI_CB_NUM])(void); /* Private function -------------------------------------------------------- */ static BSP_SPI_t SPI_Get(SPI_HandleTypeDef *hspi) { - if (hspi->Instance == SPI1) - return BSP_SPI_EXAMPLE; - /* - else if (hspi->Instance == SPIX) - return BSP_SPI_XXX; - */ +/* AUTO GENERATED SPI_GET */ else return BSP_SPI_ERR; } @@ -87,12 +82,7 @@ void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi) { /* Exported functions ------------------------------------------------------- */ SPI_HandleTypeDef *BSP_SPI_GetHandle(BSP_SPI_t spi) { switch (spi) { - case BSP_SPI_EXAMPLE: - return &hspi1; - /* - case BSP_SPI_XXX: - return &hspiX; - */ +/* AUTO GENERATED BSP_SPI_GET_HANDLE */ default: return NULL; } diff --git a/assets/User_code/bsp/spi.h b/assets/User_code/bsp/spi.h index 4b55f0f..e42bab7 100644 --- a/assets/User_code/bsp/spi.h +++ b/assets/User_code/bsp/spi.h @@ -17,8 +17,7 @@ extern "C" { /* SPI实体枚举,与设备对应 */ typedef enum { - BSP_SPI_EXAMPLE, - /* BSP_SPI_XXX,*/ +/* AUTO GENERATED BSP_SPI_NAME */ BSP_SPI_NUM, BSP_SPI_ERR, } BSP_SPI_t; diff --git a/assets/User_code/bsp/uart.c b/assets/User_code/bsp/uart.c index 950d69b..0fde9d0 100644 --- a/assets/User_code/bsp/uart.c +++ b/assets/User_code/bsp/uart.c @@ -9,10 +9,7 @@ static void (*UART_Callback[BSP_UART_NUM][BSP_UART_CB_NUM])(void); /* Private function -------------------------------------------------------- */ static BSP_UART_t UART_Get(UART_HandleTypeDef *huart) { - if (huart->Instance == USART1) - return BSP_UART_EXAMPLE; - // else if (huart->Instance == USARTX) - // return BSP_UART_XXX; +/* AUTO GENERATED UART_GET */ else return BSP_UART_ERR; } @@ -101,10 +98,7 @@ void BSP_UART_IRQHandler(UART_HandleTypeDef *huart) { UART_HandleTypeDef *BSP_UART_GetHandle(BSP_UART_t uart) { switch (uart) { - case BSP_UART_EXAMPLE: - return &huart1; - // case BSP_UART_XXX: - // return &huartX; +/* AUTO GENERATED BSP_UART_GET_HANDLE */ default: return NULL; } diff --git a/assets/User_code/bsp/uart.h b/assets/User_code/bsp/uart.h index 9c82fe3..1a0b795 100644 --- a/assets/User_code/bsp/uart.h +++ b/assets/User_code/bsp/uart.h @@ -17,8 +17,7 @@ extern "C" { /* UART实体枚举,与设备对应 */ typedef enum { - BSP_UART_EXAMPLE, - /*BSP_UART_XXX*/ +/* AUTO GENERATED BSP_UART_NAME */ BSP_UART_NUM, BSP_UART_ERR, } BSP_UART_t; diff --git a/assets/User_code/config.csv b/assets/User_code/config.csv new file mode 100644 index 0000000..4df4c5c --- /dev/null +++ b/assets/User_code/config.csv @@ -0,0 +1,4 @@ +bsp,can,delay,dwt,,gpio,i2c,mm,spi,uart, +component,peripheral,driver,library,hal,freertos,stm32cube +device,dr16,ai,nuc +module,chassis,gimbal,arm,shoot \ No newline at end of file