6 Commits

Author SHA1 Message Date
Razvalyaev
043359fe66 + фикс кривых проверок на наличие uint8_t
+ фикс перевод float в iq
+ фикс поиска вручнуб добавленных переменных в debug_vars.c
2025-07-17 10:37:58 +03:00
Razvalyaev
c55f38ef1c + пример debug_vars.c
+ exe
+ опечатка в readme
+ коррекции по абзацам в комментах
2025-07-17 09:26:57 +03:00
Razvalyaev
ae2c90160e +библиотека .c/.h переписана под универсальные дефайны intX_t uintX_t
+сделано задание размера короткого имени
+ добавлена бета поддержка stm:+
   - парс переменных из файла преокта Keil или makefile CubeIDE
   - запись в utf-8 для STM, вместо cp1251 для TMS
   - другой размер int (32 бита, вместо 16 бит) для STM
2025-07-17 09:18:03 +03:00
Razvalyaev
4de53090a1 добавлены комменты к debug_tools.c/.h
начата работа над поддержкой stm32 и кейл проектов
2025-07-15 19:05:52 +03:00
Razvalyaev
742c4e9e1b readme для .c файлов 2025-07-15 15:56:47 +03:00
Razvalyaev
369cfa808c чистка для релиза
переструктурировано чуть

и всякие мелкие фиксы
2025-07-15 15:37:29 +03:00
18 changed files with 901 additions and 25896 deletions

Binary file not shown.

View File

@@ -1,21 +1,56 @@
# DebugVarEdit — Утилита для генерации отладочных переменных C-проекта # DebugTools - Просмотр переменных по указателям
Модуль состоит из трех файлов:
- **debug_tools.c** - реализация считывания переменных
- **debug_tools.h** - объявление всякого для считывания переменных
- **debug_vars.c** - определение массива считываемых переменных
Этот модуль предоставляет функциональность для чтения значений переменных во встроенной системе, включая работу с IQ-форматами, защиту доступа и проверку диапазонов памяти.
Для чтения переменных можно использовать функции:
```c
int Debug_ReadVar(int var_ind, int32_t *return_long);
int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr);
```
Переменные доступные для чтения определяются в **debug_vars.c** (их можно прописывать вручную или генерировать через **DebugVarEdit**):
```c
// Определение массива с указателями на переменные для отладки
int DebugVar_Qnt = 5;
#pragma DATA_SECTION(dbg_vars,".dbgvar_info")
// pointer_type iq_type return_iq_type short_name
DebugVar_t dbg_vars[] = {\
{(uint8_t *)&freqTerm, pt_float, t_iq_none, t_iq10, "freqT" }, \
{(uint8_t *)&ADC_sf[0][0], pt_int16, t_iq_none, t_iq_none, "ADC_sf00" }, \
{(uint8_t *)&ADC_sf[0][1], pt_int16, t_iq_none, t_iq_none, "ADC_sf01" }, \
{(uint8_t *)&ADC_sf[0][2], pt_int16, t_iq_none, t_iq_none, "ADC_sf02" }, \
{(uint8_t *)&ADC_sf[0][3], pt_int16, t_iq_none, t_iq_none, "ADC_sf03" }, \
{(uint8_t *)&Bender[0].KOhms, pt_uint16, t_iq, t_iq10, "Bend0.KOhm" }, \
{(uint8_t *)&Bender[0].Times, pt_uint16, t_iq_none, t_iq_none, "Bend0.Time" }, \
};
```
# DebugVarEdit - Настройка переменных
**DebugVarEdit** — графическое приложение для Windows, предназначенное для настройки и генерации отладочных переменных (`debug_vars.c`) на основе исходного C-проекта. Работает с `makefile` проекта, сохраняет изменения в XML и позволяет удобно редактировать переменные и их типы через интерфейс. **DebugVarEdit** — графическое приложение для Windows, предназначенное для настройки и генерации отладочных переменных (`debug_vars.c`) на основе исходного C-проекта. Работает с `makefile` проекта, сохраняет изменения в XML и позволяет удобно редактировать переменные и их типы через интерфейс.
Программа — один исполняемый файл `DebugVarEdit.exe`, не требующий установки и дополнительных зависимостей. Программа — один исполняемый файл `DebugVarEdit.exe`, не требующий установки и дополнительных зависимостей.
> Требуется Windows 7 или новее. > Требуется Windows 7 или новее.
--- ---
## Как использовать ## Как использовать приложение
1. Запустите **DebugVarEdit.exe.** 1. Запустите **DebugVarEdit.exe.**
2. Укажите пути: 2. Укажите пути и контроллер:
- **Путь к XML** — новый или существующий файл настроек переменных; - **Путь к XML** — новый или существующий файл настроек переменных;
- **Путь к проекту** — путь к корню проека (папка, которая является корнем для проекта в Code Composer); - **Путь к проекту** — путь к корню проека (папка, которая является корнем для проекта в Code Composer);
- **Путь к makefile** — путь к `makefile` относительно корня проекта; - **Путь к makefile** — путь к `makefile` относительно корня проекта;
- **Путь для debug_vars.c** — папка, куда будет сгенерирован файл `debug_vars.c` с переменными. - **Путь для debug_vars.c** — папка, куда будет сгенерирован файл `debug_vars.c` с переменными.
- **МК** — TMS или STM. Они отличаются размером int, и также принятыми кодировками файлов (utf-8/cp1251)
3. Нажмите **Сканировать переменные**: 3. Нажмите **Сканировать переменные**:
- Программа проанализирует исходники, указанные в makefile, и найдёт все переменные. - Программа проанализирует исходники, указанные в makefile, и найдёт все переменные.
@@ -59,7 +94,7 @@
## Пример XML-файла ## Пример XML-файла
```xml ```xml
<project proj_path="C:/myproj" makefile_path="Debug/Makefile" structs_path="debugVars/structs.xml"> <project proj_path="C:/myproj" makefile_path="Debug/Makefile" structs_path="Src/DebugTools/structs.xml">
<variables> <variables>
<var name="g_myvar"> <var name="g_myvar">
<enable>true</enable> <enable>true</enable>
@@ -77,6 +112,7 @@
</project> </project>
``` ```
---
--- ---
# Для разработчиков # Для разработчиков
@@ -85,34 +121,34 @@
```bash ```bash
Src Src
├── build/
│ └── build_and_clean.py # Билдинг проекта в .exe (через nuitka или pyinstaller)
├── DebugVarEdit_GUI.py # Главное окно ├── DebugVarEdit_GUI.py # Главное окно
├── var_table.py # Таблица выбранных переменных ├── var_table.py # Таблица выбранных переменных
├── var_selector_window.py # Окно выбора переменных ├── var_selector_window.py # Окно выбора переменных
├── var_selector_table.py # Таблица переменных в окне выбора переменных ├── var_selector_table.py # Таблица переменных в окне выбора переменных
├── scan_progress_gui.py # Отображение процесса сканирования переменных ├── scan_progress_gui.py # Отображение процесса сканирования переменных
├── scan_vars.py # Сканирование переменных среди .c/.h файлов ├── scan_vars.py # Сканирование переменных среди .c/.h файлов
├── generate_debug_vars.py # Генерация debug_vars.c ├── generate_debug_vars.py # Генерация debug_vars.c
├── myXML.py # Утилиты для XML ├── myXML.py # Утилиты для XML
├── makefile_parser.py # Парсинг makefile на .c/.h файлы ├── makefile_parser.py # Парсинг makefile на .c/.h файлы
├── var_setup.py # Подготовка переменных для окна выбора переменных ├── var_setup.py # Подготовка переменных для окна выбора переменных
├── libclang.dll # Бибилиотека clang ├── libclang.dll # Бибилиотека clang
├── icon.ico # Иконка ├── icon.ico # Иконка
build
├── build_and_clean.py # Билдинг проекта в .exe (через nuitka или pyinstaller)
``` ```
### Зависимости ### Зависимости
Для запуска приложения: Для запуска приложения:
- **Python 3.7+** - **Python 3.7+**
- **clang** — используется для парсинга C-кода (требуется `libclang.dll`) - **clang** — используется для парсинга C-кода (требуется `libclang.dll`, лежит в папке Src)
- **PySide2** — GUI-фреймворк - **PySide2** — GUI-фреймворк
- **lxml** — работа с XML - **lxml** — работа с XML
> Python 3.7 и PySide2 рекомендуется для совместимости с Windows 7 > Python 3.7 и PySide2 рекомендуется для совместимости с Windows 7
Для сборки `.exe`: Для сборки `.exe`:
- **Nuitka** — создает полностью автономный `.exe` без внешних зависимостей - **Nuitka** — создает полностью автономный `.exe` без внешних зависимостей
- **PyInstaller** — создает `.exe` с зависимостью от `pythonXX.dll` (Python должен быть установлен) - **PyInstaller** — создает `.exe` с зависимостью от `pythonXX.dll` (Python должен быть установлен для запуска `.exe`)
### Сборка: ### Сборка:
@@ -132,5 +168,5 @@ build
### Установка зависимостей ### Установка зависимостей
```bash ```bash
pip install PySide2 lxml nuitka pyinstaller pip install clang PySide2 lxml nuitka pyinstaller
``` ```

View File

@@ -5,13 +5,13 @@ import sys
import os import os
import subprocess import subprocess
import lxml.etree as ET import lxml.etree as ET
from generate_debug_vars import type_map from generate_debug_vars import type_map, choose_type_map
from enum import IntEnum from enum import IntEnum
import threading import threading
from generate_debug_vars import run_generate from generate_debug_vars import run_generate
import var_setup import var_setup
from var_selector_window import var_selector_windowDialog from var_selector_window import VariableSelectorDialog
from var_table import var_tableWidget, rows from var_table import VariableTableWidget, rows
from scan_progress_gui import ProcessOutputWindow from scan_progress_gui import ProcessOutputWindow
import scan_vars import scan_vars
import myXML import myXML
@@ -21,8 +21,9 @@ from PySide2.QtWidgets import (
QApplication, QWidget, QTableWidget, QTableWidgetItem, QApplication, QWidget, QTableWidget, QTableWidgetItem,
QCheckBox, QComboBox, QLineEdit, QVBoxLayout, QHBoxLayout, QPushButton, QCheckBox, QComboBox, QLineEdit, QVBoxLayout, QHBoxLayout, QPushButton,
QCompleter, QAbstractItemView, QLabel, QMessageBox, QFileDialog, QTextEdit, QCompleter, QAbstractItemView, QLabel, QMessageBox, QFileDialog, QTextEdit,
QDialog, QTreeWidget, QTreeWidgetItem, QSizePolicy, QHeaderView QDialog, QTreeWidget, QTreeWidgetItem, QSizePolicy, QHeaderView,
) QMenuBar, QMenu, QAction
)
from PySide2.QtGui import QTextCursor, QKeyEvent, QIcon, QFont from PySide2.QtGui import QTextCursor, QKeyEvent, QIcon, QFont
from PySide2.QtCore import Qt, QProcess, QObject, Signal, QSettings from PySide2.QtCore import Qt, QProcess, QObject, Signal, QSettings
@@ -58,6 +59,7 @@ class VarEditor(QWidget):
self.output_path = None self.output_path = None
self._updating = False # Флаг блокировки рекурсии self._updating = False # Флаг блокировки рекурсии
self._resizing = False # флаг блокировки повторного вызова self._resizing = False # флаг блокировки повторного вызова
self.target = 'TMS'
self.initUI() self.initUI()
def initUI(self): def initUI(self):
@@ -122,6 +124,32 @@ class VarEditor(QWidget):
self.btn_update_vars = QPushButton(scan_title) self.btn_update_vars = QPushButton(scan_title)
self.btn_update_vars.clicked.connect(self.update_vars_data) self.btn_update_vars.clicked.connect(self.update_vars_data)
# Добавляем чекбокс для выбора типовой карты
# --- Создаем верхнее меню ---
menubar = QMenuBar(self)
menubar.setToolTip('Разные размеры int и кодировки файлов')
self.target_menu = QMenu("МК:", menubar)
# Создаем действия для выбора Target
self.action_tms = QAction("TMS", self, checkable=True)
self.action_stm = QAction("STM", self, checkable=True)
# Инициализируем QSettings с именем организации и приложения
self.settings = QSettings("SET", "DebugVarEdit_MainWindow")
# Восстанавливаем сохранённое состояние, если есть
mcu = self.settings.value("mcu_choosen", True, type=str)
self.on_target_selected(mcu)
self.target_menu.setToolTip(f'TMS: Размер int 16 бит. Кодировка cp1251\nSTM: Размер int 32 бита. Кодировка utf-8')
# Группируем действия чтобы выбирался только один
self.action_tms.triggered.connect(lambda: self.on_target_selected("TMS"))
self.action_tms.setToolTip('Размер int 16 бит. Кодировка cp1251')
self.action_stm.triggered.connect(lambda: self.on_target_selected("STM"))
self.action_stm.setToolTip('Размер int 32 бита. Кодировка utf-8')
self.target_menu.addAction(self.action_tms)
self.target_menu.addAction(self.action_stm)
menubar.addMenu(self.target_menu)
# Кнопка сохранения # Кнопка сохранения
btn_save = QPushButton(build_title) btn_save = QPushButton(build_title)
btn_save.clicked.connect(self.save_build) btn_save.clicked.connect(self.save_build)
@@ -134,9 +162,10 @@ class VarEditor(QWidget):
btn_open_output = QPushButton(open_output_title) btn_open_output = QPushButton(open_output_title)
btn_open_output.clicked.connect(self.__open_output_file_with_program) btn_open_output.clicked.connect(self.__open_output_file_with_program)
# Таблица # Таблица
self.table = var_tableWidget() self.table = VariableTableWidget()
# Основной layout # Основной layout
layout = QVBoxLayout() layout = QVBoxLayout()
layout.setMenuBar(menubar) # прикрепляем menubar в layout сверху
layout.addLayout(xml_layout) layout.addLayout(xml_layout)
layout.addLayout(proj_layout) layout.addLayout(proj_layout)
layout.addLayout(makefile_layout) layout.addLayout(makefile_layout)
@@ -150,7 +179,20 @@ class VarEditor(QWidget):
self.setLayout(layout) self.setLayout(layout)
def on_target_selected(self, target):
self.target_menu.setTitle(f'МК: {target}')
self.settings.setValue("mcu_choosen", target)
self.target = target.lower()
if self.target == "stm":
choose_type_map(True)
self.action_stm.setChecked(True)
self.action_tms.setChecked(False)
else:
choose_type_map(False)
self.action_tms.setChecked(True)
self.action_stm.setChecked(False)
def get_xml_path(self): def get_xml_path(self):
xml_path = self.xml_output_edit.text().strip() xml_path = self.xml_output_edit.text().strip()
return xml_path return xml_path
@@ -208,7 +250,7 @@ class VarEditor(QWidget):
# Создаём окно с кнопкой "Готово" # Создаём окно с кнопкой "Готово"
self.proc_win = ProcessOutputWindow(self.proj_path, self.makefile_path, self.xml_path, self.proc_win = ProcessOutputWindow(self.proj_path, self.makefile_path, self.xml_path,
on_done_callback=self.__after_scan_vars_finished) self.__after_scan_vars_finished, self)
self.proc_win.start_scan() self.proc_win.start_scan()
@@ -241,7 +283,7 @@ class VarEditor(QWidget):
return return
try: try:
run_generate(self.proj_path, self.xml_path, self.output_path) run_generate(self.proj_path, self.xml_path, self.output_path, self.table._shortname_size)
QMessageBox.information(self, "Готово", "Файл debug_vars.c успешно сгенерирован.") QMessageBox.information(self, "Готово", "Файл debug_vars.c успешно сгенерирован.")
self.update() self.update()
except Exception as e: except Exception as e:
@@ -358,15 +400,25 @@ class VarEditor(QWidget):
super().keyPressEvent(event) super().keyPressEvent(event)
def __browse_makefile(self): def __browse_makefile(self):
if self.target == 'stm':
file_filter = "Makefile или Keil-проект (*.uvprojx *.uvproj makefile);;Все файлы (*)"
dialog_title = "Выберите Makefile или Keil-проект"
else: # 'TMS' или по умолчанию
file_filter = "Makefile (makefile);;Все файлы (*)"
dialog_title = "Выберите Makefile"
file_path, _ = QFileDialog.getOpenFileName( file_path, _ = QFileDialog.getOpenFileName(
self, "Выберите Makefile", filter="Makefile (makefile);;All Files (*)" self,
dialog_title,
filter=file_filter
) )
if file_path and self.proj_path: if file_path:
path = myXML.make_relative_path(file_path, self.proj_path) if self.proj_path:
else: path = myXML.make_relative_path(file_path, self.proj_path)
path = file_path else:
self.makefile_edit.setText(path) path = file_path
self.makefile_path = path self.makefile_edit.setText(path)
self.makefile_path = path
def __browse_source_output(self): def __browse_source_output(self):
dir_path = QFileDialog.getExistingDirectory(self, "Выберите папку для debug_vars.c") dir_path = QFileDialog.getExistingDirectory(self, "Выберите папку для debug_vars.c")
@@ -438,12 +490,13 @@ class VarEditor(QWidget):
self.write_to_xml() self.write_to_xml()
def __open_variable_selector(self): def __open_variable_selector(self):
self.update()
if not self.vars_list: if not self.vars_list:
QMessageBox.warning(self, "Нет переменных", f"Сначала загрузите переменные ({scan_title}).") QMessageBox.warning(self, "Нет переменных", f"Сначала загрузите переменные ({scan_title}).")
return return
dlg = var_selector_windowDialog(self.table, self.vars_list, self.structs, self.typedef_map, self.xml_path, self) dlg = VariableSelectorDialog(self.table, self.vars_list, self.structs, self.typedef_map, self.xml_path, self)
if dlg.exec_(): if dlg.exec_():
self.write_to_xml() self.write_to_xml()
self.update() self.update()

