diff options
Diffstat (limited to 'docs/pages/developer_stm32.adoc')
| -rw-r--r-- | docs/pages/developer_stm32.adoc | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/docs/pages/developer_stm32.adoc b/docs/pages/developer_stm32.adoc new file mode 100644 index 000000000..7c04ab1a4 --- /dev/null +++ b/docs/pages/developer_stm32.adoc | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | = Developer Documentation: STM32 | ||
| 2 | |||
| 3 | == Understanding metapac | ||
| 4 | |||
| 5 | When a project that imports `embassy-stm32` is compiled, that project selects the feature corresponding to the chip that project is using. Based on that feature, `embassy-stm32` selects supported link:https://anysilicon.com/ip-intellectual-property-core-semiconductors/[IP] for the chip, and enables the corresponding HAL implementations. But how does `embassy-stm32` know what IP the chip contains, out of the hundreds of chips that we support? It's a long story that starts with `stm32-data-sources`. | ||
| 6 | |||
| 7 | == `stm32-data-sources` | ||
| 8 | |||
| 9 | link:https://github.com/embassy-rs/stm32-data-sources[`stm32-data-sources`] is as mostly barren repository. It has no README, no documentation, and few watchers. But it's the core of what makes `embassy-stm32` possible. The data for every chip that we support is taken in part from a corresponding XML file like link:https://github.com/embassy-rs/stm32-data-sources/blob/b8b85202e22a954d6c59d4a43d9795d34cff05cf/cubedb/mcu/STM32F051K4Ux.xml[`STM32F051K4Ux.xml`]. In that file, you'll see lines like the following: | ||
| 10 | |||
| 11 | [source,xml] | ||
| 12 | ---- | ||
| 13 | <IP InstanceName="I2C1" Name="I2C" Version="i2c2_v1_1_Cube"/> | ||
| 14 | <!-- snip --> | ||
| 15 | <IP ConfigFile="TIM-STM32F0xx" InstanceName="TIM1" Name="TIM1_8F0" Version="gptimer2_v2_x_Cube"/> | ||
| 16 | ---- | ||
| 17 | |||
| 18 | These lines indicate that this chip has an i2c, and that it's version is "v1_1". It also indicates that it has a general purpose timer that with a version of "v2_x". From this data, it's possible to determine which implementations should be included in `embassy-stm32`. But actually doing that is another matter. | ||
| 19 | |||
| 20 | |||
| 21 | == `stm32-data` | ||
| 22 | |||
| 23 | While all users of this project are familiar with `embassy-stm32`, fewer are familiar with the project that powers it: `stm32-data`. This project doesn't just aim to generate data for `embassy-stm32`, but for machine consumption in general. To acheive this, information from multiple files from the `stm32-data-sources` project are combined and parsed to assign register block implementations for each supported IP. The core of this matching resides in `chips.rs`: | ||
| 24 | |||
| 25 | [source,rust] | ||
| 26 | ---- | ||
| 27 | (".*:I2C:i2c2_v1_1", ("i2c", "v2", "I2C")), | ||
| 28 | // snip | ||
| 29 | (r".*TIM\d.*:gptimer.*", ("timer", "v1", "TIM_GP16")), | ||
| 30 | ---- | ||
| 31 | |||
| 32 | In this case, the i2c version corresponds to our "v2" and the general purpose timer version corresponds to our "v1". Therefore, the `i2c_v2.yaml` and `timer_v1.yaml` register block implementations are assigned to those IP, respectively. The result is that these lines arr generated in `STM32F051K4.json`: | ||
| 33 | |||
| 34 | [source,json] | ||
| 35 | ---- | ||
| 36 | { | ||
| 37 | "name": "I2C1", | ||
| 38 | "address": 1073763328, | ||
| 39 | "registers": { | ||
| 40 | "kind": "i2c", | ||
| 41 | "version": "v2", | ||
| 42 | "block": "I2C" | ||
| 43 | }, | ||
| 44 | // snip | ||
| 45 | } | ||
| 46 | // snip | ||
| 47 | { | ||
| 48 | "name": "TIM1", | ||
| 49 | "address": 1073818624, | ||
| 50 | "registers": { | ||
| 51 | "kind": "timer", | ||
| 52 | "version": "v1", | ||
| 53 | "block": "TIM_ADV" | ||
| 54 | }, | ||
| 55 | // snip | ||
| 56 | } | ||
| 57 | ---- | ||
| 58 | |||
| 59 | In addition to register blocks, data for pin and RCC mapping is also generated and consumed by `embassy-stm32`. `stm32-metapac-gen` is used to package and publish the data as a crate. | ||
| 60 | |||
| 61 | |||
| 62 | == `embassy-stm32` | ||
| 63 | |||
| 64 | In the `lib.rs` file located in the root of `embassy-stm32`, you'll see this line: | ||
| 65 | |||
| 66 | [source,rust] | ||
| 67 | ---- | ||
| 68 | #[cfg(i2c)] | ||
| 69 | pub mod i2c; | ||
| 70 | ---- | ||
| 71 | |||
| 72 | And in the `mod.rs` of the i2c mod, you'll see this: | ||
| 73 | |||
| 74 | [source,rust] | ||
| 75 | ---- | ||
| 76 | #[cfg_attr(i2c_v2, path = "v2.rs")] | ||
| 77 | ---- | ||
| 78 | |||
| 79 | Because i2c is supported for STM32F051K4 and its version corresponds to our "v2", the `i2c` and `i2c_v2`, configuration directives will be present, and `embassy-stm32` will include these files, respectively. This and other configuration directives and tables are generated from the data for chip, allowing `embassy-stm32` to expressively and clearly adapt logic and implementations to what is required for each chip. Compared to other projects across the embedded ecosystem, `embassy-stm32` is the only project that can re-use code across the entire stm32 lineup and remove difficult-to-implement unsafe logic to the HAL. \ No newline at end of file | ||
