Skip to content

Upstream changes #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Aug 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8b674ef
README: Formatting and typos
dbrgn Feb 18, 2020
5225a1d
Run cargo update
dbrgn Feb 18, 2020
6592ccb
Run cargo fmt
dbrgn Feb 18, 2020
b2e656d
Better error handling, less unwrap() in main()
dbrgn Feb 18, 2020
24c83f9
Remove unused imports
dbrgn Feb 18, 2020
873f6c7
Use dyn keyword for boxed errors
dbrgn Feb 18, 2020
482f317
README: Document database structure and feature grouping
dbrgn Feb 18, 2020
406b21c
Generate only a feature per GPIO group, not per MCU
dbrgn Feb 18, 2020
059b66d
family: Add some code documentation
dbrgn Feb 18, 2020
d8d8164
Use clap for argument parsing
dbrgn Feb 20, 2020
a6ecda1
Set up CI
dbrgn Feb 20, 2020
439efa1
Add generate target parameter
dbrgn Feb 20, 2020
cc6c4b1
Convert -m and -g args to positional args
dbrgn Feb 20, 2020
8e5d235
Simplify mcu_gpio_map creation code
dbrgn Feb 20, 2020
028140e
Generate both pin mappings and feature list
dbrgn Feb 20, 2020
4f788e0
README: Improve documentation
dbrgn Feb 20, 2020
f81e0d6
generate_features: Fix comment character
dbrgn Feb 23, 2020
272f8d2
generate_features: Add PAC dependencies
dbrgn Feb 23, 2020
2f9470f
Merge pull request #4 from dbrgn/features-pac-dependencies
dbrgn Feb 23, 2020
7c369c6
generate_features: Add support for package features
dbrgn Feb 23, 2020
700893f
IP: Match LPUART as well
dbrgn Apr 3, 2020
73a46ed
Fix code formatting
dbrgn Apr 3, 2020
0ed9111
Add support for extracting EEPROM size
dbrgn Dec 8, 2020
935512c
Correction: EEPROM size is in bytes
dbrgn Dec 8, 2020
9e210cb
Fix syntax of eeprom feature cfg attribute
dbrgn Dec 8, 2020
2c71164
Add support for parsing Flash and RAM sizes (#5)
azerupi Jul 30, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: CI

on:
push:
branches:
- master
pull_request:

jobs:
build_and_test:
name: Build and test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Run tests
uses: actions-rs/cargo@v1
with:
command: test
args: --all-features
clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: clippy
override: true
- uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
rustfmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: rustfmt
override: true
- run: cargo fmt -- --check
219 changes: 147 additions & 72 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
[package]
name = "cube-parse"
version = "0.1.0"
authors = ["HarkonenBade<[email protected]>"]
authors = ["HarkonenBade<[email protected]>", "Danilo Bargen <[email protected]>"]
edition = "2018"

[dependencies]
clap = "2"
serde = "1.0"
serde-xml-rs = "0.2"
serde_derive = "1.0"
regex = "1.1"
lazy_static = "1.2"
alphanumeric-sort = "1.0"
alphanumeric-sort = "1.0"
214 changes: 211 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,217 @@
# Cube Parser

A program to extract AF modes on MCU pins from the database files provided with STM32CubeMX.
[![Build Status][github-actions-badge]][github-actions]

A program to extract hardware configuration information from the MCU database
files shipped with STM32CubeMX.


## Usage

cargo run features STM32L0 -d /path/to/stm32cubemx/db/mcu/
cargo run pin_mappings STM32L0 -d /path/to/stm32cubemx/db/mcu/

Under a default Windows install, the database path is `C:\Program Files
(x86)\STMicroelectronics\STM32Cube\STM32CubeMX\db\mcu`, adjust as appropriate
for your local config. The MCU family name should match one of the MCU families
as defined in `families.xml`. At the time of writing, the following families
are available:

* STM32F0
* STM32F1
* STM32F2
* STM32F3
* STM32F4
* STM32F7
* STM32G0
* STM32G4
* STM32H7
* STM32L0
* STM32L1
* STM32L4
* STM32L4+
* STM32L5
* STM32MP1
* STM32WB


## The STM32CubeMX Database

The STM32CubeMX database contains the following files that are relevant to us:

### Families

In the root, there is a file called `families.xml`. It contains all MCUs
grouped by family (e.g. "STM32F0") and subfamily (e.g. "STM32F0x0 Value Line").

```xml
<Families xsi:noNamespaceSchemaLocation="families.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Family Name="STM32F0">
<SubFamily Name="STM32F0x0 Value Line">
<Mcu Name="STM32F030C6Tx" PackageName="LQFP48" RefName="STM32F030C6Tx" RPN="STM32F030C6">
<Core>Arm Cortex-M0</Core>
<Frequency>48</Frequency>
<Ram>4</Ram>
...
</Mcu>
<Mcu Name="STM32F030C8Tx" PackageName="LQFP48" RefName="STM32F030C8Tx" RPN="STM32F030C8">
...
```
cargo run $PATH_TO_MCU_DB_DIR $NAME_OF_MCU_FAMILY

### MCU

Next to the `families.xml` file, there are a lot of MCU definitions. The
filenames match the `Name` attribute in the `Mcu` element above.

For example, the `STM32L071KB(B-Z)Tx.xml` file starts like this:

```xml
<Mcu ClockTree="STM32L0" DBVersion="V3.0" Family="STM32L0" HasPowerPad="false"
IOType="" Line="STM32L0x1" Package="LQFP32" RefName="STM32L071K(B-Z)Tx"
xmlns="http://mcd.rou.st.com/modules.php?name=mcu">
<Core>Arm Cortex-M0+</Core>
<Frequency>32</Frequency>
<E2prom>6144</E2prom>
<Ram>20</Ram>
<IONb>25</IONb>
<Die>DIE447</Die>
<Flash>128</Flash>
<Flash>192</Flash>
<Voltage Max="3.6" Min="1.65"/>
<Current Lowest="0.29" Run="87"/>
<Temperature Max="125" Min="-40"/>
...
```
Under a default windows install `$PATH_TO_MCU_DB_DIR` is `C:\Program Files (x86)\STMicroelectronics\STM32Cube\STM32CubeMX\db\mcu`, adjust as appropriate for your local config. The MCU family name should match one of the MCU families as defined in `families.xml`. The program will output one AF mode definition per GPIO variant, with cfg feature gates for the different MCU variants that utalise that GPIO type.

This first part describes the MCU: How much RAM it has, what the frequency is,
how many I/Os it has, what flash variants there are, etc. Many of these things
are also encoded in the full MCU `RefName`.

Following this general description, there are a number of `IP` elements. IP
stands for "Internal Peripheral". Here we have things like the USART peripherals:

```xml
<IP InstanceName="USART1" Name="USART" Version="sci3_v1_1_Cube"/>
<IP InstanceName="USART2" Name="USART" Version="sci3_v1_1_Cube"/>
```

...or the RCC peripheral:

```xml
<IP InstanceName="RCC" Name="RCC" Version="STM32L051_rcc_v1_0"/>
```

...and, most important to us, the GPIO peripheral.

```xml
<IP ConfigFile="GPIO-STM32L0xx" InstanceName="GPIO" Name="GPIO" Version="STM32L071_gpio_v1_0"/>
```

Here, the value of the `Version` attribute points to the actual GPIO signal
definition.

(There are also some other interesting entries in that file, for example the
mapping from physical pins to internal pin names. Those are not relevant for us
though.)

### GPIO Internal Peripheral

The GPIO IP can be found in the `IP` directory. The relevant file for us is at
`IP/GPIO-<version>_Modes.xml`. The version can be extracted from the `IP`
element shown in the previous section.

In the case of the `STM32L071KBTx`, the relevant GPIO IP version file is at
`IP/GPIO-STM32L071_gpio_v1_0_Modes.xml`.

That file starts out with some `RefParameter` and `RefMode` elements. Relevant
to us are mostly the `GPIO_Pin` elements. They look like this:

```xml
<GPIO_Pin PortName="PB" Name="PB6">
<SpecificParameter Name="GPIO_Pin">
<PossibleValue>GPIO_PIN_6</PossibleValue>
</SpecificParameter>
<PinSignal Name="I2C1_SCL">
<SpecificParameter Name="GPIO_AF">
<PossibleValue>GPIO_AF1_I2C1</PossibleValue>
</SpecificParameter>
</PinSignal>
<PinSignal Name="LPTIM1_ETR">
<SpecificParameter Name="GPIO_AF">
<PossibleValue>GPIO_AF2_LPTIM1</PossibleValue>
</SpecificParameter>
</PinSignal>
<PinSignal Name="TSC_G5_IO3">
<SpecificParameter Name="GPIO_AF">
<PossibleValue>GPIO_AF3_TSC</PossibleValue>
</SpecificParameter>
</PinSignal>
<PinSignal Name="USART1_TX">
<SpecificParameter Name="GPIO_AF">
<PossibleValue>GPIO_AF0_USART1</PossibleValue>
</SpecificParameter>
</PinSignal>
</GPIO_Pin>
```

As you can see, this element describes the pin `PB6`. Depending on the chosen
Alternative Function (AF), it can become an `I2C1_SCL` pin (AF1), a `USART1_TX`
pin (AF0), or some other variants.


## GPIO Feature Groups

When generating pin function mappings, we want to avoid generating a mapping
for every possible MCU, since that would result in dozens or even hundreds of
pin definitions. However, if we don't want a mapping per MCU, we need to group
them somehow. The best way for grouping is probably to follow ST's grouping,
which is encoded in the IP versions described above.

The feature names are mapped as follows:

- `STM32L031_gpio_v1_0` -> `io-STM32L031`
- `STM32L051_gpio_v1_0` -> `io-STM32L051`
- `STM32L152x8_gpio_v1_0` -> `io-STM32L152x8`

For example, the GPIO IP file named "STM32L031_gpio_v1_0" is shared among the
following MCUs:

- STM32L010C6Tx
- STM32L031C(4-6)Tx
- STM32L031C(4-6)Tx
- STM32L031C6Ux
- STM32L031E(4-6)Yx
- STM32L031E(4-6)Yx
- STM32L031F(4-6)Px
- STM32L031F(4-6)Px
- STM32L031G(4-6)Ux
- STM32L031G(4-6)Ux
- STM32L031G6UxS
- STM32L031K(4-6)Tx
- STM32L031K(4-6)Tx
- STM32L031K(4-6)Ux
- STM32L031K(4-6)Ux
- STM32L041C(4-6)Tx
- STM32L041C(4-6)Tx
- STM32L041E6Yx
- STM32L041F6Px
- STM32L041G6Ux
- STM32L041G6UxS
- STM32L041K6Tx
- STM32L041K6Ux

As you can see, this may be a bit confusing due to the fact that both the
`STM32L010C6Tx` and the `STM32L041E6Yx` require the `io-STM32L031` feature.
However, sticking to the (sometimes non-logical) grouping used in the CubeMX
database is probably still better than creating our own grouping, which may be
broken at any time by ST releasing a new MCU in a pre-existing group, but with
a different, incompatible GPIO IP version.

In order to simplify the GPIO IP version selection for the user, alias features
are generated. These are purely a convenience for the user and are never used
directly as feature gates in the source code.


<!-- Badges -->
[github-actions]: https://github.com/dbrgn/cube-parse/actions?query=branch%3Amaster
[github-actions-badge]: https://github.com/dbrgn/cube-parse/workflows/CI/badge.svg
61 changes: 52 additions & 9 deletions src/family.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,86 @@
use std::error::Error;
use std::path::Path;

use serde;
use serde_derive::Deserialize;

use crate::utils::load_file;

#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Families {
#[serde(rename="Family")]
#[serde(rename = "Family")]
families: Vec<Family>,
}