55
Src/README_DEVELOP.md Normal file
View File

@@ -0,0 +1,55 @@
# Для разработчиков
### Структура проекта:
```bash
Src
├── build/
│ └── build_and_clean.py # Билдинг проекта в .exe (через nuitka или pyinstaller)
├── DebugVarEdit_GUI.py # Главное окно
├── var_table.py # Таблица выбранных переменных
├── var_selector_window.py # Окно выбора переменных
├── var_selector_table.py # Таблица переменных в окне выбора переменных
├── scan_progress_gui.py # Отображение процесса сканирования переменных
├── scan_vars.py # Сканирование переменных среди .c/.h файлов
├── generate_debug_vars.py # Генерация debug_vars.c
├── myXML.py # Утилиты для XML
├── makefile_parser.py # Парсинг makefile на .c/.h файлы
├── var_setup.py # Подготовка переменных для окна выбора переменных
├── libclang.dll # Бибилиотека clang
├── icon.ico # Иконка
```
### Зависимости
Для запуска приложения:
- **Python 3.7+**
- **clang** — используется для парсинга C-кода (требуется `libclang.dll`)
- **PySide2** — GUI-фреймворк
- **lxml** — работа с XML
> Python 3.7 и PySide2 рекомендуется для совместимости с Windows 7
Для сборки `.exe`:
- **Nuitka** — создает полностью автономный `.exe` без внешних зависимостей
- **PyInstaller** — создает `.exe` с зависимостью от `pythonXX.dll` (Python должен быть установлен)
### Сборка:
Если вы хотите собрать `DebugVarEdit.exe` самостоятельно из исходников, используйте скрипт **build/build_and_clean.py**. Он автоматически собирает проект с помощью Nuitka или PyInstaller:
- Собирает проект в `DebugVarEdit.exe` в корневой папке.
- Включает:
- все необходимые `.dll` (например, `libclang.dll`),
- иконку (`icon.ico`),
- плагины PySide2.
- Очищает временные папки после сборки:
- `build_temp`
- `__pycache__`
- `DebugVarEdit_GUI.*`
> Все пути, имена файлов, временные папки и выбор между Nuitka и PyInstaller можно настроить в начале файла `build_and_clean.py`.
### Установка зависимостей
```bash
pip install PySide2 lxml nuitka pyinstaller
```

View File

