libxr 0.2.2__tar.gz → 0.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: libxr
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: C++ code generator for LibXR-based embedded systems, supporting STM32 and modular robotics applications.
5
5
  Author-email: Xiao <2592509183@qq.com>
6
6
  Maintainer-email: Xiao <2592509183@qq.com>
@@ -57,6 +57,27 @@ Dynamic: license-file
57
57
 
58
58
  ## 📥 Installation 安装
59
59
 
60
+ ### 使用pipx安装 (Install via `pipx`)
61
+
62
+ windows
63
+
64
+ ```ps
65
+ python -m pip install --user pipx
66
+ python -m pipx ensurepath
67
+ pipx install libxr
68
+ pipx ensurepath
69
+ # Restart your terminal
70
+ ```
71
+
72
+ linux
73
+
74
+ ```bash
75
+ sudo apt install pipx
76
+ pipx install libxr
77
+ pipx ensurepath
78
+ # Restart your terminal
79
+ ```
80
+
60
81
  ### 使用 pip 安装 (Install via `pip`)
61
82
 
62
83
  ```bash
@@ -233,9 +254,54 @@ usage: xr_gen_code_stm32 [-h] -i INPUT -o OUTPUT [--xrobot] [--libxr-config LIBX
233
254
  Main entry point with all initialization logic
234
255
 
235
256
  - `libxr_config.yaml`:
236
- 运行时配置文件,可自定义缓冲区大小、队列等参数
257
+ 运行时配置文件,可自定义缓冲区大小、队列等参数
237
258
  Runtime config YAML, can be customized with buffer size, queue, etc.
238
259
 
260
+ - `flash_map.hpp`:
261
+ 自动生成的 Flash 扇区表,供 Flash 抽象层使用
262
+ Auto-generated flash sector layout for use with Flash abstraction layer
263
+
264
+ ---
265
+
266
+ ### `xr_stm32_flash`
267
+
268
+ 解析 STM32 型号,生成 Flash 扇区信息表(YAML 格式输出)。
269
+ Parses STM32 model name and generates flash layout info (YAML output).
270
+
271
+ ```bash
272
+ usage: xr_stm32_flash <STM32_MODEL>
273
+ ```
274
+
275
+ ### 🧠 功能说明 (Functionality)
276
+
277
+ - 根据 STM32 型号名称自动推导 Flash 大小
278
+ Automatically infers flash size from the STM32 model string
279
+
280
+ - 根据芯片系列(如 F1/F4/H7/U5 等)生成对应的扇区布局
281
+ Generates sector layout depending on the chip series (e.g., F1/F4/H7/U5)
282
+
283
+ - 输出包括每个扇区的地址、大小和索引
284
+ Output includes address, size, and index of each sector
285
+
286
+ ### 📦 输出内容 (Outputs)
287
+
288
+ - YAML 格式的 Flash 信息
289
+ Flash info in YAML format:
290
+
291
+ ```yaml
292
+ model: STM32F103C8
293
+ flash_base: '0x08000000'
294
+ flash_size_kb: 64
295
+ sectors:
296
+ - index: 0
297
+ address: '0x08000000'
298
+ size_kb: 1.0
299
+ - index: 1
300
+ address: '0x08000400'
301
+ size_kb: 1.0
302
+ ...
303
+ ```
304
+
239
305
  ---
240
306
 
241
307
  ### `xr_stm32_it`
@@ -29,6 +29,27 @@
29
29
 
30
30
  ## 📥 Installation 安装
31
31
 
32
+ ### 使用pipx安装 (Install via `pipx`)
33
+
34
+ windows
35
+
36
+ ```ps
37
+ python -m pip install --user pipx
38
+ python -m pipx ensurepath
39
+ pipx install libxr
40
+ pipx ensurepath
41
+ # Restart your terminal
42
+ ```
43
+
44
+ linux
45
+
46
+ ```bash
47
+ sudo apt install pipx
48
+ pipx install libxr
49
+ pipx ensurepath
50
+ # Restart your terminal
51
+ ```
52
+
32
53
  ### 使用 pip 安装 (Install via `pip`)
33
54
 
34
55
  ```bash