/// A MCU family (e.g. "STM32F0" or "STM32L3").
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Family {
pub name: String,
#[serde(rename="SubFamily")]
#[serde(rename = "SubFamily")]
sub_families: Vec<SubFamily>,
}

/// A MCU subfamily (e.g. "STM32F0x0 Value Line").
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct SubFamily {
pub name: String,
#[serde(rename="Mcu")]
mcus: Vec<Mcu>,
#[serde(rename = "Mcu")]
pub mcus: Vec<Mcu>,
}

/// A MCU (e.g. STM32L071KBTx).
///
/// Note that multiple MCUs (with unique `ref_name`) share a common name. For
/// example:
///
/// - `<Mcu Name="STM32L071K(B-Z)Tx" PackageName="LQFP32" RefName="STM32L071KBTx" RPN="STM32L071KB">`
/// - `<Mcu Name="STM32L071K(B-Z)Tx" PackageName="LQFP32" RefName="STM32L071KZTx" RPN="STM32L071KZ">`
///
/// Both MCUs share the same name, but the ref name is different.
///
/// The meaning of the name, using the `STM32L071KBTx` as an example:
///
/// |Part |Meaning |
/// |-----|--------|
/// |STM32|Family |
/// | L |Type |
/// | 0 |Core |
/// | 71 |Line |
/// | K |Pincount|
/// | B |Flash |
/// | T |Package |
/// | x |Temp |
/// |-----|--------|
///
/// See https://ziutek.github.io/2018/05/07/stm32_naming_scheme.html for more details.
///
/// Note that sometimes there are exceptions from this naming rule.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Mcu {
pub name: String,
package_name: String,
ref_name: String,
pub package_name: String,
pub ref_name: String,
#[serde(rename = "Flash")]
pub flash_size: String,
#[serde(rename = "Ram")]
pub ram_size: String,
}

impl Mcu {
pub fn flash_size(&self) -> Option<u32> {
self.flash_size.parse().ok()
}

pub fn ram_size(&self) -> Option<u32> {
self.ram_size.parse().ok()
}
}

impl Families {
pub fn load<P: AsRef<Path>>(db_dir: P) -> Result<Self, Box<std::error::Error>> {
pub fn load<P: AsRef<Path>>(db_dir: P) -> Result<Self, Box<dyn Error>> {
load_file(db_dir, "families.xml")
}
}
Expand Down Expand Up @@ -67,4 +110,4 @@ impl<'a> IntoIterator for &'a SubFamily {
fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
self.mcus.iter()
}
}
}
Loading