@@ -12,9 +12,10 @@ from xml.dom import minidom
import myXML import myXML
import argparse import argparse
shortnameSize = 10
# === Словарь соответствия типов XML → DebugVarType_t === # === Словарь соответствия типов XML → DebugVarType_t ===
type_map = dict([ type_map_tms = dict([
*[(k, 'pt_int8') for k in ('signed char', 'char')], *[(k, 'pt_int8') for k in ('signed char', 'char')],
*[(k, 'pt_int16') for k in ('int', 'int16', 'short')], *[(k, 'pt_int16') for k in ('int', 'int16', 'short')],
*[(k, 'pt_int32') for k in ('long', 'int32', '_iqx')], *[(k, 'pt_int32') for k in ('long', 'int32', '_iqx')],
@@ -52,6 +53,150 @@ type_map = dict([
('struct[]', 'pt_arr_struct'), ('struct[]', 'pt_arr_struct'),
('union[]', 'pt_arr_union'), ('union[]', 'pt_arr_union'),
]) ])
# === Словарь соответствия типов XML → DebugVarType_t ===
type_map_stm32 = dict([
*[(k, 'pt_int8') for k in (
'int8_t', 'signed char', 'char'
)],
# --- 8-bit unsigned ---
*[(k, 'pt_uint8') for k in (
'uint8_t', 'unsigned char'
)],
# --- 16-bit signed ---
*[(k, 'pt_int16') for k in (
'int16_t', 'short', 'short int', 'signed short', 'signed short int'
)],
# --- 16-bit unsigned ---
*[(k, 'pt_uint16') for k in (
'uint16_t', 'unsigned short', 'unsigned short int'
)],
# --- 32-bit signed ---
*[(k, 'pt_int32') for k in (
'int32_t', 'int', 'signed', 'signed int'
)],
# --- 32-bit unsigned ---
*[(k, 'pt_uint32') for k in (
'uint32_t', 'unsigned', 'unsigned int'
)],
# --- 64-bit signed ---
*[(k, 'pt_int64') for k in (
'int64_t', 'long long', 'signed long long', 'signed long long int'
)],
# --- 64-bit unsigned ---
*[(k, 'pt_uint64') for k in (
'uint64_t', 'unsigned long long', 'unsigned long long int'
)],
# --- Float ---
*[(k, 'pt_float') for k in (
'float', 'float32_t'
)],
# --- Struct and Union ---
('struct', 'pt_struct'),
('union', 'pt_union'),
('struct*', 'pt_ptr_struct'),
('union*', 'pt_ptr_union'),
('struct[]', 'pt_arr_struct'),
('union[]', 'pt_arr_union'),
# === POINTERS ===
# 8-bit
*[(k, 'pt_ptr_int8') for k in (
'int8_t*', 'signed char*', 'char*'
)],
*[(k, 'pt_ptr_uint8') for k in (
'uint8_t*', 'unsigned char*'
)],
# 16-bit
*[(k, 'pt_ptr_int16') for k in (
'int16_t*', 'short*', 'short int*', 'signed short*', 'signed short int*'
)],
*[(k, 'pt_ptr_uint16') for k in (
'uint16_t*', 'unsigned short*', 'unsigned short int*'
)],
# 32-bit
*[(k, 'pt_ptr_int32') for k in (
'int32_t*', 'int*', 'signed*', 'signed int*'
)],
*[(k, 'pt_ptr_uint32') for k in (
'uint32_t*', 'unsigned*', 'unsigned int*'
)],
# 64-bit
*[(k, 'pt_ptr_int64') for k in (
'int64_t*', 'long long*', 'signed long long*', 'signed long long int*'
)],
*[(k, 'pt_ptr_uint64') for k in (
'uint64_t*', 'unsigned long long*', 'unsigned long long int*'
)],
# float*
*[(k, 'pt_ptr_float') for k in (
'float*', 'float32_t*'
)],
# === ARRAYS ===
# 8-bit
*[(k, 'pt_arr_int8') for k in (
'int8_t[]', 'signed char[]', 'char[]'
)],
*[(k, 'pt_arr_uint8') for k in (
'uint8_t[]', 'unsigned char[]'
)],
# 16-bit
*[(k, 'pt_arr_int16') for k in (
'int16_t[]', 'short[]', 'short int[]', 'signed short[]', 'signed short int[]'
)],
*[(k, 'pt_arr_uint16') for k in (
'uint16_t[]', 'unsigned short[]', 'unsigned short int[]'
)],
# 32-bit
*[(k, 'pt_arr_int32') for k in (
'int32_t[]', 'int[]', 'signed[]', 'signed int[]'
)],
*[(k, 'pt_arr_uint32') for k in (
'uint32_t[]', 'unsigned[]', 'unsigned int[]'
)],
# 64-bit
*[(k, 'pt_arr_int64') for k in (
'int64_t[]', 'long long[]', 'signed long long[]', 'signed long long int[]'
)],
*[(k, 'pt_arr_uint64') for k in (
'uint64_t[]', 'unsigned long long[]', 'unsigned long long int[]'
)],
# float[]
*[(k, 'pt_arr_float') for k in (
'float[]', 'float32_t[]'
)],
])
type_map = type_map_tms
stm_flag_global = 0
def choose_type_map(stm_flag):
global type_map # объявляем, что будем менять глобальную переменную
global stm_flag_global # объявляем, что будем менять глобальную переменную
if stm_flag:
type_map = type_map_stm32
stm_flag_global = 1
else:
type_map = type_map_tms
stm_flag_global = 0
def map_type_to_pt(typename, varname=None, typedef_map=None): def map_type_to_pt(typename, varname=None, typedef_map=None):
typename_orig = typename.strip() typename_orig = typename.strip()
@@ -140,15 +285,20 @@ def add_new_vars_to_xml(proj_path, xml_rel_path, output_path):
Возвращает True если что-то добавлено и XML перезаписан, иначе False. Возвращает True если что-то добавлено и XML перезаписан, иначе False.
""" """
pattern = re.compile(
r'{\s*\(uint8_t\s*\*\)\s*&([a-zA-Z_][a-zA-Z0-9_]*(?:\[.*?\])?(?:(?:\.|->)[a-zA-Z_][a-zA-Z0-9_]*(?:\[.*?\])?)*)\s*,\s*'
r'(pt_\w+)\s*,\s*'
r'(t?_?iq\w+)\s*,\s*'
r'(t?_?iq\w+)\s*,\s*'
r'"([^"]+)"'
)
# Считываем существующие переменные # Считываем существующие переменные
parsed_vars = {} parsed_vars = {}
if os.path.isfile(output_path): if os.path.isfile(output_path):
with open(output_path, 'r', encoding='utf-8', errors='ignore') as f: with open(output_path, 'r', encoding='utf-8', errors='ignore') as f:
for line in f: for line in f:
# {(char *)&some.deep.var.name , pt_uint16 , t_iq15 , "ShortName"}, # {(uint8_t *)&some.deep.var.name , pt_uint16 , t_iq15 , t_iq10, "ShortName"},
m = re.match( m = pattern.search(line)
r'{\s*\(char\s*\*\)\s*&([a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*)\s*,\s*(pt_\w+)\s*,\s*(t?iq_\w+)\s*,\s*"([^"]+)"',
line)
if m: if m:
full_varname = m.group(1) # e.g., some.deep.var.name full_varname = m.group(1) # e.g., some.deep.var.name
pt_type = m.group(2) pt_type = m.group(2)
@@ -285,12 +435,27 @@ def read_vars_from_xml(proj_path, xml_rel_path):
return unique_vars, include_files, vars_need_extern return unique_vars, include_files, vars_need_extern
def read_file_try_encodings(filepath):
if not os.path.isfile(filepath):
# Файл не существует — просто вернуть пустую строку или None
return "", None
for enc in ['utf-8', 'cp1251']:
try:
with open(filepath, 'r', encoding=enc) as f:
content = f.read()
return content, enc
except UnicodeDecodeError:
continue
raise UnicodeDecodeError(f"Не удалось прочитать файл {filepath} с кодировками utf-8 и cp1251")
def generate_vars_file(proj_path, xml_path, output_dir): def generate_vars_file(proj_path, xml_path, output_dir):
output_dir = os.path.join(proj_path, output_dir) output_dir = os.path.join(proj_path, output_dir)
os.makedirs(output_dir, exist_ok=True) os.makedirs(output_dir, exist_ok=True)
output_path = os.path.join(output_dir, 'debug_vars.c') output_path = os.path.join(output_dir, 'debug_vars.c')
LIBC_path = os.path.join(output_dir, 'debug_tools.c')
LIBH_path = os.path.join(output_dir, 'debug_tools.h')
# Запись новых переменных для в XML # Запись новых переменных для в XML
@@ -338,7 +503,7 @@ def generate_vars_file(proj_path, xml_path, output_dir):
# Дополнительные поля, например комментарий # Дополнительные поля, например комментарий
comment = info.get("comment", "") comment = info.get("comment", "")
short_name = info.get("shortname", f'"{vname}"') short_name = info.get("shortname", f'"{vname}"')
short_trimmed = short_name[:10] # ограничиваем длину до 10 short_trimmed = short_name[:shortnameSize] # ограничиваем длину до 10
if pt_type not in ('pt_struct', 'pt_union'): if pt_type not in ('pt_struct', 'pt_union'):
f_name = f'{vname},' f_name = f'{vname},'
@@ -348,7 +513,7 @@ def generate_vars_file(proj_path, xml_path, output_dir):
f_short_name = f'"{short_trimmed}"' # оборачиваем в кавычки f_short_name = f'"{short_trimmed}"' # оборачиваем в кавычки
# Добавим комментарий после записи, если он есть # Добавим комментарий после записи, если он есть
comment_str = f' // {comment}' if comment else '' comment_str = f' // {comment}' if comment else ''
line = f'{{(char *)&{f_name:<57} {f_type:<15} {f_iq:<15} {f_ret_iq:<15} {f_short_name:<21}}}, \\{comment_str}' line = f'{{(uint8_t *)&{f_name:<58} {f_type:<15} {f_iq:<15} {f_ret_iq:<15} {f_short_name:<21}}}, \\{comment_str}'
new_debug_vars[vname] = line new_debug_vars[vname] = line
else: else:
@@ -394,14 +559,19 @@ def generate_vars_file(proj_path, xml_path, output_dir):
out_lines.append(f'\n\n// Определение массива с указателями на переменные для отладки') out_lines.append(f'\n\n// Определение массива с указателями на переменные для отладки')
out_lines.append(f'int DebugVar_Qnt = {len(all_debug_lines)};') out_lines.append(f'int DebugVar_Qnt = {len(all_debug_lines)};')
out_lines.append('#pragma DATA_SECTION(dbg_vars,".dbgvar_info")') if stm_flag_global == 0:
out_lines.append('#pragma DATA_SECTION(dbg_vars,".dbgvar_info")')
out_lines.append('// pointer_type iq_type return_iq_type short_name')
out_lines.append('DebugVar_t dbg_vars[] = {\\') out_lines.append('DebugVar_t dbg_vars[] = {\\')
out_lines.extend(all_debug_lines) out_lines.extend(all_debug_lines)
out_lines.append('};') out_lines.append('};')
out_lines.append('') out_lines.append('')
# Выберем кодировку для записи файла # Выберем кодировку для записи файла
# Если встречается несколько, возьмем первую из set # Если встречается несколько, возьмем первую из set
enc_to_write = 'cp1251' if stm_flag_global == 0:
enc_to_write = 'cp1251'
else:
enc_to_write = 'utf-8'
#print("== GLOBAL VARS FOUND ==") #print("== GLOBAL VARS FOUND ==")
#for vname, (vtype, path) in vars_in_c.items(): #for vname, (vtype, path) in vars_in_c.items():
@@ -411,6 +581,16 @@ def generate_vars_file(proj_path, xml_path, output_dir):
with open(output_path, 'w', encoding=enc_to_write) as f: with open(output_path, 'w', encoding=enc_to_write) as f:
f.write('\n'.join(out_lines)) f.write('\n'.join(out_lines))
if os.path.isfile(LIBC_path):
libc_code, _ = read_file_try_encodings(LIBC_path)
with open(LIBC_path, 'w', encoding=enc_to_write) as f:
f.write(libc_code)
if os.path.isfile(LIBH_path):
libh_code, _ = read_file_try_encodings(LIBH_path)
with open(LIBH_path, 'w', encoding=enc_to_write) as f:
f.write(libh_code)
print(f'Файл debug_vars.c сгенерирован в кодировке, переменных: {len(all_debug_lines)}') print(f'Файл debug_vars.c сгенерирован в кодировке, переменных: {len(all_debug_lines)}')
@@ -472,16 +652,17 @@ Usage example:
print(f"Error: Project path '{proj_path}' не является директорией или не существует.") print(f"Error: Project path '{proj_path}' не является директорией или не существует.")
sys.exit(1) sys.exit(1)
generate_vars_file(proj_path, xml_path_rel, output_dir_rel) generate_vars_file(proj_path, xml_path_rel, output_dir_rel, 0)
if __name__ == "__main__": if __name__ == "__main__":
main() main()
def run_generate(proj_path, xml_path, output_dir): def run_generate(proj_path, xml_path, output_dir, shortname_size):
import os import os
global shortnameSize
shortnameSize = shortname_size
# Normalize absolute paths # Normalize absolute paths
proj_path = os.path.abspath(proj_path) proj_path = os.path.abspath(proj_path)
xml_path_abs = os.path.abspath(xml_path) xml_path_abs = os.path.abspath(xml_path)

View File

@@ -1,5 +1,6 @@
import os import os
import re import re
from lxml import etree as ET
def strip_single_line_comments(code): def strip_single_line_comments(code):
@@ -66,89 +67,176 @@ def find_all_includes_recursive(c_files, include_dirs, processed_files=None):
return include_files return include_files
def parse_objects_list(objects_list_path, project_root):
c_files = []
include_dirs = set()
if not os.path.isfile(objects_list_path):
return c_files, include_dirs
with open(objects_list_path, 'r', encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
line = line.strip().strip('"').replace("\\", "/")
if line.endswith(".o"):
c_file = re.sub(r"\.o$", ".c", line)
abs_path = os.path.normpath(os.path.join(project_root, c_file))
if os.path.isfile(abs_path):
if not any(x in abs_path for x in ["DebugTools", "v120", "v100"]):
c_files.append(abs_path)
include_dirs.add(os.path.dirname(abs_path))
return c_files, include_dirs
def parse_uvprojx(uvprojx_path):
import xml.etree.ElementTree as ET
import os
tree = ET.parse(uvprojx_path)
root = tree.getroot()
project_dir = os.path.dirname(os.path.abspath(uvprojx_path))
c_files = []
include_dirs = set()
defines = set()
# Найдём C-файлы и директории
for file_elem in root.findall(".//FilePath"):
file_path = file_elem.text
if file_path:
abs_path = os.path.normpath(os.path.join(project_dir, file_path))
if os.path.isfile(abs_path):
if abs_path.endswith(".c"):
c_files.append(abs_path)
include_dirs.add(os.path.dirname(abs_path))
# Включаем IncludePath
for inc_path_elem in root.findall(".//IncludePath"):
path_text = inc_path_elem.text
if path_text:
paths = path_text.split(';')
for p in paths:
p = p.strip()
if p:
abs_inc_path = os.path.normpath(os.path.join(project_dir, p))
if os.path.isdir(abs_inc_path):
include_dirs.add(abs_inc_path)
# Добавим <Define>
for define_elem in root.findall(".//Define"):
def_text = define_elem.text
if def_text:
for d in def_text.split(','):
d = d.strip()
if d:
defines.add(d)
h_files = find_all_includes_recursive(c_files, include_dirs)
return sorted(c_files), sorted(h_files), sorted(include_dirs), sorted(defines)
def parse_makefile(makefile_path, proj_path): def parse_makefile(makefile_path, proj_path):
makefile_dir = os.path.dirname(makefile_path) import os
project_root = proj_path import re
project_root = os.path.abspath(proj_path)
c_files = []
include_dirs = set()
defines = [] # Заглушка: нет define-параметров из Makefile
with open(makefile_path, 'r', encoding='utf-8') as f: with open(makefile_path, 'r', encoding='utf-8') as f:
lines = f.readlines() lines = f.readlines()
objs_lines = [] raw_entries = []
collecting = False collecting = False
for line in lines: for line in lines:
stripped = line.strip() stripped = line.strip()
if stripped.startswith("ORDERED_OBJS") and "+=" in stripped:
parts = stripped.split("\\") if (("ORDERED_OBJS" in stripped or "C_SOURCES" in stripped) and ("+=" in stripped or "=" in stripped)):
first_part = parts[0]
idx = first_part.find("+=")
tail = first_part[idx+2:].strip()
if tail:
objs_lines.append(tail)
collecting = True collecting = True
if len(parts) > 1:
for p in parts[1:]:
p = p.strip()
if p:
objs_lines.append(p)
continue
if collecting: if collecting:
if stripped.endswith("\\"): line_clean = stripped.rstrip("\\").strip()
objs_lines.append(stripped[:-1].strip()) if line_clean:
else: line_clean = re.sub(r"\$\([^)]+\)", "", line_clean)
objs_lines.append(stripped) line_clean = re.sub(r"\$\{[^}]+\}", "", line_clean)
raw_entries.append(line_clean)
if not stripped.endswith("\\"):
collecting = False collecting = False
objs_str = ' '.join(objs_lines) for entry in raw_entries:
for token in entry.split():
token = token.strip('"')
if not token:
continue
objs_str = re.sub(r"\$\([^)]+\)", "", objs_str) token = token.replace("\\", "/")
objs = [] if token.endswith(".obj"):
for part in objs_str.split(): token = re.sub(r"\.obj$", ".c", token)
part = part.strip() elif token.endswith(".o"):
if part.startswith('"') and part.endswith('"'): token = re.sub(r"\.o$", ".c", token)
part = part[1:-1]
if part:
objs.append(part)
c_files = [] if token.endswith(".c"):
include_dirs = set() abs_path = os.path.normpath(os.path.join(project_root, token))
if os.path.isfile(abs_path):
if not any(x in abs_path for x in ["DebugTools", "v120", "v100"]):
c_files.append(abs_path)
include_dirs.add(os.path.dirname(abs_path))
for obj_path in objs: if not c_files:
if "DebugTools" in obj_path: makefile_dir = os.path.dirname(os.path.abspath(makefile_path))
continue objects_list_path = os.path.join(makefile_dir, "objects.list")
if "v120" in obj_path: c_from_objects, inc_from_objects = parse_objects_list(objects_list_path, project_root)
continue c_files.extend(c_from_objects)
if "v100" in obj_path: include_dirs.update(inc_from_objects)
continue
if obj_path.startswith("Debug\\") or obj_path.startswith("Debug/"): for line in lines:
rel_path = obj_path.replace("Debug\\", "Src\\").replace("Debug/", "Src/") if "-I" in line or "C_INCLUDES" in line:
else: matches = re.findall(r"-I\s*([^\s\\]+)", line)
rel_path = obj_path for match in matches:
match = match.strip('"').replace("\\", "/")
abs_include = os.path.normpath(os.path.join(project_root, match))
if os.path.isdir(abs_include):
include_dirs.add(abs_include)
abs_path = os.path.normpath(os.path.join(project_root, rel_path)) # Добавляем пути с заменой 'Src' на 'Inc', если путь заканчивается на 'Src'
additional_includes = set()
root, ext = os.path.splitext(abs_path) for inc in include_dirs:
if ext.lower() == ".obj": if inc.endswith(os.sep + "Src") or inc.endswith("/Src"):
c_path = root + ".c" inc_inc = inc[:-3] + "Inc" # заменяем 'Src' на 'Inc'
else: if os.path.isdir(inc_inc):
c_path = abs_path additional_includes.add(inc_inc)
# Проверяем существование файла, если нет — пропускаем
if not os.path.isfile(c_path):
continue
# Сохраняем только .c файлы
if c_path.lower().endswith(".c"):
c_files.append(c_path)
dir_path = os.path.dirname(c_path)
if dir_path and "DebugTools" not in dir_path:
include_dirs.add(dir_path)
include_dirs.update(additional_includes)
h_files = find_all_includes_recursive(c_files, include_dirs) h_files = find_all_includes_recursive(c_files, include_dirs)
return sorted(c_files), sorted(h_files), sorted(include_dirs), sorted(defines)
return sorted(c_files), sorted(h_files), sorted(include_dirs)
def parse_project(project_file_path, project_root=None):
"""
Выбирает парсер в зависимости от расширения project_file_path:
- для *.uvprojx и *.uvproj вызывается парсер Keil
- для остальных - parse_makefile
project_root нужен для parse_makefile, если не передан - берется из project_file_path
"""
ext = os.path.splitext(project_file_path)[1].lower()
if ext in ['.uvprojx', '.uvproj']:
# Парсим Keil проект
return parse_uvprojx(project_file_path)
else:
# Парсим makefile
if project_root is None:
project_root = os.path.dirname(os.path.abspath(project_file_path))
return parse_makefile(project_file_path, project_root)

View File

@@ -7,7 +7,7 @@ import contextlib
import io import io
import json import json
from scan_vars import run_scan from scan_vars import run_scan
from var_table import var_tableWidget, rows from var_table import VariableTableWidget, rows
from PySide2.QtWidgets import ( from PySide2.QtWidgets import (
QApplication, QWidget, QTableWidget, QTableWidgetItem, QApplication, QWidget, QTableWidget, QTableWidgetItem,
@@ -73,13 +73,13 @@ class EmittingStream(QObject):
self._buffer = "" self._buffer = ""
class ProcessOutputWindow(QDialog): class ProcessOutputWindow(QDialog):
def __init__(self, proj_path, makefile_path, xml_path, on_done_callback=None): def __init__(self, proj_path, makefile_path, xml_path, on_done_callback=None, parent=None):
super().__init__() super().__init__(parent)
self.setWindowTitle("Поиск переменных...") self.setWindowTitle("Поиск переменных...")
self.resize(600, 480) self.resize(600, 480)
self.setModal(True) self.setModal(True)
self.setAttribute(Qt.WA_DeleteOnClose)
self.proj_path = proj_path self.proj_path = proj_path
self.makefile_path = makefile_path self.makefile_path = makefile_path

View File

@@ -11,7 +11,7 @@ from clang import cindex
from clang.cindex import Config from clang.cindex import Config
import lxml.etree as ET import lxml.etree as ET
from xml.dom import minidom from xml.dom import minidom
from makefile_parser import parse_makefile from makefile_parser import parse_project
from collections import deque from collections import deque
import argparse import argparse
import myXML import myXML
@@ -118,11 +118,11 @@ def get_canonical_typedef_file(var_type, include_dirs):
break break
return None return None
def analyze_variables_across_files(c_files, h_files, include_dirs): def analyze_variables_across_files(c_files, h_files, include_dirs, global_defs):
optional_printf(PRINT_STATUS, "Starting analysis of variables across files...") optional_printf(PRINT_STATUS, "Starting analysis of variables across files...")
index = clang.cindex.Index.create() index = clang.cindex.Index.create()
args = [f"-I{inc}" for inc in include_dirs] define_args = [f"-D{d}" for d in global_defs]
args = [f"-I{inc}" for inc in include_dirs] + define_args
unique_vars = {} # имя переменной → словарь с инфой unique_vars = {} # имя переменной → словарь с инфой
h_files_needed = set() h_files_needed = set()
vars_need_extern = {} # имя переменной → словарь без поля 'extern' vars_need_extern = {} # имя переменной → словарь без поля 'extern'
@@ -154,6 +154,7 @@ def analyze_variables_across_files(c_files, h_files, include_dirs):
# Проверяем, начинается ли имя с "_" и содержит заглавные буквы или служебные символы # Проверяем, начинается ли имя с "_" и содержит заглавные буквы или служебные символы
return bool(re.match(r"^_[_A-Z]", var_name)) return bool(re.match(r"^_[_A-Z]", var_name))
if node.kind == clang.cindex.CursorKind.VAR_DECL: if node.kind == clang.cindex.CursorKind.VAR_DECL:
if node.semantic_parent.kind == clang.cindex.CursorKind.TRANSLATION_UNIT: if node.semantic_parent.kind == clang.cindex.CursorKind.TRANSLATION_UNIT:
is_extern = (node.storage_class == clang.cindex.StorageClass.EXTERN) is_extern = (node.storage_class == clang.cindex.StorageClass.EXTERN)
@@ -170,7 +171,12 @@ def analyze_variables_across_files(c_files, h_files, include_dirs):
return # игнорируем только явно известные служебные переменные return # игнорируем только явно известные служебные переменные
if node.spelling == 'HUGE': # еще одна служеюная, которую хз как выделять if node.spelling == 'HUGE': # еще одна служеюная, которую хз как выделять
return return
if 'Drivers' in node.location.file.name:
return
if 'uint' in node.spelling:
a = 1
# Проверяем, является ли тип указателем на функцию # Проверяем, является ли тип указателем на функцию
# Признак: в типе есть '(' и ')' и '*', например: "void (*)(int)" # Признак: в типе есть '(' и ')' и '*', например: "void (*)(int)"
if "(" in var_type and "*" in var_type and ")" in var_type: if "(" in var_type and "*" in var_type and ")" in var_type:
@@ -295,6 +301,8 @@ def strip_ptr_and_array(typename):
return typename return typename
def analyze_typedefs_and_struct(typedefs, structs): def analyze_typedefs_and_struct(typedefs, structs):
optional_printf(PRINT_STATUS, "Resolving typedefs and expanding struct field types...") optional_printf(PRINT_STATUS, "Resolving typedefs and expanding struct field types...")
@@ -422,10 +430,28 @@ def contains_anywhere_in_node(node, target: str) -> bool:
return False return False
def analyze_typedefs_and_structs_across_files(c_files, include_dirs):
def try_guess_std_include():
# Популярные места, где может лежать stdint.h
guesses = [
r"C:\Keil_v5\ARM\ARMCLANG\include",
r"C:\Program Files (x86)\GNU Arm Embedded Toolchain",
r"C:\Program Files (x86)\Arm GNU Toolchain"
]
found = []
for base in guesses:
for root, dirs, files in os.walk(base):
if "stdint.h" in files:
found.append(root)
return found
def analyze_typedefs_and_structs_across_files(c_files, include_dirs, global_defs):
optional_printf(PRINT_STATUS, "Starting analysis of typedefs and structs across files...") optional_printf(PRINT_STATUS, "Starting analysis of typedefs and structs across files...")
index = clang.cindex.Index.create() index = clang.cindex.Index.create()
args = [f"-I{inc}" for inc in include_dirs] define_args = [f"-D{d}" for d in global_defs]
extra_std_include_dirs = try_guess_std_include()
args = [f"-I{inc}" for inc in include_dirs] + extra_std_include_dirs + define_args
unique_typedefs_raw = {} unique_typedefs_raw = {}
unique_structs_raw = {} unique_structs_raw = {}
@@ -452,7 +478,6 @@ def analyze_typedefs_and_structs_across_files(c_files, include_dirs):
raw_name = node.spelling raw_name = node.spelling
normalized_name = normalize_type_name(raw_name) normalized_name = normalize_type_name(raw_name)
# struct_name всегда с префиксом # struct_name всегда с префиксом
if node.spelling and "unnamed" not in normalized_name: if node.spelling and "unnamed" not in normalized_name:
struct_name = f"{prefix}{normalized_name}" struct_name = f"{prefix}{normalized_name}"
@@ -855,10 +880,10 @@ Usage example:
print(f"Error: Makefile path '{makefile_path}' does not exist.") print(f"Error: Makefile path '{makefile_path}' does not exist.")
sys.exit(1) sys.exit(1)
c_files, h_files, include_dirs = parse_makefile(makefile_path, proj_path) c_files, h_files, include_dirs, global_defs = parse_project(makefile_path, proj_path)
vars, includes, externs = analyze_variables_across_files(c_files, h_files, include_dirs) vars, includes, externs = analyze_variables_across_files(c_files, h_files, include_dirs, global_defs)
typedefs, structs = analyze_typedefs_and_structs_across_files(c_files, include_dirs) typedefs, structs = analyze_typedefs_and_structs_across_files(c_files, include_dirs, global_defs)
vars = dict(sorted(vars.items())) vars = dict(sorted(vars.items()))
includes = get_sorted_headers(c_files, includes, include_dirs) includes = get_sorted_headers(c_files, includes, include_dirs)
@@ -898,10 +923,10 @@ def run_scan(proj_path, makefile_path, output_xml, verbose=2):
if not os.path.isfile(makefile_path): if not os.path.isfile(makefile_path):
raise FileNotFoundError(f"Makefile path '{makefile_path}' does not exist.") raise FileNotFoundError(f"Makefile path '{makefile_path}' does not exist.")
c_files, h_files, include_dirs = parse_makefile(makefile_path, proj_path) c_files, h_files, include_dirs, global_defs = parse_project(makefile_path, proj_path)
vars, includes, externs = analyze_variables_across_files(c_files, h_files, include_dirs) vars, includes, externs = analyze_variables_across_files(c_files, h_files, include_dirs, global_defs)
typedefs, structs = analyze_typedefs_and_structs_across_files(c_files, include_dirs) typedefs, structs = analyze_typedefs_and_structs_across_files(c_files, include_dirs, global_defs)
vars = dict(sorted(vars.items())) vars = dict(sorted(vars.items()))
includes = get_sorted_headers(c_files, includes, include_dirs) includes = get_sorted_headers(c_files, includes, include_dirs)

View File

@@ -244,7 +244,6 @@ class VariableSelectWidget(QWidget):
def filter_tree(self): def filter_tree(self):
text = self.search_input.text().strip().lower() text = self.search_input.text().strip().lower()
print(f"[{self.objectName()}] Filtering tree with text: '{text}'")
path_parts = split_path(text) if text else [] path_parts = split_path(text) if text else []
if '.' not in text and '->' not in text and '[' not in text and text != '': if '.' not in text and '->' not in text and '[' not in text and text != '':
@@ -358,8 +357,6 @@ class VariableSelectWidget(QWidget):
self.completer.setModel(QStringListModel(completions)) self.completer.setModel(QStringListModel(completions))
self.completer.complete() self.completer.complete()
print(f"[{self.objectName()}] Updating completions for text: '{text}' -> {len(completions)} completions found.")
print(f" Completions: {completions[:5]}") # Вывести первые 5 для проверки
return completions return completions
@@ -469,7 +466,6 @@ class VariableSelectWidget(QWidget):
def on_search_text_changed(self, text): def on_search_text_changed(self, text):
sender_widget = self.sender() sender_widget = self.sender()
sender_name = sender_widget.objectName() if sender_widget else "Unknown Sender" sender_name = sender_widget.objectName() if sender_widget else "Unknown Sender"
print(f"[{self.objectName()}] (Sender: {sender_name}) Search text changed: '{text}'")
self.completer.setWidget(self.search_input) self.completer.setWidget(self.search_input)
self.filter_tree() self.filter_tree()

View File

@@ -15,7 +15,7 @@ import var_selector_table
array_re = re.compile(r'^(\w+)\[(\d+)\]$') array_re = re.compile(r'^(\w+)\[(\d+)\]$')
class var_selector_windowDialog(QDialog): class VariableSelectorDialog(QDialog):
def __init__(self, table, all_vars, structs, typedefs, xml_path=None, parent=None): def __init__(self, table, all_vars, structs, typedefs, xml_path=None, parent=None):
super().__init__(parent) super().__init__(parent)
self.setWindowTitle("Выбор переменных") self.setWindowTitle("Выбор переменных")
@@ -62,11 +62,29 @@ class var_selector_windowDialog(QDialog):
self.selected_vars_widget.tree.itemDoubleClicked.connect(self.on_rigth_tree_double_click) self.selected_vars_widget.tree.itemDoubleClicked.connect(self.on_rigth_tree_double_click)
self.selected_vars_widget.setObjectName("RightTable") self.selected_vars_widget.setObjectName("RightTable")
# Подписи над таблицами
label_all = QLabel("Все переменные")
label_all.setStyleSheet("font-weight: bold; font-size: 14px;")
label_selected = QLabel("Выбранные переменные")
label_selected.setStyleSheet("font-weight: bold; font-size: 14px;")
# --- Лэйауты --- # --- Лэйауты ---
main_layout = QVBoxLayout(self) # главный вертикальный layout окна main_layout = QVBoxLayout(self) # главный вертикальный layout окна
tables_layout = QHBoxLayout() # горизонтальный layout с таблицами и кнопками # Чекбокс автодополнения — первый в главном layout
main_layout.addWidget(self.autocomplete_checkbox)
# Подписи над таблицами
labels_layout = QHBoxLayout()
labels_layout.addWidget(label_all)
labels_layout.addStretch()
labels_layout.addWidget(label_selected)
main_layout.addLayout(labels_layout)
# Горизонтальный layout с таблицами и кнопками
tables_layout = QHBoxLayout()
# Левая таблица # Левая таблица
self.vars_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.vars_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
@@ -101,7 +119,7 @@ class var_selector_windowDialog(QDialog):
self.btn_accept.clicked.connect(self.on_apply_clicked) self.btn_accept.clicked.connect(self.on_apply_clicked)
# Соединяем чекбокс с методом виджета # Соединяем чекбокс с методом виджета
self.autocomplete_checkbox.stateChanged.connect(self.vars_widget.set_autocomplete) self.autocomplete_checkbox.stateChanged.connect(self.set_autocomplete_tables)
# Устанавливаем начальное состояние автодополнения в виджете # Устанавливаем начальное состояние автодополнения в виджете
self.vars_widget.set_autocomplete(self.autocomplete_checkbox.isChecked()) self.vars_widget.set_autocomplete(self.autocomplete_checkbox.isChecked())
self.selected_vars_widget.set_autocomplete(self.autocomplete_checkbox.isChecked()) self.selected_vars_widget.set_autocomplete(self.autocomplete_checkbox.isChecked())
@@ -224,13 +242,6 @@ class var_selector_windowDialog(QDialog):
self.accept() self.accept()
def save_checkbox_state(self):
self.settings.setValue("autocomplete_enabled", self.autocomplete_checkbox.isChecked())
# Обнови on_left_tree_double_click: # Обнови on_left_tree_double_click:
def on_left_tree_double_click(self, item, column): def on_left_tree_double_click(self, item, column):
selected_names = [item.text(0)] selected_names = [item.text(0)]
@@ -373,3 +384,9 @@ class var_selector_windowDialog(QDialog):
def save_checkbox_state(self): def save_checkbox_state(self):
self.settings.setValue("autocomplete_enabled", self.autocomplete_checkbox.isChecked()) self.settings.setValue("autocomplete_enabled", self.autocomplete_checkbox.isChecked())
def set_autocomplete_tables(self, state):
self.vars_widget.set_autocomplete(state)
self.selected_vars_widget.set_autocomplete(state)

View File

@@ -1,10 +1,10 @@
from PySide2.QtWidgets import ( from PySide2.QtWidgets import (
QTableWidget, QTableWidgetItem, QCheckBox, QComboBox, QLineEdit, QCompleter, QTableWidget, QTableWidgetItem, QCheckBox, QComboBox, QLineEdit, QCompleter,
QAbstractItemView, QHeaderView, QLabel, QAbstractItemView, QHeaderView, QLabel, QSpacerItem, QSizePolicy, QSpinBox,
QDialog, QVBoxLayout, QHBoxLayout, QPushButton, QScrollArea, QWidget QDialog, QVBoxLayout, QHBoxLayout, QPushButton, QScrollArea, QWidget
) )
from PySide2.QtGui import QColor, QBrush, QPalette from PySide2.QtGui import QColor, QBrush, QPalette
from PySide2.QtCore import Qt from PySide2.QtCore import Qt, QSettings
from enum import IntEnum from enum import IntEnum
from generate_debug_vars import type_map from generate_debug_vars import type_map
import time import time
@@ -60,8 +60,65 @@ class FilterDialog(QDialog):
return [cb.text() for cb in self.checkboxes if cb.isChecked()] return [cb.text() for cb in self.checkboxes if cb.isChecked()]
class SetSizeDialog(QDialog):
"""
Диалоговое окно для выбора числового значения (размера).
"""
def __init__(self, parent=None, initial_value=10, min_value=1, max_value=50, title="Укажите размер короткого имени"):
super().__init__(parent)
self.setWindowTitle(title)
self.setFixedSize(320, 120) # Задаем фиксированный размер для аккуратного вида
class var_tableWidget(QTableWidget): # Основной вертикальный макет
main_layout = QVBoxLayout(self)
# Макет для ввода значения
input_layout = QHBoxLayout()
label = QLabel("Количество символов:", self)
self.spin_box = QSpinBox(self)
self.spin_box.setRange(min_value, max_value) # Устанавливаем диапазон допустимых значений
initial_value = parent._shortname_size
self.spin_box.setValue(initial_value) # Устанавливаем начальное значение
self.spin_box.setFocus() # Устанавливаем фокус на поле ввода
input_layout.addWidget(label)
input_layout.addWidget(self.spin_box)
main_layout.addLayout(input_layout)
# Добавляем пустое пространство для лучшего разделения
main_layout.addSpacerItem(QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding))
# Макет для кнопок
btn_layout = QHBoxLayout()
btn_layout.addStretch() # Добавляем растягивающийся элемент, чтобы кнопки были справа
btn_ok = QPushButton("OK")
btn_cancel = QPushButton("Отмена")
btn_layout.addWidget(btn_ok)
btn_layout.addWidget(btn_cancel)
main_layout.addLayout(btn_layout)
# Подключение сигналов к слотам
btn_ok.clicked.connect(self.accept) # При нажатии "OK" диалог закроется со статусом "Accepted"
btn_cancel.clicked.connect(self.reject) # При нажатии "Отмена" - со статусом "Rejected"
def get_selected_size(self):
"""
Возвращает значение, выбранное в QSpinBox.
"""
return self.spin_box.value()
class CtrlScrollComboBox(QComboBox):
def wheelEvent(self, event):
if event.modifiers() & Qt.ControlModifier:
super().wheelEvent(event)
else:
event.ignore()
class VariableTableWidget(QTableWidget):
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(0, 8, parent) super().__init__(0, 8, parent)
# Таблица переменных # Таблица переменных
@@ -77,16 +134,22 @@ class var_tableWidget(QTableWidget):
]) ])
self.setEditTriggers(QAbstractItemView.AllEditTriggers) self.setEditTriggers(QAbstractItemView.AllEditTriggers)
self.var_list = [] self.var_list = []
# Инициализируем QSettings с именем организации и приложения
self.settings = QSettings("SET", "DebugVarEdit_VarTable")
# Восстанавливаем сохранённое состояние, если есть
shortsize = self.settings.value("shortname_size", True, type=int)
self._shortname_size = shortsize
self.type_options = list(dict.fromkeys(type_map.values())) self.type_options = list(dict.fromkeys(type_map.values()))
self.pt_types_all = [t.replace('pt_', '') for t in self.type_options] self.pt_types_all = [t.replace('pt_', '') for t in self.type_options]
self.iq_types_all = ['iq_none', 'iq'] + [f'iq{i}' for i in range(1, 31)] self.iq_types_all = ['iq_none', 'iq'] + [f'iq{i}' for i in range(1, 31)]
# Задаём базовые iq-типы (без префикса 'iq_') # Задаём базовые iq-типы (без префикса 'iq_')
self.iq_types = ['iq_none', 'iq24', 'iq19', 'iq15', 'iq10'] self.iq_types = ['iq_none', 'iq', 'iq10', 'iq15', 'iq19', 'iq24']
# Фильтруем типы из type_map.values() исключая те, что содержат 'arr' или 'ptr' # Фильтруем типы из type_map.values() исключая те, что содержат 'arr' или 'ptr'
self.type_options = [t for t in set(type_map.values()) if 'arr' not in t and 'ptr' not in t] type_options = [t for t in dict.fromkeys(type_map.values()) if 'arr' not in t and 'ptr' not in t and
'struct' not in t and 'union' not in t and '64' not in t]
# Формируем display_type_options без префикса 'pt_' # Формируем display_type_options без префикса 'pt_'
self.pt_types = [t.replace('pt_', '') for t in self.type_options] self.pt_types = [t.replace('pt_', '') for t in type_options]
self._iq_type_filter = list(self.iq_types) # Текущий фильтр iq типов (по умолчанию все) self._iq_type_filter = list(self.iq_types) # Текущий фильтр iq типов (по умолчанию все)
self._pt_type_filter = list(self.pt_types) self._pt_type_filter = list(self.pt_types)
@@ -117,9 +180,6 @@ class var_tableWidget(QTableWidget):
def populate(self, vars_list, structs, on_change_callback): def populate(self, vars_list, structs, on_change_callback):
self.var_list = vars_list self.var_list = vars_list
self.type_options = list(dict.fromkeys(type_map.values()))
self.pt_types = [t.replace('pt_', '') for t in self.type_options]
iq_types = ['iq_none', 'iq'] + [f'iq{i}' for i in range(1, 31)]
# --- ДО: удаляем отображение структур и union-переменных # --- ДО: удаляем отображение структур и union-переменных
for var in vars_list: for var in vars_list:
@@ -168,7 +228,7 @@ class var_tableWidget(QTableWidget):
self.setItem(row, rows.type, origin_item) self.setItem(row, rows.type, origin_item)
# pt_type # pt_type
pt_combo = QComboBox() pt_combo = CtrlScrollComboBox()
pt_combo.addItems(self.pt_types) pt_combo.addItems(self.pt_types)
value = var['pt_type'].replace('pt_', '') value = var['pt_type'].replace('pt_', '')
if value not in self.pt_types: if value not in self.pt_types:
@@ -176,11 +236,10 @@ class var_tableWidget(QTableWidget):
pt_combo.setCurrentText(value) pt_combo.setCurrentText(value)
pt_combo.currentTextChanged.connect(on_change_callback) pt_combo.currentTextChanged.connect(on_change_callback)
pt_combo.setStyleSheet(style_with_padding) pt_combo.setStyleSheet(style_with_padding)
pt_combo.wheelEvent = lambda e: e.ignore()
self.setCellWidget(row, rows.pt_type, pt_combo) self.setCellWidget(row, rows.pt_type, pt_combo)
# iq_type # iq_type
iq_combo = QComboBox() iq_combo = CtrlScrollComboBox()
iq_combo.addItems(self.iq_types) iq_combo.addItems(self.iq_types)
value = var['iq_type'].replace('t_', '') value = var['iq_type'].replace('t_', '')
if value not in self.iq_types: if value not in self.iq_types:
@@ -188,17 +247,15 @@ class var_tableWidget(QTableWidget):
iq_combo.setCurrentText(value) iq_combo.setCurrentText(value)
iq_combo.currentTextChanged.connect(on_change_callback) iq_combo.currentTextChanged.connect(on_change_callback)
iq_combo.setStyleSheet(style_with_padding) iq_combo.setStyleSheet(style_with_padding)
iq_combo.wheelEvent = lambda e: e.ignore()
self.setCellWidget(row, rows.iq_type, iq_combo) self.setCellWidget(row, rows.iq_type, iq_combo)
# return_type # return_type
ret_combo = QComboBox() ret_combo = CtrlScrollComboBox()
ret_combo.addItems(self.iq_types) ret_combo.addItems(self.iq_types)
value = var['return_type'].replace('t_', '') value = var['return_type'].replace('t_', '')
ret_combo.setCurrentText(value) ret_combo.setCurrentText(value)
ret_combo.currentTextChanged.connect(on_change_callback) ret_combo.currentTextChanged.connect(on_change_callback)
ret_combo.setStyleSheet(style_with_padding) ret_combo.setStyleSheet(style_with_padding)
ret_combo.wheelEvent = lambda e: e.ignore()
self.setCellWidget(row, rows.ret_type, ret_combo) self.setCellWidget(row, rows.ret_type, ret_combo)
# short_name # short_name
@@ -230,7 +287,7 @@ class var_tableWidget(QTableWidget):
t3 = time.time() t3 = time.time()
shortname = short_name_edit.text() if short_name_edit else "" shortname = short_name_edit.text() if short_name_edit else ""
long_shortname = len(shortname) > 10 long_shortname = len(shortname) > self._shortname_size
found = name in var_names_set found = name in var_names_set
color = None color = None
@@ -276,7 +333,7 @@ class var_tableWidget(QTableWidget):
def on_header_clicked(self, logicalIndex): def on_header_clicked(self, logicalIndex):
if logicalIndex == rows.pt_type: if logicalIndex == rows.pt_type:
dlg = FilterDialog(self, self.pt_types_all, self._pt_type_filter, "Выберите Pointer Types") dlg = FilterDialog(self, self.pt_types_all, self._pt_type_filter, "Выберите базовые типы")
if dlg.exec_(): if dlg.exec_():
self._pt_type_filter = dlg.get_selected() self._pt_type_filter = dlg.get_selected()
self.update_comboboxes({rows.pt_type: self._pt_type_filter}) self.update_comboboxes({rows.pt_type: self._pt_type_filter})
@@ -292,6 +349,13 @@ class var_tableWidget(QTableWidget):
if dlg.exec_(): if dlg.exec_():
self._ret_type_filter = dlg.get_selected() self._ret_type_filter = dlg.get_selected()
self.update_comboboxes({rows.ret_type: self._ret_type_filter}) self.update_comboboxes({rows.ret_type: self._ret_type_filter})
elif logicalIndex == rows.short_name:
dlg = SetSizeDialog(self)
if dlg.exec_():
self._shortname_size = dlg.get_selected_size()
self.settings.setValue("shortname_size", self._shortname_size)
self.check()
@@ -309,6 +373,7 @@ class var_tableWidget(QTableWidget):
current = combo.currentText() current = combo.currentText()
combo.blockSignals(True) combo.blockSignals(True)
combo.clear() combo.clear()
combo.addItems(allowed_items) combo.addItems(allowed_items)
if current in allowed_items: if current in allowed_items:
combo.setCurrentText(current) combo.setCurrentText(current)

