# PySVDAssistant
**Repository Path**: thostones/py-svdassistant
## Basic Information
- **Project Name**: PySVDAssistant
- **Description**: PySVDAssistant 是一个处理 XLSX 文件并生成Keil SVD 字符串的 Python 脚本,该字符串随后将保存到指定的输出文件中。该脚本可以处理单个 XLSX 文件以及包含多个 XLSX 文件的目录。
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 3
- **Forks**: 0
- **Created**: 2024-08-05
- **Last Updated**: 2025-10-08
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# PySVDAssistant
## 说明
`PySVDAssistant` 是一个根据.xlsx文件内容并生成.svd文件的工具。该脚本可以处理单个.xlsx文件以及包含多个.xlsx文件的目录。
## PySVDAssistant 使用说明
### 使用方法
```cmd
PySVDAssistant Version:0.3.0
py Usage: python PySVDAssistant.py [Options] [input xlsx paths or files...]
exe Usage: PySVDAssistant.exe [Options] [input xlsx paths or files...]
Options:
-SVDOut=SVDOutPutDirPath Specify the output dir path of SVD file (default: ./)
-RTLOut=RTLOutPutDirPath Specify the output dir path of RTL file (default: ./)
-DisableSVD Disable SVD Conversion
-DisableRTL Disable RTL Conversion
```
### 注意事项
- 该脚本至少需要一个输入路径才能正常工作。如果未提供输入路径,将默认使用当前目录。
- 脚本会检查指定路径中是否存在 XLSX 文件。如果未找到 XLSX 文件,将显示错误信息,并且脚本将退出。
### 错误处理
该脚本包括以下场景的错误检查:
1. 未指定输入路径。
2. 在指定路径中未找到 XLSX 文件。
3. 从 Excel 文件中提取信息失败。
4. 生成 SVD 字符串失败。
如果发生错误,将显示适当的错误信息,脚本将以非零状态码退出。
### 退出代码
- `0` : 执行成功
- `1` : 未指定输入路径
- `2` : 获取 SVD 信息失败
- `3` : 生成 SVD 字符串失败
### 文件夹结构
1. Install, python脚本运行的准备工作
2. SVDClasses, SVD数据结构类的定义
3. ExcelAPI, 从excel读取数据和转化的API
4. Docs, 用于保存Readme中需要的文件
5. Test, 用于测试
## python环境准备
如直接运行exe请忽略本节。
### 在线安装
直接运行
```cmd
pip install -r ./Install/packagelist.cfg
```
### 离线安装
#### 下载
通常所需的 Python 包已经下载并保存在 `./Install/package` 文件夹中。
如果没有,您可以进入 `./Install` 文件夹并运行下载脚本,这将重新下载必要的包到 `./Install/package` 文件夹中。 具体命令如下:
```cmd
cd Install
python download.py
```
#### 安装
一旦确认包已经准备好,或者 `download.py` 的执行已成功完成,您可以使用以下命令进行安装:
```cmd
python install.py
```
## 脚本执行前的准备工作
### 一个文件夹
这个文件夹用于存放所有的xlxs文件。这个文件夹的路径会被作为工具脚本运行的唯一输入参数。
### Excel文件和Sheets
这个工具脚本被设计用于从后缀为xlsx的excel文件中读取数据,并转化为Keil package的SVD文件。其它格式没有被格式过。
它主要依赖Sheet的名称和内容,并不要求sheets必须在同一个excel文件中,这样可以方便团队协作,分散撰写不同的sheet。
外设以外的Sheets固定包括"DEVICE","CPU","PERIPHERALS"。
### 注意:xlsx文件所有内容不要有全角字符不要有汉字,否则SVDCovn会出错。 如果生成或安装PACK包时报错,大概率是SVD文件中包含非法字符,请检查生成的SVD文件,根据SVD文件问题修改xlsx文件
#### "DEVICE" Sheet
Sheet名称必须是"DEVICE”,用于保存SVD中Device的属性信息,表头必须和下面一致:
| name | description | version | addressUnitBits | width | size | resetValue | resetMask |
| ---- | ----------- | ------- | --------------- | ----- | ---- | ---------- | --------- |
其中,各属性名称和SVD文件的字段要求一致,需要进一步了解请参考SVD文件说明,这里不进行赘述。第二行是对应属性的值。
#### "CPU" Sheet
Sheet名称必须是"CPU,用于保存SVD中CPU的属性信息,表头必须和下面一致:
| name | revision | endian | mpuPresent | fpuPresent | nvicPrioBits | vendorSystickConfig |
| ---- | -------- | ------ | ---------- | ---------- | ------------ | ------------------- |
其中,各属性名称和SVD文件的字段要求一致,需要进一步了解请参考SVD文件说明,这里不进行赘述。第二行是对应属性的值。
#### "PERIPHERALS" Sheet
Sheet名称必须是"PERIPHERALS",用于保存SVD中外设的属性信息,表头必须为:
***name, groupName, sheetName, headerStructName, baseAddress, offset, size , description, interrupt, int_name, int_description***
表格的内容只是示例:
| name | groupName | sheetName | headerStructName | baseAddress | offset | size | description | interrupt | int_name | int_description |
| ---- | --------- | --------- | ---------------- | ----------- | ------ | ------ | ----------- | --------- | ---------- | --------------- |
| TIM0 | Timer | TIMER0 | TIM16 | 0x40007000 | 0x0 | 0x1000 | 16bit Timer | 7 | | |
| TIM1 | Timer | TIMER1 | TIM16 | 0x40008000 | 0x0 | 0x1000 | 16bit Timer | 8 | | |
| TIM2 | Timer | TIMER2 | TIM32 | 0x40009000 | 0x0 | 0x1000 | 32bit Timer | 9 | | |
| DMA | DMA | DMA | DMA | 0x4000A000 | 0x0 | 0x1000 | DMA | 10 | DMA_finish | |
| DMA | | | | | | | | 11 | | half finish |
| | | | | | | | | 12 | | |
其中,第二行是对应属性的值。 表头里name、groupName、headerStructName、baseAddress、offset、size、description等和SVD文件的字段要求一致,需要进一步了解请参考SVD文件说明,这里不进行赘述。
其它sheet说明:
**sheetName**:对应外设Sheet名称中这个外设的名称,相当于是一个别名。在上面的例子里面,工具认为sheet名称中包含“TIMER0”的sheet是用来描述TIM0的,以此类推。
**headerStructName**:属性意义和SVD相关要求一致。这里要说明的是,工具会把所有具有同一headerStructName的外设信息进行排列,在第一位的外设会进行详细描述并不会具有headerStructName这个属性,后面的外设会具有headerStructName,以及具有个性化的一些属性比如bassAddress等,其它共性的属性并不会被详细描述比如Registers等。
**interrupt, int_name, nt_description**:对应SVD文件中Inerrupt block中的中断信息。上表中DMA的中断信息SVD为:
```xml
DMA_finish
10
DMA_2
11
DMA_3
12
half finish
```
注意,需要录入多中断的外设(name),第一次出现这个外设的信息必须是完整的,后续再出现这个外设中断信息之外的信息是不会被录入的;连续登记中断信息的行,“interrupt”字段是必须的;如果“name”字段为空,则认为当前中断信息要注册在刚被识别到的外设信息中。
#### 外设Sheet
单个外设的信息需要由两个Sheet(**MAP**和**DETAL**)组成,分别是**外设名称_MAP**和**外设名称_DETAL**,比如***TIMER0_MAP***和***TIMER0_DETAIL***。
##### MAP
MAP sheet保存的是外设的概要信息。Sheet名称必须是外设的名称(*PERIPHERALS* Sheet中*sheetName*列中的名称)+"MAP",用于保存SVD中外设的属性信息,表头必须和下面一致:
| addressOffset | name | resetValue | description | dim | dimIncrement | dimIndex |
| ------------- | ---- | ---------- | ----------- | --- | ------------ | -------- |
其中,各属性名称和SVD文件的字段要求一致,需要进一步了解请参考SVD文件说明,这里不进行赘述。
以下各行是对应外设的信息。
##### DETAIL
DETAIL sheet保存的是外设的寄存器的详细信息。Sheet名称必须是外设的名称(*PERIPHERALS* Sheet中*sheetName*列中的名称)+"DETAL",用于保存SVD中外设的属性信息,表头必须和下面一致:
| regname | name | msb | lsb | access | description | headerEnumName | enumValueName | enumValue | enumDescription | modifiedWriteValues | writeConstraint | readAction |
| ------- | ---- | --- | --- | ------ | ----------- | -------------- | ------------- | --------- | --------------- | ------------------- | --------------- | ---------- |
其中,"name"、“msb”、“lsb”、"access"、"description"、"modifiedWriteValues"、"readAction"名称和SVD文件中Field各字段要求一致,需要进一步了解请参考SVD文件说明,这里不进行赘述。参考链接:
以下字段需要注意:
##### regname
Field所属的寄存器名称,需要与MAP页面一致。
##### access"字段
大小写不敏感。目前只接受这些字段"RO","read-only","WO":"write-only","RW"(或“RW”):"read-write"。其中"RO"是"read-only"的缩写,"WO"是"write-only"的缩写,"RW"是"read-write"的缩写。若识别到其它值,脚本运行时会报错。
##### headerEnumName,enumValueName,enumValue,enumDescription
有以下字段用于描述枚举类型:
**headerEnumName**:枚举C语言struct类型名称
**enumValueName**:枚举值名称
**enumValue**:枚举值
**enumDescription**:枚举值的描述
如果一个Field中不包含枚举类型,则"headerEnumName"需要不填写,其后的"enumValueName"、"enumValue"、"enumDescription"填写也会被忽略。
如果一个Field中包含枚举类型需要,那么用连续多行进行说明,每一行通过"enumValueName"、"enumValue"、"enumDescription"描述一个enumValue。
对这样的连续多行:
1. 其中第一行的"name"、"access"、"description"、"enumValue"应该进行详细描述。
2. 其余行的"name"字段可以为空或和第一行保持一致。
3. 其余行的"access"、"description"、"headerEnumName"等这些部分都以第一行为准,不再读取其余行的相关内容。
举例如下:
| name | access | description | headerEnumName | enumValueName | enumValue | enumDescription |
| ----------- | ------ | ------------------------------------------ | -------------- | ------------- | --------- | --------------- |
| GreatStatus | RW | Overflow interrupt enables the controller. | Great | NoGreat | 0 | |
| | | | | Normal | 1 | |
| | | | | Great | 2 | |
| | | | | SuperGreat | 3 | |
| BadStatus | RO | Overflow interrupt flag. | Bad | NoBad | 0 | |
| BadStatus | RO | Overflow interrupt flag. | Bad | Bad | 1 | |
| BadStatus | RO | Overflow interrupt flag. | Bad | SuperBad | 3 | |
##### writeConstraint
允许输入“enumDescription”,“writeAsRead”和“range[A-B]”,如需输入多类约束,需要用','连接如:“enumDescription,writeAsRead,range[1-5]”
参考链接:
###### enumDescription
转化为
```xml
...
true
...
```
###### writeAsRead
转化为
```xml
...
true
...
```
###### range[A-B]
转化为
```xml
...
A
B
...
```