@@ -205,9 +226,54 @@ usage: xr_gen_code_stm32 [-h] -i INPUT -o OUTPUT [--xrobot] [--libxr-config LIBX
205
226
  Main entry point with all initialization logic
206
227
 
207
228
  - `libxr_config.yaml`:
208
- 运行时配置文件,可自定义缓冲区大小、队列等参数
229
+ 运行时配置文件,可自定义缓冲区大小、队列等参数
209
230
  Runtime config YAML, can be customized with buffer size, queue, etc.
210
231
 
232
+ - `flash_map.hpp`:
233
+ 自动生成的 Flash 扇区表,供 Flash 抽象层使用
234
+ Auto-generated flash sector layout for use with Flash abstraction layer
235
+
236
+ ---
237
+
238
+ ### `xr_stm32_flash`
239
+
240
+ 解析 STM32 型号,生成 Flash 扇区信息表(YAML 格式输出)。
241
+ Parses STM32 model name and generates flash layout info (YAML output).
242
+
243
+ ```bash
244
+ usage: xr_stm32_flash <STM32_MODEL>
245
+ ```
246
+
247
+ ### 🧠 功能说明 (Functionality)
248
+
249
+ - 根据 STM32 型号名称自动推导 Flash 大小
250
+ Automatically infers flash size from the STM32 model string
251
+
252
+ - 根据芯片系列(如 F1/F4/H7/U5 等)生成对应的扇区布局
253
+ Generates sector layout depending on the chip series (e.g., F1/F4/H7/U5)
254
+
255
+ - 输出包括每个扇区的地址、大小和索引
256
+ Output includes address, size, and index of each sector
257
+
258
+ ### 📦 输出内容 (Outputs)
259
+
260
+ - YAML 格式的 Flash 信息
261
+ Flash info in YAML format:
262
+
263
+ ```yaml
264
+ model: STM32F103C8
265
+ flash_base: '0x08000000'
266
+ flash_size_kb: 64
267
+ sectors:
268
+ - index: 0
269
+ address: '0x08000000'
270
+ size_kb: 1.0
271
+ - index: 1
272
+ address: '0x08000400'
273
+ size_kb: 1.0
274
+ ...
275
+ ```
276
+
211
277
  ---
212
278
 
213
279
  ### `xr_stm32_it`
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "libxr"
7
- version = "0.2.2"
7
+ version = "0.2.4"
8
8
  description = "C++ code generator for LibXR-based embedded systems, supporting STM32 and modular robotics applications."
9
9
  requires-python = ">=3.8"
10
10
  authors = [
@@ -46,6 +46,7 @@ xr_gen_code = "libxr.GeneratorCode:main"
46
46
  xr_stm32_it = "libxr.GeneratorSTM32IT:main"
47
47
  xr_stm32_cmake = "libxr.GeneratorSTM32CMake:main"
48
48
  xr_stm32_clang = "libxr.GeneratorSTM32CMakeClang:main"
49
+ xr_stm32_flash = "libxr.STM32FlashGenerator:main"
49
50
  xr_cubemx_cfg = "libxr.ConfigCubemxProject:main"
50
51
 
51
52
  [tool.setuptools.packages.find]
@@ -348,8 +348,10 @@ def generate_dma_resources(project_data: dict) -> str:
348
348
  "buffer_size",
349
349
  DMA_DEFAULT_SIZES[p_type_base]["buffer"]
350
350
  )
351
-
352
- dma_code.append(f"static uint8_t {instance_lower}_buf[{buf_size}];")
351
+ if p_type_base in ["ADC"]:
352
+ dma_code.append(f"static uint16_t {instance_lower}_buf[{int(buf_size/2)}];")
353
+ else:
354
+ dma_code.append(f"static uint8_t {instance_lower}_buf[{buf_size}];")
353
355
 
354
356
  return "/* DMA Resources */\n" + "\n".join(dma_code) if dma_code else ""
355
357
 
@@ -472,7 +474,7 @@ class PeripheralFactory:
472
474
  def _generate_header_includes(use_xrobot: bool = False) -> str:
473
475
  """Generate essential header inclusions with optional XRobot components."""
474
476
  headers = [
475
- '#include "app_main.h"',
477
+ '#include "app_main.h"\n',
476
478
  '#include "libxr.hpp"',
477
479
  '#include "main.h"',
478
480
  '#include "stm32_adc.hpp"',
@@ -485,13 +487,14 @@ def _generate_header_includes(use_xrobot: bool = False) -> str:
485
487
  '#include "stm32_spi.hpp"',
486
488
  '#include "stm32_timebase.hpp"',
487
489
  '#include "stm32_uart.hpp"',
488
- '#include "stm32_usb.hpp"'
490
+ '#include "stm32_usb.hpp"',
491
+ '#include "flash_map.hpp"'
489
492
  ]
490
493
 
491
494
  if use_xrobot:
492
495
  headers.extend([
493
496
  '#include "app_framework.hpp"\n'
494
- '#include "xrobot_main.hpp"'
497
+ '#include "xrobot_main.hpp"\n'
495
498
  ])
496
499
 
497
500
  return '\n'.join(headers) + '\n\nusing namespace LibXR;\n'
@@ -764,6 +767,70 @@ void app_main(void);
764
767
  logging.info(f"Generated header: {header_path}")
765
768
 
766
769
 
770
+ def generate_flash_map_cpp(flash_info: dict) -> str:
771
+ """
772
+ Convert flash_info dictionary to a C++ constexpr struct array.
773
+
774
+ :param flash_info: Output from flash_info_to_dict
775
+
776
+ :return: C++ code as a string
777
+ """
778
+ lines = [
779
+ "#include \"stm32_flash.hpp\"",
780
+ "",
781
+ "constexpr LibXR::FlashSector FLASH_SECTORS[] = {",
782
+ ]
783
+
784
+ for s in flash_info["sectors"]:
785
+ index = s["index"]
786
+ address = int(s["address"], 16)
787
+ size_kb = int(s["size_kb"])
788
+ lines.append(f" {{0x{address:08X}, 0x{(size_kb * 1024):08X}}},")
789
+
790
+ lines.append("};\n")
791
+ lines.append("constexpr size_t FLASH_SECTOR_NUMBER = sizeof(FLASH_SECTORS) / sizeof(LibXR::FlashSector);")
792
+ return "\n".join(lines)
793
+
794
+ def inject_flash_layout(project_data: dict, output_dir: str) -> None:
795
+ """
796
+ Automatically generate FlashLayout from project_data['Mcu']['Type']
797
+ and inject it into libxr_settings. Also generates flash_map.hpp.
798
+
799
+ :param project_data: Project configuration containing MCU type
800
+
801
+ :param output_dir: Output directory for generated flash_map.hpp
802
+ """
803
+ try:
804
+ from libxr.STM32FlashGenerator import layout_flash, flash_info_to_dict
805
+ mcu_model = project_data.get("Mcu", {}).get("Type", "").strip()
806
+ if not mcu_model:
807
+ logging.warning("Cannot find MCU name, skipping FlashLayout generation")
808
+ return
809
+
810
+ flash_info = layout_flash(mcu_model)
811
+ flash_dict = flash_info_to_dict(flash_info)
812
+ libxr_settings["FlashLayout"] = flash_dict
813
+ logging.info(f"FlashLayout is generated and injected, MCU: {mcu_model}")
814
+
815
+ cpp_code = generate_flash_map_cpp(flash_dict)
816
+ if output_dir:
817
+ hpp_path = os.path.join(output_dir, "flash_map.hpp")
818
+ with open(hpp_path, "w", encoding="utf-8") as f:
819
+ f.write(f"""#pragma once
820
+ // Auto-generated Flash Layout Map
821
+ // MCU: {mcu_model}
822
+
823
+ #include "main.h"
824
+
825
+ """)
826
+ f.write(cpp_code)
827
+ logging.info(f"Flash layout map written to: {hpp_path}")
828
+ except ImportError as e:
829
+ logging.warning(f"Cannot import FlashLayout generator: {e}")
830
+ except Exception as e:
831
+ logging.warning(f"Cannot generate FlashLayout: {e}")
832
+
833
+
767
834
  def main():
768
835
  try:
769
836
  args = parse_arguments()
@@ -788,6 +855,8 @@ def main():
788
855
  with open(args.output, "w", encoding="utf-8") as f:
789
856
  f.write(output_code)
790
857
 
858
+ inject_flash_layout(project_data, output_dir)
859
+
791
860
  config_path = os.path.join(output_dir, "libxr_config.yaml")
792
861
 
793
862
  with open(config_path, "w", encoding="utf-8") as f:
@@ -0,0 +1,185 @@
1
+ import re
2
+ from dataclasses import dataclass
3
+ from typing import Optional, List
4
+ import sys
5
+ import traceback
6
+ import yaml
7
+
8
+
9
+ @dataclass
10
+ class FlashSector:
11
+ """Flash memory sector information"""
12
+ index: int
13
+ address: int
14
+ size: int
15
+
16
+
17
+ @dataclass
18
+ class FlashInfo:
19
+ """Complete flash memory configuration"""
20
+ model: str
21
+ flash_base: int
22
+ flash_sectors: List[FlashSector]
23
+ flash_size_kb: Optional[int] = None
24
+
25
+
26
+ FLASH_SIZE_CODES = {
27
+ '4': 16, '6': 32, '8': 64, 'B': 128, 'C': 256, 'D': 384,
28
+ 'E': 512, 'F': 768, 'G': 1024, 'H': 1536, 'I': 2048,
29
+ 'J': 3072, 'K': 4096, 'L': 6144, 'M': 8192, 'N': 12288,
30
+ 'P': 16384, 'Q': 512, 'R': 640, 'S': 768, 'T': 1024, 'Z': 512,
31
+ '5': 512, '7': 2048, 'A': 1024, 'V': 1024, 'W': 512, 'X': 1024, 'Y': 2048,
32
+ '1': 256, '3': 8,
33
+ }
34
+
35
+
36
+ def get_flash_kb(model: str) -> int:
37
+ """Get flash size from STM32 model number (original logic preserved)"""
38
+ model = model.strip().upper()
39
+
40
+ # Original condition chain preserved
41
+ if model.startswith("STM32WL"):
42
+ if "X" in model:
43
+ return 1024
44
+ if any(code in model for code in ['55', '54', '53', '52']):
45
+ return 512
46
+ return 512
47
+ if model.startswith("STM32WBA"):
48
+ code = model[11]
49
+ return FLASH_SIZE_CODES.get(code, 512)
50
+ if model.startswith("STM32WB"):
51
+ if "7" in model:
52
+ return 2048
53
+ if "V" in model:
54
+ return 1024
55
+ return 512
56
+ if model.startswith("STM32U5"):
57
+ if "A" in model:
58
+ return 1024
59
+ code = model[10]
60
+ return FLASH_SIZE_CODES.get(code, None)
61
+
62
+ # Original fallback logic
63
+ try:
64
+ return FLASH_SIZE_CODES[model[10]]
65
+ except (KeyError, IndexError):
66
+ raise ValueError(f"Unrecognized capacity code for {model}")
67
+
68
+
69
+ def layout_flash(model: str) -> FlashInfo:
70
+ """Flash layout generator (original logic fully preserved)"""
71
+ model = model.upper()
72
+ flash_kb = get_flash_kb(model)
73
+ flash_base = 0x08000000
74
+ layout = []
75
+
76
+ # Original condition chain
77
+ if "F1" in model:
78
+ page_size = 1024 if flash_kb <= 128 else 2048
79
+ layout = [((flash_kb * 1024) // page_size, page_size)]
80
+ elif "F2" in model or "F4" in model:
81
+ sector_sizes = [16, 16, 16, 16, 64] + [128] * 12
82
+ layout = []
83
+ remaining = flash_kb
84
+ for size in sector_sizes:
85
+ if remaining >= size:
86
+ layout.append((1, size * 1024))
87
+ remaining -= size
88
+ else:
89
+ break
90
+ elif "U5" in model:
91
+ layout = [(1, 128 * 1024)] * (flash_kb // 128)
92
+ elif any(x in model for x in ["WL", "L4", "G0", "G4", "C0", "U0"]):
93
+ layout = [((flash_kb * 1024) // 2048, 2048)]
94
+ elif "L0" in model:
95
+ layout = [((flash_kb * 1024) // 128, 128)]
96
+ elif "WB" in model:
97
+ layout = [((flash_kb * 1024) // 4096, 4096)]
98
+ elif "WBA" in model:
99
+ layout = [(1, 32 * 1024)] * (flash_kb // 32)
100
+ elif "H7" in model:
101
+ layout = [((flash_kb * 1024) // (128 * 1024), 128 * 1024)]
102
+ elif any(x in model for x in ["F7", "F3", "F0"]):
103
+ layout = [((flash_kb * 1024) // 2048, 2048)]
104
+ elif "L1" in model:
105
+ layout = [((flash_kb * 1024) // 256, 256)]
106
+ else:
107
+ layout = [((flash_kb * 1024) // 1024, 1024)]
108
+
109
+ # Original sector generation
110
+ sectors = []
111
+ addr = flash_base
112
+ for count, size in layout:
113
+ for _ in range(count):
114
+ sectors.append(FlashSector(
115
+ index=len(sectors),
116
+ address=addr,
117
+ size=size
118
+ ))
119
+ addr += size
120
+
121
+ return FlashInfo(
122
+ model=model,
123
+ flash_base=flash_base,
124
+ flash_sectors=sectors,
125
+ flash_size_kb=flash_kb
126
+ )
127
+
128
+
129
+ def flash_info_to_dict(info: FlashInfo) -> dict:
130
+ """Original serialization logic preserved"""
131
+ return {
132
+ "model": info.model,
133
+ "flash_base": f"0x{info.flash_base:08X}",
134
+ "flash_size_kb": info.flash_size_kb,
135
+ "sectors": [
136
+ {"index": s.index, "address": f"0x{s.address:08X}", "size_kb": round(s.size / 1024, 3)}
137
+ for s in info.flash_sectors
138
+ ]
139
+ }
140
+
141
+
142
+ def main():
143
+ """Command line interface for STM32 flash information tool"""
144
+
145
+ def validate_model(model: str) -> bool:
146
+ """Validate STM32 model number format"""
147
+ return (
148
+ '-' not in model and
149
+ model.upper().startswith("STM32") and
150
+ len(model) > 8
151
+ )
152
+
153
+ if len(sys.argv) != 2:
154
+ print("STM32 Flash Information Tool")
155
+ print("Usage:")
156
+ print(f" xr_stm32_flash <STM32_MODEL>")
157
+ print("\nExamples:")
158
+ print(f" xr_stm32_flash STM32F103C8T6")
159
+ print(f" xr_stm32_flash STM32L476RG")
160
+ sys.exit(1)
161
+
162
+ model = sys.argv[1].strip().upper()
163
+
164
+ try:
165
+ if not validate_model(model):
166
+ raise ValueError(f"Invalid STM32 model format: {model}")
167
+
168
+ info = layout_flash(model)
169
+ print(yaml.safe_dump(
170
+ flash_info_to_dict(info),
171
+ sort_keys=False,
172
+ allow_unicode=True,
173
+ default_flow_style=False
174
+ ))
175
+
176
+ except Exception as e:
177
+ print(f"\nERROR: Failed to process model {model}")
178
+ print(f"Reason: {str(e)}")
179
+ print("\nStack trace:")
180
+ traceback.print_exc()
181
+ sys.exit(2)
182
+
183
+
184
+ if __name__ == '__main__':
185
+ main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: libxr
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: C++ code generator for LibXR-based embedded systems, supporting STM32 and modular robotics applications.
5
5
  Author-email: Xiao <2592509183@qq.com>
6
6
  Maintainer-email: Xiao <2592509183@qq.com>
@@ -57,6 +57,27 @@ Dynamic: license-file
57
57
 
58
58
  ## 📥 Installation 安装
59
59
 
60
+ ### 使用pipx安装 (Install via `pipx`)
61
+
62
+ windows
63
+
64
+ ```ps
65
+ python -m pip install --user pipx
66
+ python -m pipx ensurepath
67
+ pipx install libxr
68
+ pipx ensurepath
69
+ # Restart your terminal
70
+ ```
71
+
72
+ linux
73
+
74
+ ```bash
75
+ sudo apt install pipx
76
+ pipx install libxr
77
+ pipx ensurepath
78
+ # Restart your terminal
79
+ ```
80
+
60
81
  ### 使用 pip 安装 (Install via `pip`)
61
82
 
62
83
  ```bash
@@ -233,9 +254,54 @@ usage: xr_gen_code_stm32 [-h] -i INPUT -o OUTPUT [--xrobot] [--libxr-config LIBX
233
254
  Main entry point with all initialization logic
234
255
 
235
256
  - `libxr_config.yaml`:
236
- 运行时配置文件,可自定义缓冲区大小、队列等参数
257
+ 运行时配置文件,可自定义缓冲区大小、队列等参数
237
258
  Runtime config YAML, can be customized with buffer size, queue, etc.
238
259
 
260
+ - `flash_map.hpp`:
261
+ 自动生成的 Flash 扇区表,供 Flash 抽象层使用
262
+ Auto-generated flash sector layout for use with Flash abstraction layer
263
+
264
+ ---
265
+
266
+ ### `xr_stm32_flash`
267
+
268
+ 解析 STM32 型号,生成 Flash 扇区信息表(YAML 格式输出)。
269
+ Parses STM32 model name and generates flash layout info (YAML output).
270
+
271
+ ```bash
272
+ usage: xr_stm32_flash <STM32_MODEL>
273
+ ```
274
+
275
+ ### 🧠 功能说明 (Functionality)
276
+
277
+ - 根据 STM32 型号名称自动推导 Flash 大小
278
+ Automatically infers flash size from the STM32 model string
279
+
280
+ - 根据芯片系列(如 F1/F4/H7/U5 等)生成对应的扇区布局
281
+ Generates sector layout depending on the chip series (e.g., F1/F4/H7/U5)
282
+
283
+ - 输出包括每个扇区的地址、大小和索引
284
+ Output includes address, size, and index of each sector
285
+
286
+ ### 📦 输出内容 (Outputs)
287
+
288
+ - YAML 格式的 Flash 信息
289
+ Flash info in YAML format:
290
+
291
+ ```yaml
292
+ model: STM32F103C8
293
+ flash_base: '0x08000000'
294
+ flash_size_kb: 64
295
+ sectors:
296
+ - index: 0
297
+ address: '0x08000000'
298
+ size_kb: 1.0
299
+ - index: 1
300
+ address: '0x08000400'
301
+ size_kb: 1.0
302
+ ...
303
+ ```
304
+
239
305
  ---
240
306
 
241
307
  ### `xr_stm32_it`
@@ -9,6 +9,7 @@ src/libxr/GeneratorSTM32CMakeClang.py
9
9
  src/libxr/GeneratorSTM32IT.py
10
10
  src/libxr/PeripheralAnalyzer.py
11
11
  src/libxr/PeripheralAnalyzerSTM32.py
12
+ src/libxr/STM32FlashGenerator.py
12
13
  src/libxr/__init__.py
13
14
  src/libxr.egg-info/PKG-INFO
14
15
  src/libxr.egg-info/SOURCES.txt
@@ -6,4 +6,5 @@ xr_parse = libxr.PeripheralAnalyzer:main
6
6
  xr_parse_ioc = libxr.PeripheralAnalyzerSTM32:main
7
7
  xr_stm32_clang = libxr.GeneratorSTM32CMakeClang:main
8
8
  xr_stm32_cmake = libxr.GeneratorSTM32CMake:main
9
+ xr_stm32_flash = libxr.STM32FlashGenerator:main
9
10
  xr_stm32_it = libxr.GeneratorSTM32IT:main
File without changes
File without changes
File without changes
File without changes