View File

@@ -1,46 +1,68 @@
#include "debug_tools.h" #include "debug_tools.h"
#include "IQmathLib.h"
DebugLowLevel_t debug_ll = DEBUG_LOWLEVEL_INIT; #if !defined(GLOBAL_Q)
#define GLOBAL_Q 16
#endif
static int getDebugVar(DebugVar_t *var, long *int_var, float *float_var);
static int convertDebugVarToIQx(DebugVar_t *var, long *ret_var); DebugLowLevel_t debug_ll = DEBUG_LOWLEVEL_INIT; ///< Ñòðóêòóðà îòëàäêè íèæíåãî óðîâíÿ (èíèöèàëèçàöèÿ)
static int getDebugVar(DebugVar_t *var, int32_t *int_var, float *float_var);
static int convertDebugVarToIQx(DebugVar_t *var, int32_t *ret_var);
///////////////////////////----EXAPLE-----////////////////////////////// ///////////////////////////----EXAPLE-----//////////////////////////////
long var_numb = 1; int var_numb = 1; ///< Ïðèìåð ïåðåìåííîé äëÿ îòëàäêè
DebugVarName_t var_name; DebugVarName_t var_name; ///< Èìÿ ïåðåìåííîé
long return_var; int32_t return_var; ///< Ïåðåìåííàÿ äëÿ âîçâðàòà ðåçóëüòàòà
long return_ll_var; int32_t return_ll_var; ///< Âîçâðàùàåìîå çíà÷åíèå ñ íèæíåãî óðîâíÿ
int result; int result; ///< Ïåðåìåííàÿ ðåçóëüòàòà
char ext_date[] = {7, 233, 11, 07, 16, 50}; DateTime_t ext_date = {2025, 11, 07, 16, 50}; ///< Ïðèìåð âíåøíåé äàòû ñáîðêè
/**
* @brief Ïðèìåð èñïîëüçîâàíèÿ ôóíêöèé îòëàäêè.
* @details Äåìîíñòðàöèîííàÿ ôóíêöèÿ äëÿ ðàáîòû ñ ïåðåìåííûìè îòëàäêè.
*/
void Debug_Test_Example(void) void Debug_Test_Example(void)
{ {
result = Debug_ReadVar(var_numb, &return_var); result = Debug_ReadVar(var_numb, &return_var);
result = Debug_ReadVarName(var_numb, var_name); result = Debug_ReadVarName(var_numb, var_name);
if(Debug_LowLevel_Initialize(ext_date) == 0) if(Debug_LowLevel_Initialize(&ext_date) == 0)
result = Debug_LowLevel_ReadVar(&return_ll_var); result = Debug_LowLevel_ReadVar(&return_ll_var);
} }
///////////////////////////----PUBLIC-----////////////////////////////// ///////////////////////////----PUBLIC-----//////////////////////////////
int Debug_ReadVar(int var_ind, long *return_long)
/**
* @brief ×èòàåò ïåðåìåííóþ ïî èíäåêñó.
* @param var_ind èíäåêñ ïåðåìåííîé.
* @param return_32b óêàçàòåëü äëÿ âîçâðàòà ðåçóëüòàòà.
* @return int 0: óñïåõ, 1: îøèáêà.
* @details Èñïîëüçóåòñÿ äëÿ ÷òåíèÿ çíà÷åíèé ïåðåìåííûõ ïî èõ èíäåêñó.
*/
int Debug_ReadVar(int var_ind, int32_t *return_32b)
{ {
if(return_long == NULL) if(return_32b == NULL)
return 1; return 1;
long tmp_var; int32_t tmp_var;
if (var_ind >= DebugVar_Qnt) if (var_ind >= DebugVar_Qnt)
return 1; return 1;
if((dbg_vars[var_numb].ptr_type == pt_struct) || (dbg_vars[var_numb].ptr_type == pt_union) || if((dbg_vars[var_ind].ptr_type == pt_struct) || (dbg_vars[var_ind].ptr_type == pt_union) ||
(dbg_vars[var_numb].ptr_type == pt_unknown)) (dbg_vars[var_ind].ptr_type == pt_unknown))
return 1; return 1;
return convertDebugVarToIQx(&dbg_vars[var_ind], return_32b);
return convertDebugVarToIQx(&dbg_vars[var_numb], return_long);
} }
/**
* @brief ×èòàåò èìÿ ïåðåìåííîé ïî èíäåêñó.
* @param var_ind èíäåêñ ïåðåìåííîé.
* @param name_ptr óêàçàòåëü íà áóôåð èìåíè (DebugVarName_t).
* @return int 0: óñïåõ, 1: îøèáêà.
* @details Êîïèðóåò èìÿ ïåðåìåííîé â ïðåäîñòàâëåííûé áóôåð.
*/
int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr) int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr)
{ {
if(name_ptr == NULL) if(name_ptr == NULL)
@@ -51,29 +73,34 @@ int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr)
int i; int i;
// Êîïèðîâàíèå ñ çàùèòîé îò ïåðåïîëíåíèÿ è ÿâíîé îñòàíîâêîé ïî '\0' // Êîïèðîâàíèå ñ çàùèòîé îò ïåðåïîëíåíèÿ è ÿâíîé îñòàíîâêîé ïî '\0'
for (i = 0; i < sizeof(dbg_vars[var_numb].name); i++) for (i = 0; i < sizeof(dbg_vars[var_ind].name); i++)
{ {
name_ptr[i] = dbg_vars[var_numb].name[i]; name_ptr[i] = dbg_vars[var_ind].name[i];
if (dbg_vars[var_numb].name[i] == '\0') if (dbg_vars[var_ind].name[i] == '\0')
break; break;
} }
// Ãàðàíòèðîâàííîå çàâåðøåíèå ñòðîêè (íà ñëó÷àé, åñëè â var->name íå áûëî '\0') // Ãàðàíòèðîâàííîå çàâåðøåíèå ñòðîêè (íà ñëó÷àé, åñëè â var->name íå áûëî '\0')
name_ptr[sizeof(dbg_vars[var_numb].name) - 1] = '\0'; name_ptr[sizeof(dbg_vars[var_ind].name) - 1] = '\0';
return 0; return 0;
} }
/**
int Debug_LowLevel_ReadVar(long *return_long) * @brief ×èòàåò çíà÷åíèå ïåðåìåííîé îòëàäêè ñ íèæíåãî óðîâíÿ.
* @param return_32b óêàçàòåëü íà ïåðåìåííóþ, êóäà çàïèñûâàåòñÿ ðåçóëüòàò.
* @return int 0: óñïåõ, 1: îøèáêà, 2: íåäîïóñòèìûé àäðåñ.
* @details Èñïîëüçóåò àäðåññ, ïåðåäàâàåìûé ñ òåðìèíàëêè äëÿ ïîëó÷åíèÿ çíà÷åíèÿ.
*/
int Debug_LowLevel_ReadVar(int32_t *return_32b)
{ {
if (return_long == NULL) if (return_32b == NULL)
return 1; return 1;
if (debug_ll.isVerified == 0) if (debug_ll.isVerified == 0)
return 1; return 1;
char *addr = debug_ll.dbg_var.Ptr; uint8_t *addr = debug_ll.dbg_var.Ptr;
unsigned long addr_val = (unsigned long)addr; uint32_t addr_val = (uint32_t)addr;
// Ðàçðåø¸ííûå äèàïàçîíû ïàìÿòè (èç .cmd ôàéëà) // Ðàçðåø¸ííûå äèàïàçîíû ïàìÿòè (èç .cmd ôàéëà)
if (!( if (!(
@@ -89,32 +116,28 @@ int Debug_LowLevel_ReadVar(long *return_long)
return 2; // Çàïðåù¸ííûé àäðåñ — íåëüçÿ ÷èòàòü return 2; // Çàïðåù¸ííûé àäðåñ — íåëüçÿ ÷èòàòü
} }
return convertDebugVarToIQx(&debug_ll.dbg_var, return_long); return convertDebugVarToIQx(&debug_ll.dbg_var, return_32b);
;
} }
/**
int Debug_LowLevel_Initialize(const char* external_date) * @brief Èíèöèàëèçàöèÿ îòëàäêè íà íèæíåì óðîâíå ïî äàòå ñáîðêè.
* @param external_date ñòðóêòóðà ñ äàòîé DateTime_t
* @return int 0: ñîâïàäàåò, 1: íå ñîâïàäàåò, -1: îøèáêà.
* @details Ñðàâíèâàåò äàòó êîìïèëÿöèè ñ çàïðàøèâàåìîé è èíèöèàëèçèðóåò îòëàäî÷íóþ ïåðåìåííóþ.
*/
int Debug_LowLevel_Initialize(DateTime_t* external_date)
{ {
if (external_date == NULL) { if (external_date == NULL) {
return -1; return -1;
} }
// Ïðåîáðàçóåì external_date â ñòðóêòóðó
DateTime_t ext;
ext.year = (external_date[0] << 8) | external_date[1];
ext.day = external_date[2];
ext.month = external_date[3];
ext.hour = external_date[4];
ext.minute = external_date[5];
// Ñðàâíåíèå âñåõ ïîëåé // Ñðàâíåíèå âñåõ ïîëåé
if (ext.year == debug_ll.build_date.year && if (external_date->year == debug_ll.build_date.year &&
ext.month == debug_ll.build_date.month && external_date->month == debug_ll.build_date.month &&
ext.day == debug_ll.build_date.day && external_date->day == debug_ll.build_date.day &&
ext.hour == debug_ll.build_date.hour && external_date->hour == debug_ll.build_date.hour &&
ext.minute == debug_ll.build_date.minute) external_date->minute == debug_ll.build_date.minute)
{ {
debug_ll.isVerified = 1; debug_ll.isVerified = 1;
return 0; // Ñîâïàëî return 0; // Ñîâïàëî
@@ -129,6 +152,12 @@ int Debug_LowLevel_Initialize(const char* external_date)
/////////////////////----INTERNAL FUNCTIONS-----//////////////////////// /////////////////////----INTERNAL FUNCTIONS-----////////////////////////
/**
* @brief Ïðåîáðàçóåò òèï IQ ïåðåìåííîé â ÷èñëî áèòîâ äëÿ ñäâèãà(Q-ôàêòîð).
* @param t òèï IQ (ïåðå÷èñëåíèå DebugVarIQType_t).
* @return int Q-ôàêòîð (íàïðèìåð, 24), 0: åñëè t_iq_none, -1: îøèáêà.
* @details Ñîïîñòàâëÿåò òèï IQ ïåðåìåííîé ñ ñîîòâåòñòâóþùèì Q-çíà÷åíèåì.
*/
static int iqTypeToQ(DebugVarIQType_t t) static int iqTypeToQ(DebugVarIQType_t t)
{ {
if (t == t_iq_none) if (t == t_iq_none)
@@ -141,9 +170,16 @@ static int iqTypeToQ(DebugVarIQType_t t)
return -1; // îøèáêà return -1; // îøèáêà
} }
static int convertDebugVarToIQx(DebugVar_t *var, long *ret_var) /**
* @brief Ïðåîáðàçóåò ïåðåìåííóþ îòëàäêè â IQ ôîðìàò.
* @param var óêàçàòåëü íà ïåðåìåííóþ îòëàäêè.
* @param ret_var óêàçàòåëü äëÿ âîçâðàòà çíà÷åíèÿ â ôîðìàòå 32 áèòà.
* @return int 0: óñïåõ, 1: îøèáêà ÷òåíèÿ, 2: íåïðàâèëüíûé ôîðìàò, 3: ïåðåïîëíåíèå.
* @details Îïðåäåëÿåò ôîðìàò IQ ïåðåìåííîé, êîíâåðòèðóåò å¸ â 32b ñ ó÷¸òîì ìàñøòàáà.
*/
static int convertDebugVarToIQx(DebugVar_t *var, int32_t *ret_var)
{ {
long iq_numb, iq_united, iq_final; int32_t iq_numb, iq_united, iq_final;
float float_numb; float float_numb;
if(getDebugVar(var, &iq_numb, &float_numb) != 0) if(getDebugVar(var, &iq_numb, &float_numb) != 0)
@@ -155,30 +191,30 @@ static int convertDebugVarToIQx(DebugVar_t *var, long *ret_var)
if (src_q < 0 || dst_q < 0) if (src_q < 0 || dst_q < 0)
return 2; // íåïðàâèëüíûé ôîðìàò return 2; // íåïðàâèëüíûé ôîðìàò
long long iq_united64 = 0; int64_t iq_united64 = 0;
long long iq_final64 = 0; int64_t iq_final64 = 0;
// Êîíâåðòàöèÿ ê GLOBAL_Q (64-áèò) // Êîíâåðòàöèÿ ê GLOBAL_Q (64-áèò)
if (var->iq_type == t_iq_none) { if (var->iq_type == t_iq_none) {
if (var->ptr_type == pt_float) { if (var->ptr_type == pt_float) {
// float_numb óìíîæàåì íà 2^GLOBAL_Q (2^24=16777216) // float_numb óìíîæàåì íà 2^GLOBAL_Q
// Ðåçóëüòàò ïðèâîäèì ê long long // Ðåçóëüòàò ïðèâîäèì ê 64 áèòà
iq_united64 = (long long)(float_numb * 16777216.0f); iq_united64 = (int64_t)(float_numb * (1 << GLOBAL_Q));
} else { } else {
iq_united64 = ((long long)iq_numb) << GLOBAL_Q; iq_united64 = ((int64_t)iq_numb) << GLOBAL_Q;
} }
} else { } else {
int shift = GLOBAL_Q - src_q; int shift = GLOBAL_Q - src_q;
if (shift >= 0) if (shift >= 0)
iq_united64 = ((long long)iq_numb) << shift; iq_united64 = ((int64_t)iq_numb) << shift;
else else
iq_united64 = ((long long)iq_numb) >> (-shift); iq_united64 = ((int64_t)iq_numb) >> (-shift);
} }
// Êîíâåðòàöèÿ èç GLOBAL_Q â öåëåâîé IQ (64-áèò) // Êîíâåðòàöèÿ èç GLOBAL_Q â öåëåâîé IQ (64-áèò)
if (var->return_type == t_iq_none) { if (var->return_type == t_iq_none) {
// Âîçâðàùàåì öåëîå, îòáðîñèâ äðîáíóþ ÷àñòü // Âîçâðàùàåì öåëîå, îòáðîñèâ äðîáíóþ ÷àñòü
*ret_var = (long)(iq_united64 >> GLOBAL_Q); *ret_var = (uint32_t)(iq_united64 >> GLOBAL_Q);
} else { } else {
int shift = dst_q - GLOBAL_Q; int shift = dst_q - GLOBAL_Q;
if (shift >= 0) if (shift >= 0)
@@ -187,54 +223,65 @@ static int convertDebugVarToIQx(DebugVar_t *var, long *ret_var)
iq_final64 = iq_united64 >> (-shift); iq_final64 = iq_united64 >> (-shift);
// Ïðîâåðÿåì ïåðåïîëíåíèå int32_t // Ïðîâåðÿåì ïåðåïîëíåíèå int32_t
if (iq_final64 > LONG_MAX || iq_final64 < LONG_MIN) if (iq_final64 > 2147483647 || iq_final64 < -2147483648)
return 3; // ïåðåïîëíåíèå return 3; // ïåðåïîëíåíèå
*ret_var = (long)iq_final64; *ret_var = (uint32_t)iq_final64;
} }
return 0; return 0;
} }
static int getDebugVar(DebugVar_t *var, long *int_var, float *float_var) /**
* @brief Ïðî÷èòàòü çíà÷åíèå ïåðåìåííîé îòëàäêè.
* @param var óêàçàòåëü íà ñòðóêòóðó DebugVar.
* @param int_var óêàçàòåëü íà ïåðåìåííóþ òèïà 32 áèòà äëÿ âîçâðàòà öåëî÷èñëåííîãî çíà÷åíèÿ.
* @param float_var óêàçàòåëü íà ïåðåìåííóþ òèïà float äëÿ âîçâðàòà çíà÷åíèÿ ñ ïëàâàþùåé òî÷êîé.
* @return int 0: óñïåõ, 1: îøèáêà óêàçàòåëåé èëè íåïîääåðæèâàåìûé òèï, 3/4: îøèáêà âûðàâíèâàíèÿ.
* @details  çàâèñèìîñòè îò òèïà ïåðåìåííîé ñ÷èòûâàåò å¸ çíà÷åíèå è ñîõðàíÿåò â ñîîòâåòñòâóþùåì óêàçàòåëå.
*/
static int getDebugVar(DebugVar_t *var, int32_t *int_var, float *float_var)
{ {
if (!var || !int_var || !float_var || !var->Ptr) if (!var || !int_var || !float_var || !var->Ptr)
return 1; // îøèáêà: null óêàçàòåëü return 1; // îøèáêà: null óêàçàòåëü
char *addr = var->Ptr; uint8_t *addr = var->Ptr;
unsigned long addr_val = (unsigned long)addr; uint32_t addr_val = (uint32_t)addr;
switch (var->ptr_type) switch (var->ptr_type)
{ {
case pt_int8: // 8 áèò case pt_int8: // 8 áèò
if ((addr_val & ALIGN_8BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 1; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile int8_t *)addr);
case pt_uint8: case pt_uint8:
// âûðàâíèâàíèå íå íóæíî äëÿ 8 áèò if ((addr_val & ALIGN_8BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
*int_var = *((volatile char *)addr); return 1; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile uint8_t *)addr);
break; break;
case pt_int16: // 16 áèò (int) case pt_int16: // 16 áèò (int)
if ((addr_val & ALIGN_16BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 2; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile int16_t *)addr);
case pt_uint16: case pt_uint16:
*int_var = *((volatile int *)addr); if ((addr_val & ALIGN_16BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 2; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile uint16_t *)addr);
break; break;
case pt_int32: // 32 áèò (long) case pt_int32: // 32 áèò
case pt_uint32: if ((addr_val & ALIGN_32BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
if (addr_val & 0x1) // ïðîâåðÿåì âûðàâíèâàíèå ïî 2 ñëîâàì (4 áàéòà)
return 3; // îøèáêà âûðàâíèâàíèÿ return 3; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile long *)addr); *int_var = *((volatile int32_t *)addr);
case pt_uint32:
if ((addr_val & ALIGN_32BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 3; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile uint32_t *)addr);
break; break;
// case pt_int64: // 64 áèò (long long)
// case pt_uint64:
// if (addr_val & 0x3) // ïðîâåðêà âûðàâíèâàíèÿ ïî 4 ñëîâàì (8 áàéòàì)
// return 2; // îøèáêà âûðàâíèâàíèÿ
// // Òóò ïðîñòî ÷èòàåì, íî long long ìîæåò íå ïîìåñòèòüñÿ â *int_var
// // Ìîæíî çàìåíèòü ëîãèêó ïîä 64-áèòíîå ÷òåíèå ïðè íåîáõîäèìîñòè
// *int_var = *((volatile long long *)addr);
// break;
case pt_float: // float (4 áàéòà) case pt_float: // float (4 áàéòà)
if (addr_val & 0x1) // ïðîâåðêà âûðàâíèâàíèÿ ïî 2 ñëîâàì if ((addr_val & ALIGN_FLOAT) != 0) // ïðîâåðêà âûðàâíèâàíèÿ
return 4; // îøèáêà âûðàâíèâàíèÿ return 4; // îøèáêà âûðàâíèâàíèÿ
*float_var = *((volatile float *)addr); *float_var = *((volatile float *)addr);
break; break;
@@ -259,211 +306,3 @@ static int getDebugVar(DebugVar_t *var, long *int_var, float *float_var)
return 0; // óñïåõ return 0; // óñïåõ
} }
///////////// OUTDATE ////////////////
//
// // ïðèâåäåíèå ê îäíîìó IQ
// switch(var->iq_type)
// {
// case t_iq_none:
// if(var->ptr_type == pt_float)
// {
// iq_united = _IQ(float_numb);
// }
// else
// {
// iq_united = _IQ(iq_numb);
// }
// break;
// case t_iq1:
// iq_united = _IQ1toIQ(iq_numb);
// break;
// case t_iq2:
// iq_united = _IQ2toIQ(iq_numb);
// break;
// case t_iq3:
// iq_united = _IQ3toIQ(iq_numb);
// break;
// case t_iq4:
// iq_united = _IQ4toIQ(iq_numb);
// break;
// case t_iq5:
// iq_united = _IQ5toIQ(iq_numb);
// break;
// case t_iq6:
// iq_united = _IQ6toIQ(iq_numb);
// break;
// case t_iq7:
// iq_united = _IQ7toIQ(iq_numb);
// break;
// case t_iq8:
// iq_united = _IQ8toIQ(iq_numb);
// break;
// case t_iq9:
// iq_united = _IQ9toIQ(iq_numb);
// break;
// case t_iq10:
// iq_united = _IQ10toIQ(iq_numb);
// break;
// case t_iq11:
// iq_united = _IQ11toIQ(iq_numb);
// break;
// case t_iq12:
// iq_united = _IQ12toIQ(iq_numb);
// break;
// case t_iq13:
// iq_united = _IQ13toIQ(iq_numb);
// break;
// case t_iq14:
// iq_united = _IQ14toIQ(iq_numb);
// break;
// case t_iq15:
// iq_united = _IQ15toIQ(iq_numb);
// break;
// case t_iq16:
// iq_united = _IQ16toIQ(iq_numb);
// break;
// case t_iq17:
// iq_united = _IQ17toIQ(iq_numb);
// break;
// case t_iq18:
// iq_united = _IQ18toIQ(iq_numb);
// break;
// case t_iq19:
// iq_united = _IQ19toIQ(iq_numb);
// break;
// case t_iq20:
// iq_united = _IQ20toIQ(iq_numb);
// break;
// case t_iq21:
// iq_united = _IQ21toIQ(iq_numb);
// break;
// case t_iq22:
// iq_united = _IQ22toIQ(iq_numb);
// break;
// case t_iq23:
// iq_united = _IQ23toIQ(iq_numb);
// break;
// case t_iq24:
// iq_united = _IQ24toIQ(iq_numb);
// break;
// case t_iq25:
// iq_united = _IQ25toIQ(iq_numb);
// break;
// case t_iq26:
// iq_united = _IQ26toIQ(iq_numb);
// break;
// case t_iq27:
// iq_united = _IQ27toIQ(iq_numb);
// break;
// case t_iq28:
// iq_united = _IQ28toIQ(iq_numb);
// break;
// case t_iq29:
// iq_united = _IQ29toIQ(iq_numb);
// break;
// case t_iq30:
// iq_united = _IQ30toIQ(iq_numb);
// break;
// }
//
// // ïðèâåäåíèå îáùåãî IQ ê çàïðàøèâàåìîìó
// switch(var->return_type)
// {
// case t_iq_none:
// iq_final = (long)_IQtoF(iq_united);
// break;
// case t_iq1:
// iq_final = _IQtoIQ1(iq_united);
// break;
// case t_iq2:
// iq_final = _IQtoIQ2(iq_united);
// break;
// case t_iq3:
// iq_final = _IQtoIQ3(iq_united);
// break;
// case t_iq4:
// iq_final = _IQtoIQ4(iq_united);
// break;
// case t_iq5:
// iq_final = _IQtoIQ5(iq_united);
// break;
// case t_iq6:
// iq_final = _IQtoIQ6(iq_united);
// break;
// case t_iq7:
// iq_final = _IQtoIQ7(iq_united);
// break;
// case t_iq8:
// iq_final = _IQtoIQ8(iq_united);
// break;
// case t_iq9:
// iq_final = _IQtoIQ9(iq_united);
// break;
// case t_iq10:
// iq_final = _IQtoIQ10(iq_united);
// break;
// case t_iq11:
// iq_final = _IQtoIQ11(iq_united);
// break;
// case t_iq12:
// iq_final = _IQtoIQ12(iq_united);
// break;
// case t_iq13:
// iq_final = _IQtoIQ13(iq_united);
// break;
// case t_iq14:
// iq_final = _IQtoIQ14(iq_united);
// break;
// case t_iq15:
// iq_final = _IQtoIQ15(iq_united);
// break;
// case t_iq16:
// iq_final = _IQtoIQ16(iq_united);
// break;
// case t_iq17:
// iq_final = _IQtoIQ17(iq_united);
// break;
// case t_iq18:
// iq_final = _IQtoIQ18(iq_united);
// break;
// case t_iq19:
// iq_final = _IQtoIQ19(iq_united);
// break;
// case t_iq20:
// iq_final = _IQtoIQ20(iq_united);
// break;
// case t_iq21:
// iq_final = _IQtoIQ21(iq_united);
// break;
// case t_iq22:
// iq_final = _IQtoIQ22(iq_united);
// break;
// case t_iq23:
// iq_final = _IQtoIQ23(iq_united);
// break;
// case t_iq24:
// iq_final = _IQtoIQ24(iq_united);
// break;
// case t_iq25:
// iq_final = _IQtoIQ25(iq_united);
// break;
// case t_iq26:
// iq_final = _IQtoIQ26(iq_united);
// break;
// case t_iq27:
// iq_final = _IQtoIQ27(iq_united);
// break;
// case t_iq28:
// iq_final = _IQtoIQ28(iq_united);
// break;
// case t_iq29:
// iq_final = _IQtoIQ29(iq_united);
// break;
// case t_iq30:
// iq_final = _IQtoIQ30(iq_united);
// break;
// }
// *ret_var = iq_final;

View File

@@ -1,8 +1,40 @@
#ifndef DEBUG_TOOLS #ifndef DEBUG_TOOLS
#define DEBUG_TOOLS #define DEBUG_TOOLS
#include "IQmathLib.h" #include <stdint.h>
#include "DSP281x_Device.h" #include <limits.h>
#if UINT8_MAX // Åñëè åñòü òèï 8 áèò - çí÷à÷èò àäðåñàöèÿ ïî 8 áèò
#define ALIGN_8BIT 0x0 ///< Âûðàâíèâàíèå áåç îãðàíè÷åíèé (ëþáîé àäðåñ)
#define ALIGN_16BIT 0x1 ///< Âûðàâíèâàíèå: àäðåñ äîëæåí áûòü êðàòåí 2 (addr & 0x1 == 0)
#define ALIGN_32BIT 0x3 ///< Âûðàâíèâàíèå: àäðåñ äîëæåí áûòü êðàòåí 4 (addr & 0x3 == 0)
#define ALIGN_64BIT 0x7 ///< Âûðàâíèâàíèå: àäðåñ äîëæåí áûòü êðàòåí 8 (addr & 0x7 == 0)
#define ALIGN_FLOAT ALIGN_32BIT
#else // Åñëè íåò òèïà 8 áèò - çíà÷èò àäðåñàöèÿ ïî 16 áèò
#define ALIGN_8BIT 0x0 ///< Âûðàâíèâàíèå áåç îãðàíè÷åíèé (ëþáîé àäðåñ)
#define ALIGN_16BIT 0x0 ///< Âûðàâíèâàíèå áåç îãðàíè÷åíèé (ëþáîé àäðåñ)
#define ALIGN_32BIT 0x1 ///< Âûðàâíèâàíèå: àäðåñ äîëæåí áûòü êðàòåí 4 (addr & 0x1 == 0)
#define ALIGN_64BIT 0x3 ///< Âûðàâíèâàíèå: àäðåñ äîëæåí áûòü êðàòåí 8 (addr & 0x3 == 0)
#define ALIGN_FLOAT ALIGN_32BIT
#endif //STM32/TMS32
#if !UINT8_MAX
typedef unsigned char uint8_t;
typedef signed char int8_t;
#endif
#if !defined(NULL)
#define NULL 0
#endif
/**
* @brief Òèï äàííûõ, íà êîòîðûé óêàçûâàåò óêàçàòåëü ïåðåìåííîé îòëàäêè.
*/
typedef enum typedef enum
{ {
pt_unknown, // unknown pt_unknown, // unknown
@@ -14,7 +46,7 @@ typedef enum
pt_uint16, // unsigned int pt_uint16, // unsigned int
pt_uint32, // unsigned long pt_uint32, // unsigned long
pt_uint64, // unsigned long pt_uint64, // unsigned long
pt_float, // float pt_float, // floatf
pt_struct, // struct pt_struct, // struct
pt_union, // struct pt_union, // struct
// pt_ptr_int8, // signed char* // pt_ptr_int8, // signed char*
@@ -31,6 +63,9 @@ typedef enum
// pt_arr_uint32, // unsigned long[] // pt_arr_uint32, // unsigned long[]
}DebugVarPtrType_t; }DebugVarPtrType_t;
/**
* @brief Òèïû IQ-ïðåäñòàâëåíèÿ ïåðåìåííîé îòëàäêè.
*/
typedef enum typedef enum
{ {
t_iq_none, t_iq_none,
@@ -67,45 +102,67 @@ typedef enum
t_iq30 t_iq30
}DebugVarIQType_t; }DebugVarIQType_t;
typedef char DebugVarName_t[11]; typedef char DebugVarName_t[11]; ///< Èìÿ ïåðåìåííîé îòëàäêè (äî 10 ñèìâîëîâ + \0)
/**
* @brief Îïèñàíèå ïåðåìåííîé îòëàäêè.
*/
typedef struct typedef struct
{ {
char* Ptr; uint8_t* Ptr; ///< Óêàçàòåëü íà çíà÷åíèå ïåðåìåííîé
DebugVarPtrType_t ptr_type; DebugVarPtrType_t ptr_type; ///< Òèï çíà÷åíèÿ
DebugVarIQType_t iq_type; DebugVarIQType_t iq_type; ///< Òèï IQ ïåðåìåííîé (åñëè åñòü)
DebugVarIQType_t return_type; DebugVarIQType_t return_type;///< Òèï IQ âîçâðàùàåìîãî çíà÷åíèÿ
DebugVarName_t name; DebugVarName_t name; ///< Èìÿ ïåðåìåííîé
}DebugVar_t; } DebugVar_t;
typedef long DebugValue_t;
/**
* @brief Ñòðóêòóðà äàòû è âðåìåíè.
*/
typedef struct { typedef struct {
int year; uint16_t year; ///< Ãîä (íàïðèìåð, 2025)
char month; uint8_t month; ///< Ìåñÿö (1-12)
char day; uint8_t day; ///< Äåíü (1-31)
char hour; uint8_t hour; ///< ×àñû (0-23)
char minute; uint8_t minute; ///< Ìèíóòû (0-59)
} DateTime_t; } DateTime_t;
/**
* @brief Ñòðóêòóðà íèæíåãî óðîâíÿ îòëàäêè.
*/
typedef struct typedef struct
{ {
DateTime_t build_date; DateTime_t build_date; ///< Äàòà ñáîðêè
unsigned int isVerified; unsigned int isVerified; ///< Ôëàã èíèöèàëèçàöèè íèçêîóðîâíåíîé îòëàäêè (0 — íåò, 1 — óñïåøíî)
DebugVar_t dbg_var; DebugVar_t dbg_var; ///< Ïåðåìåííàÿ äëÿ îòëàäêè
}DebugLowLevel_t; }DebugLowLevel_t;
extern DebugLowLevel_t debug_ll; extern DebugLowLevel_t debug_ll; ///< Ãëîáàëüíûé ýêçåìïëÿð îòëàäêè íèæíåãî óðîâíÿ
/** @brief Ìàêðîñ èíèöèàëèçàöèè äàòû */
#define DATE_INIT {BUILD_YEAR, BUILD_MONTH, BUILD_DATA, BUILD_HOURS, BUILD_MINUTES} #define DATE_INIT {BUILD_YEAR, BUILD_MONTH, BUILD_DATA, BUILD_HOURS, BUILD_MINUTES}
/** @brief Ìàêðîñ èíèöèàëèçàöèè ïåðåìåííîé îòëàäêè */
#define DEBUG_VAR_INIT {0, pt_uint16, t_iq_none, t_iq_none, "\0"} #define DEBUG_VAR_INIT {0, pt_uint16, t_iq_none, t_iq_none, "\0"}
/** @brief Ìàêðîñ èíèöèàëèçàöèè íèæíåãî óðîâíÿ îòëàäêè */
#define DEBUG_LOWLEVEL_INIT {DATE_INIT, 0, DEBUG_VAR_INIT} #define DEBUG_LOWLEVEL_INIT {DATE_INIT, 0, DEBUG_VAR_INIT}
extern int DebugVar_Qnt; extern int DebugVar_Qnt; ///< Êîëè÷åñòâî ïåðåìåííûõ îòëàäêè
extern DebugVar_t dbg_vars[]; extern DebugVar_t dbg_vars[]; ///< Ìàññèâ ïåðåìåííûõ îòëàäêè
/* Ïðèìåð èñïîëüçîâàíèÿ îòëàäêè */
void Debug_Test_Example(void); void Debug_Test_Example(void);
int Debug_ReadVar(int var_ind, long *return_long); /* ×èòàåò çíà÷åíèå ïåðåìåííîé ïî èíäåêñó */
int Debug_ReadVar(int var_ind, int32_t *return_long);
/* ×èòàåò èìÿ ïåðåìåííîé ïî èíäåêñó */
int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr); int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr);
int Debug_LowLevel_ReadVar(long *return_long); /* ×èòàåò çíà÷åíèå ïåðåìåííîé ñ íèæíåãî óðîâíÿ */
int Debug_LowLevel_Initialize(const char* external_date); int Debug_LowLevel_ReadVar(int32_t *return_long);
/* Èíèöèàëèçèðóåò îòëàäêó íèæíåãî óðîâíÿ */
int Debug_LowLevel_Initialize(DateTime_t *external_date);
#endif //DEBUG_TOOLS #endif //DEBUG_TOOLS

View File

@@ -1,341 +0,0 @@
// Ýòîò ôàéë ñãåíåðèðîâàí àâòîìàòè÷åñêè
#include "debug_tools.h"
// Èíêëþäû äëÿ äîñòóïà ê ïåðåìåííûì
#include "vector.h"
#include "errors.h"
#include "RS_Functions_modbus.h"
#include "xp_project.h"
#include "adc_tools.h"
#include "pwm_vector_regul.h"
#include "log_can.h"
#include "f281xpwm.h"
#include "v_pwm24.h"
#include "xp_write_xpwm_time.h"
#include "dq_to_alphabeta_cos.h"
#include "teta_calc.h"
#include "rotation_speed.h"
#include "detect_phase_break2.h"
#include "RS_Functions.h"
#include "Spartan2E_Functions.h"
#include "xp_controller.h"
#include "xp_rotation_sensor.h"
#include "x_serial_bus.h"
#include "x_parallel_bus.h"
#include "xPeriphSP6_loader.h"
#include "log_params.h"
#include "CAN_Setup.h"
#include "CRC_Functions.h"
#include "log_to_memory.h"
#include "global_time.h"
#include "svgen_dq.h"
#include "pid_reg3.h"
#include "IQmathLib.h"
#include "doors_control.h"
#include "isolation.h"
#include "main22220.h"
#include "optical_bus.h"
#include "alarm_log_can.h"
#include "bender.h"
#include "can_watercool.h"
#include "detect_phase_break.h"
#include "modbus_read_table.h"
#include "rmp_cntl_my1.h"
// Ýêñòåðíû äëÿ äîñòóïà ê ïåðåìåííûì
extern int ADC0finishAddr;
extern int ADC0startAddr;
extern int ADC1finishAddr;
extern int ADC1startAddr;
extern int ADC2finishAddr;
extern int ADC2startAddr;
extern int ADC_f[2][16];
extern int ADC_sf[2][16];
extern int ADDR_FOR_ALL;
extern int BUSY;
extern BENDER Bender[2];
extern int CAN_answer_wait[32];
extern int CAN_count_cycle_input_units[8];
extern int CAN_no_answer[32];
extern int CAN_refresh_cicle[32];
extern int CAN_request_sent[32];
extern int CAN_timeout[32];
extern int CAN_timeout_cicle[32];
extern int CNTRL_ADDR;
extern const int CNTRL_ADDR_UNIVERSAL;
extern _iq CONST_15;
extern _iq CONST_23;
extern int CanOpenUnites[30];
extern int CanTimeOutErrorTR;
extern XControll_reg Controll;
extern int Dpwm;
extern int Dpwm2;
extern int Dpwm4;
extern int EvaTimer1InterruptCount;
extern int EvaTimer2InterruptCount;
extern int EvbTimer3InterruptCount;
extern int EvbTimer4InterruptCount;
extern int Fpwm;
extern int IN0finishAddr;
extern int IN0startAddr;
extern int IN1finishAddr;
extern int IN1startAddr;
extern int IN2finishAddr;
extern int IN2startAddr;
extern float IQ_OUT_NOM;
extern long I_OUT_1_6_NOMINAL_IQ;
extern long I_OUT_1_8_NOMINAL_IQ;
extern float I_OUT_NOMINAL;
extern long I_OUT_NOMINAL_IQ;
extern long I_ZPT_NOMINAL_IQ;
extern _iq Id_out_max_full;
extern _iq Id_out_max_low_speed;
extern _iq Iq_out_max;
extern _iq Iq_out_nom;
extern const unsigned long K_LEM_ADC[20];
extern float KmodTerm;
extern int ROTfinishAddr;
extern unsigned int RS_Len[70];
extern const unsigned int R_ADC[20];
extern int RotPlaneStartAddr;
extern _iq SQRT_32;
extern int Unites[8][128];
extern int VAR_FREQ_PWM_XTICS;
extern int VAR_PERIOD_MAX_XTICS;
extern int VAR_PERIOD_MIN_BR_XTICS;
extern int VAR_PERIOD_MIN_XTICS;
extern int Zpwm;
extern WINDING a;
extern volatile AddrToSent addrToSent;
extern unsigned int adr_read_from_modbus3;
extern ALARM_LOG_CAN alarm_log_can;
extern ALARM_LOG_CAN_SETUP alarm_log_can_setup;
extern ANALOG_VALUE analog;
extern int ar_sa_all[3][6][4][7];
extern _iq ar_tph[7];
extern int block_size_counter_fast;
extern int block_size_counter_slow;
extern _iq break_result_1;
extern _iq break_result_2;
extern _iq break_result_3;
extern _iq break_result_4;
extern Byte byte;
extern long c_s;
extern int calibration1;
extern int calibration2;
extern test_functions callfunc;
extern CANOPEN_CAN_SETUP canopen_can_setup;
extern unsigned int capnum0;
extern unsigned int capnum1;
extern unsigned int capnum2;
extern unsigned int capnum3;
extern unsigned int chNum;
extern BREAK_PHASE_I chanell1;
extern BREAK_PHASE_I chanell2;
extern int cmd_3_or_16;
extern int compress_size;
extern ControlReg controlReg;
extern COS_FI_STRUCT cos_fi;
extern unsigned int count_error_sync;
extern int count_modbus_table_changed;
extern int count_run_pch;
extern WORD crc_16_tab[256];
extern char crypt[34];
extern int cur_position_buf_modbus16_can;
extern CYCLE cycle[32];
extern int delta_capnum;
extern int delta_error;
extern volatile DOORS_STATUS doors;
extern int enable_can;
extern int enable_can_recive_after_units_box;
extern _iq err_level_adc;
extern _iq err_level_adc_on_go;
extern unsigned int err_main;
extern int err_modbus16;
extern int err_modbus3;
extern ERRORS errors;
extern FLAG f;
extern volatile int fail;
extern FAULTS faults;
extern FIFO fifo;
extern ANALOG_VALUE filter;
extern int flag_buf;
extern int flag_enable_can_from_mpu;
extern int flag_enable_can_from_terminal;
extern int flag_on_off_pch;
extern unsigned int flag_received_first_mess_from_MPU;
extern unsigned int flag_reverse;
extern unsigned int flag_send_answer_rs;
extern int flag_test_tabe_filled;
extern int flag_we_int_pwm_on;
extern _iq freq1;
extern float freqTerm;
extern GLOBAL_TIME global_time;
extern int hb_logs_data;
extern int i;
extern BREAK2_PHASE i1_out;
extern BREAK2_PHASE i2_out;
extern int init_log[3];
extern _iq19 iq19_k_norm_ADC[20];
extern _iq19 iq19_zero_ADC[20];
extern _iq iq_alfa_coef;
extern _iq iq_k_norm_ADC[20];
extern IQ_LOGSPARAMS iq_logpar;
extern _iq iq_max;
extern _iq iq_norm_ADC[20];
extern ISOLATION isolation1;
extern ISOLATION isolation2;
extern _iq k1;
extern float kI_D;
extern float kI_D_Inv31;
extern float kI_Q;
extern float kI_Q_Inv31;
extern float kP_D;
extern float kP_D_Inv31;
extern float kP_Q;
extern float kP_Q_Inv31;
extern _iq koef_Base_stop_run;
extern _iq koef_Iabc_filter;
extern _iq koef_Im_filter;
extern _iq koef_Im_filter_long;
extern _iq koef_K_stop_run;
extern _iq koef_Krecup;
extern _iq koef_Min_recup;
extern _iq koef_TemperBSU_long_filter;
extern _iq koef_Ud_fast_filter;
extern _iq koef_Ud_long_filter;
extern _iq koef_Wlong;
extern _iq koef_Wout_filter;
extern _iq koef_Wout_filter_long;
extern long koeff_Fs_filter;
extern long koeff_Idq_filter;
extern _iq koeff_Iq_filter;
extern long koeff_Iq_filter_slow;
extern long koeff_Ud_filter;
extern long koeff_Uq_filter;
extern volatile unsigned long length;
extern _iq level_on_off_break[13][2];
extern logcan_TypeDef log_can;
extern LOG_CAN_SETUP log_can_setup;
extern TYPE_LOG_PARAMS log_params;
extern long logbuf_sync1[10];
extern LOGSPARAMS logpar;
extern int m_PWM;
extern MAILBOXS_CAN_SETUP mailboxs_can_setup;
extern int manufactorerAndProductID;
extern MODBUS_REG_STRUCT * modbus_table_can_in;
extern MODBUS_REG_STRUCT * modbus_table_can_out;
extern MODBUS_REG_STRUCT modbus_table_in[450];
extern MODBUS_REG_STRUCT modbus_table_out[450];
extern MODBUS_REG_STRUCT * modbus_table_rs_in;
extern MODBUS_REG_STRUCT * modbus_table_rs_out;
extern MODBUS_REG_STRUCT modbus_table_test[450];
extern MPU_CAN_SETUP mpu_can_setup;
extern NEW_CYCLE_FIFO new_cycle_fifo;
extern int no_write;
extern int no_write_slow;
extern int number_modbus_table_changed;
extern OPTICAL_BUS_DATA optical_read_data;
extern OPTICAL_BUS_DATA optical_write_data;
extern MODBUS_REG_STRUCT options_controller[200];
extern _iq pidCur_Ki;
extern PIDREG3 pidD;
extern PIDREG3 pidD2;
extern PIDREG3 pidFvect;
extern int pidFvectKi_test;
extern int pidFvectKp_test;
extern PIDREG3 pidPvect;
extern PIDREG3 pidQ;
extern PIDREG3 pidQ2;
extern PIDREG_KOEFFICIENTS pidReg_koeffs;
extern PIDREG3 pidTetta;
extern POWER_RATIO power_ratio;
extern int prev_flag_buf;
extern unsigned int prev_status_received;
extern T_project project;
extern PWMGEND pwmd;
extern T_controller_read r_c_sbus;
extern T_controller_read r_controller;
extern FIFO refo;
extern TMS_TO_TERMINAL_STRUCT reply;
extern TMS_TO_TERMINAL_TEST_ALL_STRUCT reply_test_all;
extern RMP_MY1 rmp_freq;
extern RMP_MY1 rmp_wrot;
extern T_rotation_sensor rotation_sensor;
extern ROTOR_VALUE rotor;
extern RS_DATA_STRUCT rs_a;
extern RS_DATA_STRUCT rs_b;
extern unsigned int sincronisationFault;
extern char size_cmd15;
extern char size_cmd16;
extern int size_fast_done;
extern int size_slow_done;
extern int stop_log;
extern int stop_log_slow;
extern SVGENDQ svgen_dq_1;
extern SVGENDQ svgen_dq_2;
extern SVGEN_PWM24 svgen_pwm24_1;
extern SVGEN_PWM24 svgen_pwm24_2;
extern unsigned int temp;
extern _iq temperature_limit_koeff;
extern INVERTER_TEMPERATURES temperature_warning_BI1;
extern INVERTER_TEMPERATURES temperature_warning_BI2;
extern RECTIFIER_TEMPERATURES temperature_warning_BV1;
extern RECTIFIER_TEMPERATURES temperature_warning_BV2;
extern TERMINAL_CAN_SETUP terminal_can_setup;
extern TETTA_CALC tetta_calc;
extern int timCNT_alg;
extern int timCNT_prev;
extern unsigned int time;
extern float time_alg;
extern long time_pause_enable_can_from_mpu;
extern long time_pause_enable_can_from_terminal;
extern int time_pause_logs;
extern int time_pause_titles;
extern volatile int tryNumb;
extern UNITES_CAN_SETUP unites_can_setup;
extern VECTOR_CONTROL vect_control;
extern WaterCooler water_cooler;
extern _iq winding_displacement;
extern Word word;
extern WordReversed wordReversed;
extern WordToReverse wordToReverse;
extern X_PARALLEL_BUS x_parallel_bus_project;
extern X_SERIAL_BUS x_serial_bus_project;
extern unsigned int xeeprom_controll_fast;
extern unsigned int xeeprom_controll_store;
extern XPWM_TIME xpwm_time;
extern _iq zadan_Id_min;
extern int zero_ADC[20];
// Îïðåäåëåíèå ìàññèâà ñ óêàçàòåëÿìè íà ïåðåìåííûå äëÿ îòëàäêè
int DebugVar_Qnt = 23;
#pragma DATA_SECTION(dbg_vars,".dbgvar_info")
DebugVar_t dbg_vars[] = {\
{(char *)&ADC0finishAddr, pt_int16, t_iq_none, t_iq_none, "ADC0finish" }, \
{(char *)&IQ_OUT_NOM, pt_float, t_iq_none, t_iq10, "IQ_OUT_NOM" }, \
{(char *)&KmodTerm, pt_float, t_iq_none, t_iq10, "KmodTerm" }, \
{(char *)&freqTerm, pt_float, t_iq_none, t_iq10, "freqTerm" }, \
{(char *)&ADC_sf[0][0], pt_int16, t_iq_none, t_iq_none, "ADC_sf00" }, \
{(char *)&ADC_sf[0][1], pt_int16, t_iq_none, t_iq_none, "ADC_sf01" }, \
{(char *)&ADC_sf[0][2], pt_int16, t_iq_none, t_iq_none, "ADC_sf02" }, \
{(char *)&ADC_sf[0][3], pt_int16, t_iq_none, t_iq_none, "ADC_sf03" }, \
{(char *)&ADC_sf[0][4], pt_int16, t_iq_none, t_iq_none, "ADC_sf04" }, \
{(char *)&ADC_sf[0][5], pt_int16, t_iq_none, t_iq_none, "ADC_sf05" }, \
{(char *)&ADC_sf[0][6], pt_int16, t_iq_none, t_iq_none, "ADC_sf06" }, \
{(char *)&ADC_sf[0][7], pt_int16, t_iq_none, t_iq_none, "ADC_sf07" }, \
{(char *)&ADC_sf[0][8], pt_int16, t_iq_none, t_iq_none, "ADC_sf08" }, \
{(char *)&ADC_sf[0][9], pt_int16, t_iq_none, t_iq_none, "ADC_sf09" }, \
{(char *)&ADC_sf[0][10], pt_int16, t_iq_none, t_iq_none, "ADC_sf010" }, \
{(char *)&ADC_sf[0][11], pt_int16, t_iq_none, t_iq_none, "ADC_sf011" }, \
{(char *)&ADC_sf[0][12], pt_int16, t_iq_none, t_iq_none, "ADC_sf012" }, \
{(char *)&ADC_sf[0][13], pt_int16, t_iq_none, t_iq_none, "ADC_sf013" }, \
{(char *)&ADC_sf[0][14], pt_int16, t_iq_none, t_iq_none, "ADC_sf014" }, \
{(char *)&ADC_sf[0][15], pt_int16, t_iq_none, t_iq_none, "ADC_sf015" }, \
{(char *)&Bender[0].KOhms, pt_uint16, t_iq_none, t_iq_none, "Bend0.KOhm" }, \
{(char *)&Bender[0].Times, pt_uint16, t_iq_none, t_iq_none, "Bend0.Time" }, \
{(char *)&Bender[0].Error.all, pt_uint16, t_iq_none, t_iq_none, "Bend0.Err" }, \
};

23
debug_vars_example.c Normal file
View File

@@ -0,0 +1,23 @@
#include "debug_tools.h"
// Инклюды для доступа к переменным
#include "bender.h"
// Экстерны для доступа к переменным
extern int ADC0finishAddr;
// Определение массива с указателями на переменные для отладки
int DebugVar_Qnt = 5;
#pragma DATA_SECTION(dbg_vars,".dbgvar_info")
// pointer_type iq_type return_iq_type short_name
DebugVar_t dbg_vars[] = {\
{(uint8_t *)&freqTerm, pt_float, t_iq_none, t_iq10, "freqT" }, \
{(uint8_t *)&ADC_sf[0][0], pt_int16, t_iq_none, t_iq_none, "ADC_sf00" }, \
{(uint8_t *)&ADC_sf[0][1], pt_int16, t_iq_none, t_iq_none, "ADC_sf01" }, \
{(uint8_t *)&ADC_sf[0][2], pt_int16, t_iq_none, t_iq_none, "ADC_sf02" }, \
{(uint8_t *)&ADC_sf[0][3], pt_int16, t_iq_none, t_iq_none, "ADC_sf03" }, \
{(uint8_t *)&Bender[0].KOhms, pt_uint16, t_iq, t_iq10, "Bend0.KOhm" }, \
{(uint8_t *)&Bender[0].Times, pt_uint16, t_iq_none, t_iq_none, "Bend0.Time" }, \
};

20181
structs.xml

File diff suppressed because it is too large Load Diff

4908
vars.xml

File diff suppressed because it is too large Load Diff