From 35380ae9e4dc98f04165314e14a6731afaa13790 Mon Sep 17 00:00:00 2001 From: pellico Date: Thu, 4 Apr 2024 18:09:46 +0200 Subject: [PATCH] First commit --- .gitignore | 4 + CODE_OF_CONDUCT.md | 133 + CONTRIBUTING.md | 32 + Cargo.lock | 1261 ++ Cargo.toml | 46 + LICENSE.txt | 13 + README.md | 437 + build.rs | 10 + deny.toml | 272 + rust-toolchain.toml | 3 + src/lib.rs | 543 + src/main.rs | 5 + src/rust_gen.rs | 598 + src/rust_gen/ir.rs | 156 + src/rust_gen/util.rs | 71 + src/rust_gen/xml2ir.rs | 447 + src/rust_gen/xml2ir/svd2temp.rs | 221 + src/svd_util.rs | 41 + templates/rust/Cargo_toml.tera | 51 + templates/rust/aurix_core.tera | 37 + templates/rust/build_cortex.tera | 16 + templates/rust/common.tera | 782 ++ templates/rust/device_x.tera | 5 + templates/rust/lib.tera | 183 + templates/rust/macros.tera | 183 + templates/rust/peri_mod.tera | 37 + templates/rust/reg_name.tera | 29 + templates/rust/tracing.tera | 229 + test_svd/simple.xml | 821 ++ test_svd/simple_csfr.svd | 11708 ++++++++++++++++ test_svd/svd.xsd | 645 + tests/common/mod.rs | 74 + tests/reference_gen_code/simple.txt | 101 + tests/resources/LICENSE.txt | 3 + .../project_files_aurix/.cargo/config.toml | 16 + .../linker-scripts/tc39xB_memory.ld | 110 + .../linker-scripts/tc39x_bsp_example_llvm.ld | 671 + .../project_files_aurix/rust-toolchain.toml | 3 + .../project_files_aurix/src/bin/main.rs | 97 + .../tc162-rt/.cargo/config | 12 + .../project_files_aurix/tc162-rt/.gitignore | 2 + .../project_files_aurix/tc162-rt/Cargo.toml | 8 + .../project_files_aurix/tc162-rt/README.md | 15 + .../project_files_aurix/tc162-rt/src/lib.rs | 588 + .../project_files_cortex_m/.cargo/config.toml | 15 + .../project_files_cortex_m/Cargo.toml | 6 + .../cortex_test/Cargo.toml | 15 + .../cortex_test/build.rs | 18 + .../cortex_test/memory.x | 31 + .../cortex_test/src/bin/main.rs | 58 + .../project_files_generic/src/bin/main.rs | 96 + .../project_files_tracing/src/bin/main.rs | 121 + tests/test_basic_svd_aurix.rs | 116 + tests/test_basic_svd_cortex_m.rs | 34 + tests/test_basic_svd_generic.rs | 73 + tests/test_basic_svd_tracing.rs | 67 + 56 files changed, 21369 insertions(+) create mode 100644 .gitignore create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 build.rs create mode 100644 deny.toml create mode 100644 rust-toolchain.toml create mode 100644 src/lib.rs create mode 100644 src/main.rs create mode 100644 src/rust_gen.rs create mode 100644 src/rust_gen/ir.rs create mode 100644 src/rust_gen/util.rs create mode 100644 src/rust_gen/xml2ir.rs create mode 100644 src/rust_gen/xml2ir/svd2temp.rs create mode 100644 src/svd_util.rs create mode 100644 templates/rust/Cargo_toml.tera create mode 100644 templates/rust/aurix_core.tera create mode 100644 templates/rust/build_cortex.tera create mode 100644 templates/rust/common.tera create mode 100644 templates/rust/device_x.tera create mode 100644 templates/rust/lib.tera create mode 100644 templates/rust/macros.tera create mode 100644 templates/rust/peri_mod.tera create mode 100644 templates/rust/reg_name.tera create mode 100644 templates/rust/tracing.tera create mode 100644 test_svd/simple.xml create mode 100644 test_svd/simple_csfr.svd create mode 100644 test_svd/svd.xsd create mode 100644 tests/common/mod.rs create mode 100644 tests/reference_gen_code/simple.txt create mode 100644 tests/resources/LICENSE.txt create mode 100644 tests/resources/project_files_aurix/.cargo/config.toml create mode 100644 tests/resources/project_files_aurix/linker-scripts/tc39xB_memory.ld create mode 100644 tests/resources/project_files_aurix/linker-scripts/tc39x_bsp_example_llvm.ld create mode 100644 tests/resources/project_files_aurix/rust-toolchain.toml create mode 100644 tests/resources/project_files_aurix/src/bin/main.rs create mode 100644 tests/resources/project_files_aurix/tc162-rt/.cargo/config create mode 100644 tests/resources/project_files_aurix/tc162-rt/.gitignore create mode 100644 tests/resources/project_files_aurix/tc162-rt/Cargo.toml create mode 100644 tests/resources/project_files_aurix/tc162-rt/README.md create mode 100644 tests/resources/project_files_aurix/tc162-rt/src/lib.rs create mode 100644 tests/resources/project_files_cortex_m/.cargo/config.toml create mode 100644 tests/resources/project_files_cortex_m/Cargo.toml create mode 100644 tests/resources/project_files_cortex_m/cortex_test/Cargo.toml create mode 100644 tests/resources/project_files_cortex_m/cortex_test/build.rs create mode 100644 tests/resources/project_files_cortex_m/cortex_test/memory.x create mode 100644 tests/resources/project_files_cortex_m/cortex_test/src/bin/main.rs create mode 100644 tests/resources/project_files_generic/src/bin/main.rs create mode 100644 tests/resources/project_files_tracing/src/bin/main.rs create mode 100644 tests/test_basic_svd_aurix.rs create mode 100644 tests/test_basic_svd_cortex_m.rs create mode 100644 tests/test_basic_svd_generic.rs create mode 100644 tests/test_basic_svd_tracing.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b3658fd --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target +/generated_code/ +/lcov.info + diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..20bcc4f --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,133 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[INSERT CONTACT METHOD]. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..fb98a5d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,32 @@ +# Contributing Guidelines + +Thank you for your interest in contributing to our project! Please take a moment to review these guidelines before diving in. + +## Getting Started + +1. Fork the repository +2. Clone the forked repository to your local machine +3. Create a new branch for your features or bug fixes +4. Make the changes to your branch +5. Run all available tests to ensure that your changes do not break the existing functionality +6. Push your changes to your forked repository +7. Submit a pull request to the original repository + +## Guidelines + +- Follow the existing code style and conventions +- Write clear commit messages +- Write tests for your code changes +- Update documentation as necessary +- Be respectful and welcoming to others in the community +- Use descriptive names for your branches and pull requests + +## Code of Conduct + +Please read and abide by our [Code of Conduct](CODE_OF_CONDUCT.md) + +## License + +By contributing to this project, you agree that your contributions will be licensed under the project's [LICENSE](LICENSE.txt). + +If you have any questions or need further assistance, please don't hesitate to reach out to us. We appreciate your contributions! diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..cf7a833 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1261 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bstr" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" + +[[package]] +name = "cc" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "windows-targets", +] + +[[package]] +name = "chrono-tz" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59ae0466b83e838b81a54256c39d5d7c20b9d7daa10510a242d9b75abd5936e" +dependencies = [ + "chrono", + "chrono-tz-build", + "phf", +] + +[[package]] +name = "chrono-tz-build" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f" +dependencies = [ + "parse-zoneinfo", + "phf", + "phf_codegen", +] + +[[package]] +name = "clap" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "deunicode" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6e854126756c496b8c81dec88f9a706b15b875c5849d4097a3854476b9fdf94" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "globset" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags 1.3.2", + "ignore", + "walkdir", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "humansize" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" +dependencies = [ + "libm", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ignore" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is-terminal" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy-regex" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d12be4595afdf58bd19e4a9f4e24187da2a66700786ff660a418e9059937a4c" +dependencies = [ + "lazy-regex-proc_macros", + "once_cell", + "regex", +] + +[[package]] +name = "lazy-regex-proc_macros" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44bcd58e6c97a7fcbaffcdc95728b393b8d98933bfadad49ed4097845b57ef0b" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +dependencies = [ + "serde", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "parse-zoneinfo" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" +dependencies = [ + "regex", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73541b156d32197eecda1a4014d7f868fd2bcb3c550d5386087cfba442bf69c" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c35eeed0a3fab112f75165fdc026b3913f4183133f19b49be773ac9ea966e8bd" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2adbf29bb9776f28caece835398781ab24435585fe0d4dc1374a61db5accedca" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "roxmltree" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" + +[[package]] +name = "rustix" +version = "0.38.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "similar" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slug" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bd94acec9c8da640005f8e135a39fc0372e74535e6b368b7a04b875f784c8c4" +dependencies = [ + "deunicode", + "wasm-bindgen", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "svd-parser" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d17a2c2ef5aa450e80d714232a5932e7d8a39cac092e9e9ef8411bc833de3c4" +dependencies = [ + "anyhow", + "roxmltree", + "svd-rs", + "thiserror", +] + +[[package]] +name = "svd-rs" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aea8090314157cc490b559da0c66f2228c066b56154f0321ad83b459a0a8278" +dependencies = [ + "once_cell", + "regex", + "thiserror", +] + +[[package]] +name = "svd2pac" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "convert_case", + "env_logger", + "fs_extra", + "lazy-regex", + "linked-hash-map", + "log", + "serde", + "serde_json", + "similar", + "svd-parser", + "syn", + "tempfile", + "tera", + "thiserror", + "toml_edit", +] + +[[package]] +name = "syn" +version = "2.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys", +] + +[[package]] +name = "tera" +version = "1.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "970dff17c11e884a4a09bc76e3a17ef71e01bb13447a11e85226e254fe6d10b8" +dependencies = [ + "chrono", + "chrono-tz", + "globwalk", + "humansize", + "lazy_static", + "percent-encoding", + "pest", + "pest_derive", + "rand", + "regex", + "serde", + "serde_json", + "slug", + "unic-segment", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" +dependencies = [ + "unic-ucd-segment", +] + +[[package]] +name = "unic-ucd-segment" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e34556e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "svd2pac" +version = "0.1.0" +edition = "2021" +rust-version = "1.70" +categories = ["command-line-utilities", "development-tools::ffi"] +readme = "README.md" +homepage = "tbd" +keywords = ["generator","svd", "pac"] +license = "MIT" +description = "Tool to generate peripheral access crates from SVD files" +publish = false # to be removed before publishing + +[dependencies] +anyhow = "1.0.70" +lazy-regex = "3.0" +thiserror = "1.0.40" +svd-parser = { version = "0.14", features = ["derive-from", "expand"] } +tera = "1.19.0" +clap = { version = "4.2.4", features = ["derive", "cargo"] } +log = { version = "0.4.17", features = ["std"] } +env_logger = "0.10.0" +convert_case = "0.6" +serde_json = "1.0.96" +serde = { version = "1.0.160", features = ["derive"] } +syn = "2.0.33" +linked-hash-map = {version="0.5",features =["serde_impl"]} + + +[dev-dependencies] +similar = "2.2" +fs_extra = "1.3" +tempfile = "3.6" +toml_edit = "0.19" + +[profile.dev.package."*"] +codegen-units = 1 # better optimizations +opt-level = 3 + +[lib] +path = "src/lib.rs" # This just make happy cargo-readme +doctest = false + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc"] + diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..b36ef3d --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,13 @@ +Copyright (c) 2024 Infineon Technologies AG + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE diff --git a/README.md b/README.md new file mode 100644 index 0000000..5625c20 --- /dev/null +++ b/README.md @@ -0,0 +1,437 @@ +# svd2pac + +Tool to generate Peripheral Access Crates from SVD files + +## Why another PAC generator ? + +This tool has a very different approach compared to `svd2rust` and it is inspired by [chiptool](https://github.com/embassy-rs/chiptool). + +### Motivation + +- Register access should be unsafe because we consider it as C FFI and many times theres HW undefined behaviour that can be solved + only at driver level. (e.g. sometimes also the order of writing register bitfields is important. + discussion on this topic available here ). +- No ownership because owned registers are an obstacle to writing low level drivers (LLD). Anyway writing + LLDs requires a lot of unsafe code and ownership makes it more complex to access registers from interrupts + and other threads. LLDs shall present safe APIs because only they can implement all logic for a safe usage of peripherals. +- Support [tracing](#tracing) of register accesses and additionally mocking of registers on non-embedded devices through + external libraries. This allows the execution unit tests for code that uses the generated libraries on non-embedded devices. +- PAC shall have ideally 0 dependencies to any other crates. + +## chiptool features implemented by `svd2pac` + +- No owned data structure -> unsafe api that can be used from any interrupts or thread. +- Register values are represented by structs. No write to register when updating a bitfield. +- Enumerated values are represented with a struct + associated constants. +- Essentially same API to access registers that chiptool uses. +- Logging of register accesses. + +## Major differences to chiptool + +- Support for modify atomic assembly instruction (only Aurix). +- Bitfields are structs with setters and getters. This prevents naming conflicts with bitfield names like `set_xxx`. +- Bitfield setters consume the register struct and support a fluent api. Lower coding in closure. +- Support for the "Cluster" tag in SVD files. +- Support also for 8,16,64 bit size registers. +- Avoid long type and bitfield names (chiptool concatenates identifiers) by generating modules for registers and svd clusters. +- No support for SVD transformation. + +## Limitations + +* Inheritance via `derivedFrom` attribute is supported only in `cluster` declaration and requires + that child is not overriding anything except `name`, `description` and `offset` +* `headerStructName` tag is considered only in `cluster`` tag +* `resetMask` tag is ignored +* `protection` tag is ignored +* `writeConstraint` tag is ignored +* `modifiedWriteValues` tag is ignored +* `readAction` tag is ignored +* `headerEnumName` tag is ignored +* in `enumeratedValue` only `value` tag is supported. No support for _don't care bits_ and `isDefault` tag + +## How to install & prerequisite + +```bash +cargo install cargo-svd2pac +``` + +if automatic code formatting is desired install `rustfmt`. + +```bash +rustup component add rustfmt +``` + + +## How to use the tool + +Get a full overview for all cli flags: +```bash +svd2pac -h +``` + +Generate PAC without any platform specific code: +```bash +svd2pac +``` + +To generated Aurix PACs use: +```bash +svd2pac --target aurix +``` + +By default `svd2pac` performs strict validation of svd files. + +It is possible to relax or disable svd validation by using option `--svd-validation-level` +```bash +svd2pac --svd-validation-level weak +``` +### Notable CLI flags + +--- +#### Select target :`--target` option +This option allows to have target specific code generation + +##### `--target=generic` +This target allows generation of generic code that is independent from any architecture. +It ignores nvicPrioBits, fpuPresent,mpuPresent, vendorSystickConfig attributes and interrupt tag. + +##### `--target=aurix` + +Generate the PAC with Aurix platform specific `lmst` instruction support in addition to +normal `read/write` instructions. + +##### `--target=cortex-m` + +The purpose of this option is generating a PAC that can be used with common cortex-m framework as RTIC. +Developer can use CPU register with same API generated by `svd2rust` but for peripheral he shall use the API of `svd2pac` +In this way he can reuse the code related to CPU and develop peripheral driver using `svd2pac` style. + +Extra feature compared to `generic` target + +- Re-export of cortex-m core peripherals +- Peripherals type but now it is possible to call Peripheral::take without limitations. +- Interrupt table + +#### Enable register mocking: `--tracing` option +Enable with the `--tracing` cli flag. +Generate the PAC with a non-default feature flag to allow for tracing reads/writes, [see below](#tracing-feature) + +## How to use the generated code + +The generator outputs a complete crate into the provided folder. +In the generated PACs all peripherals modules are gated by a feature and therefore by default no peripheral modules is compiled. +This is speed-up the compilation process. The `features=["all"]` enable the compilations of all modules. + +### Naming + +Some examples showing naming/case, given the timer module in `test_svd/simple.xml`: +- `TIMER` instance of a module struct for a peripheral called "timer" +- `timer::Timer` type of the module instance above +- `TIMER::bitfield_reg()` access function for a register +- `timer::bitfield_reg` module containing bitfield structs for the "BITFIELD_REG" register +- `timer::bitfield_reg::Run` module containing enumeration values for the "RUN" bitfield +- `timer::bitfield_reg::Run::RUNNING` bitfield value constant + +### Examples + +>**Note** +> +>The following examples are based on the `test_svd/simple.xml` svd used for testing. +>In this example we mostly use a `TIMER` module with a few registers, among them: +>- `SR` a status register that is mostly read-only +>- `BITFIELD_REG` which is a register with multiple bitfields +>- `NONBITFIELD_REG`, a register without bitfields + +#### Read + +A register is read using the `.read()` function. It returns a struct with convenient functions to access +bitfield values. Each bitfield is represented by a struct that is optimized away, the actual values can +be retrieved by calling `.get()` + +```rust +use test_pac::{timer, TIMER}; + +// Read register `SR` and check `RUN` bitfield +let status = unsafe { TIMER.sr().read() }; +if status.run().get() == timer::sr::Run::RUNNING { /* do something */ } + +// Access bitfield directly inline +while unsafe { TIMER.sr().read().run().get() == timer::sr::Run::RUNNING } { /* ... */ } + +// Check bitfield with enumeration +// (r# as prefix must be used here since `match` is a rust keyword) +match unsafe { TIMER.sr().read().r#match().get() } { + timer::sr::Match::NO_MATCH => (), + timer::sr::Match::MATCH_HIT => (), + // since .get() returns a struct, match does not recognize + // an exhaustive match and a wildcard is needed + _ => panic!("impossible"), +} + +// a register might not have a bitfield at all, then we access the value directly +let numeric_value = unsafe { TIMER.prescale_rd().read() }; +``` + +#### Modify (read/modify/write) + +The `modify` function takes a closure/function that is passed to the current register value. +The closure must modify the passed value and return the value to be written. + +```rust +use test_pac::{timer, TIMER} + +// read `BITFIELD_REG` register, set `BoolRw` to true, `BitfieldRw` to 0x3, +// then write back to register +unsafe { + TIMER + .bitfield_reg() + .modify(|r| r.boolrw().set(true).bitfieldrw().set(0x3)) +} + +// write with dynamic value and enum +let x: bool = get_some_bool_value(); +unsafe { + TIMER.bitfield_reg().modify(|r| { + r.bitfieldenumerated() + .set(timer::bitfield_reg::BitfieldEnumerated::GPIOA_6) + .boolrw() + .set(x) + }) +} +``` +> Note: The register is not modified when the `set()` function is called. `set()` modifies the value + stored in the CPU and returns the modified struct. The register is only written once with + the value returned by the closure. + +> Note: `modify()`, due to doing a read and write with modification of read data in between is not + atomic and can be subject to race conditions and may be interrupted by an interrupt. + +#### Write + +A register can be written with an instance of the appropriate struct. The struct instance can be obtained +from a read by calling `.default()` (to start off with the register default value) or from a previous +register read/write. + +```rust +use test_pac::{timer, TIMER} + +// start with default value, configure some stuff and write to +// register. +let reg = timer::BitfieldReg::default() + .bitfieldrw() + .set(1) + .boolw() + .set(true); +unsafe { TIMER.bitfield_reg().write(reg) }; + +/* do some other initialization */ + +// set `BoolRw` in addition to the settings before and write that +// note that .set() returns a new instance of the BitfieldReg struct +// with the old being consumed +// additional changes could be chained after .set() as above +let reg = reg.boolrw().set(true); +unsafe { TIMER.bitfield_reg().write(reg) }; +``` + +#### Initialization & write-only registers + +`.init()` allows for the same functionality as `.write()`, but it is limited to start with the register +default value. It can also be used as a shorthand for write-only registers. + +The closure passed to the `.init()` function gets the default value as input and writes back +the return value of the closure to the register. + +```rust +use test_pac::{timer, TIMER} + +// do some initializations, write `BoolW` and `BoolRW` with given values, +// write others with defaults +unsafe { + TIMER + .bitfield_reg() + .init(|r| r.boolw().set(true).boolrw().set(false)) +} + +// use init also for write-only registers +unsafe { + TIMER.int().init(|r| { + r.en() + .set(timer::int::En::ENABLE) + .mode() + .set(timer::int::Mode::OVERFLOW) + }) +}; +``` +#### Combine all the things +Especially the read and write functionality can be combined, e.g. + +```rust +let status = unsafe { TIMER.bitfield_reg().read() }; +if status.boolr().get() { + let modified = status.boolrw().set(true); + unsafe { TIMER.bitfield_reg().write(modified) } +} +``` + +#### Raw access +For use cases like logging, initializing from a table, etc. it is +possible to read/write registers as plain integers. + +```rust +// get register value as integer value +let to_log:u32 = unsafe { TIMER.sr().read().get_raw() }; + +// write register with integer value, e.g. read from table +unsafe { TIMER.bitfield_reg().modify(|r| r.set_raw(0x1234)) }; +``` + +#### Modify Atomic (only Aurix) +This function is available only for Aurix microcontrollers. It uses the `ldmst` instruction +to read-modify-write a value in a register. This instruction blocks the bus until the end of +the transaction. Therefore it affects the other masters on the bus. + +```rust +TIMER.bitfield_reg().modify_atomic(|f| { + f.bitfieldenumerated() + .set(bitfield_reg::BitfieldEnumerated::GPIOA_0) + .bitfieldw() + .set(3) +}); +``` +Code generation for Aurix is enabled using `--target aurix ` + +#### Array of peripherals + +SVD arrays of peripherals are modeled using Rust arrays. + +```rust +for peri in UART { + unsafe { + peri.reg16bitenum().modify(|r| { + r.bitfield9bitsenum() + .set(uart::reg16bitenum::Bitfield9BitsEnum::VAL_0) + }) + }; +} +``` + +#### Array of registers +Arrays of registers are modeled as an array of register structs in the module. + +```rust +let reg_array = TIMER.arrayreg(); +for reg in reg_array { + let reg_val = unsafe { r.read() }; + let old_val = reg_val.get(); + unsafe { r.write(reg_val.set(old_val + 1)) }; +} +``` + +#### Array of bitfields +Arrays of bitfields are modeled as an array of bitfield structs in the register. + +```rust + let mut reg_value = unsafe { TIMER.bitfield_reg().read() }; + for x in 0..2 { + reg_value = reg_value.fieldarray(x).set(bitfield_reg::FieldArray::FALLING); + } + unsafe { TIMER.bitfield_reg().write(reg_value) }; +``` + +#### Write an enumerated bitfield by passing an integer literal +The size of value cannot exceed bit field size. +Here the associated struct type can be created from the integer, +as the `From` trait implementation is available for the bitfield structure. + +```rust +TIMER.bitfield_reg().modify(|f| { + f.bitfieldenumerated() + .set(0.into()) +}); +``` + +#### Get mask and offset of a bitfield +It is possible to get mask and offset of a single bitfield using `mask` and `offset`. The returned mask is aligned to the LSB and not shifted (i.e. a 3-bit wide field has a mask of `0x7`, independent of position of the field). +```rust + let register_bitfield = TIMER.bitfield_reg().read().bitfieldr(); + let _offset = register_bitfield.offset(); + let _mask = register_bitfield.mask(); +``` + +## Tracing feature +When generating the PAC with the `--tracing` cli-flag, the PAC is generated with +an optional feature flag `tracing`. Enabling the feature provides the following +additional functionalities: +- an interface where register accesses can be piped though, enabling + developers to log accesses to registers or even mock registers outright. + An implementation of that interface for unittests will be published in the near future. +- a special `RegisterValue` trait that allows constructing values of + registers from integers. +- an additional `insanely_unsafe` module which allows reading and writing, write-only and + read-only registers (intended for mocking state in tests). +- an additional `reg_name` module that contains a perfect hash map of physical + addresses to string names of all registers that reside at an address. + +`tracing` is intended for testing, etc. on a host machine and uses additional +crates that are not embedded-friendly. + +The second feature flag that is added is `tracing_dummy`. By default tracing requires +callbacks to be registered for logging. If no callbacks are registered the code will +panic. If `tracing_dummy` is enabled the code will not panic and silently drop logs +if no callbacks are registerd. + +### Examples +Below, some simple examples on how to use the tracing APIs are shown. +For a more complete example + +#### Construcing a register value from a raw value with tracing +When implementing tests using the tracing feature we want to be +able to provide arbitrary data during those tests. + +```rust +use pac::common::RegisterValue; +let value = pac::peripheral::register::new(0xC0FFEE); +unsafe{ pac::PERIPHERAL.register().write(value) }; +``` + +#### Reading a value from a **write-only** register with tracing +Again for testing: in a testcase we need to do the exact opposite +of what normal code does, i.e. we need to "write" read-only registers +and "read" write-only registers. + +Tracing provides a backdoor to allow those actions that are not +allowed in normal code. + +```rust +use pac::tracing::insanely_unsafe; +let value = unsafe{ pac::PERIPHERAL.write_only_register().read_write_only() }; +``` + +#### Get the names of registers at a specific address +For better logging a map of address to name translation is generated/available +if tracing is enabled. + +```rust +let regs_at_c0ffee = pac::reg_name::reg_name_from_addr(0xC0FFEE); +println!("{regs_at_c0ffee:?}"); +``` + + +## Running tests + +To execute the tests it is required to add as target "thumbv7em-none-eabihf". +This can be done using +```bash +rustup target add thumbv7em-none-eabihf +``` + +To test the generation of Aurix PAC it is necessary to install Hightec Rust Aurix compiler and select it as default compiler. +`build.rs` detects automatically the toolchain and add the configuration option to enable Aurix specific tests. + +## Credits + +A small portion of template common.tera is copied from +[Link to commit from where code has been copies](https://github.com/embassy-rs/chiptool/commit/4834a9b35982b393beae84a04960c9add886c1f7) + +License: MIT diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..31a1178 --- /dev/null +++ b/build.rs @@ -0,0 +1,10 @@ +use std::env; +const RUSTUP_TOOLCHAIN_ID: &str = "RUSTUP_TOOLCHAIN"; +fn main() { + // In case of Aurix toolchain enable test of code generated for Aurix microcontroller + let rustup_toolchain = env::var(RUSTUP_TOOLCHAIN_ID) + .unwrap_or_else(|_| format!("Unable to to get environment variable {RUSTUP_TOOLCHAIN_ID}")); + if rustup_toolchain.contains("tricore") { + println!("cargo:rustc-cfg=aurix_tests"); + } +} diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..0bc908a --- /dev/null +++ b/deny.toml @@ -0,0 +1,272 @@ +# This template contains all of the possible sections and their default values + +# Note that all fields that take a lint level have these possible values: +# * deny - An error will be produced and the check will fail +# * warn - A warning will be produced, but the check will not fail +# * allow - No warning or error will be produced, though in some cases a note +# will be + +# The values provided in this template are the default values that will be used +# when any section or field is not specified in your own configuration + +# Root options + +# If 1 or more target triples (and optionally, target_features) are specified, +# only the specified targets will be checked when running `cargo deny check`. +# This means, if a particular package is only ever used as a target specific +# dependency, such as, for example, the `nix` crate only being used via the +# `target_family = "unix"` configuration, that only having windows targets in +# this list would mean the nix crate, as well as any of its exclusive +# dependencies not shared by any other crates, would be ignored, as the target +# list here is effectively saying which targets you are building for. +targets = [ + # The triple can be any string, but only the target triples built in to + # rustc (as of 1.40) can be checked against actual config expressions + #{ triple = "x86_64-unknown-linux-musl" }, + # You can also specify which target_features you promise are enabled for a + # particular target. target_features are currently not validated against + # the actual valid features supported by the target architecture. + #{ triple = "wasm32-unknown-unknown", features = ["atomics"] }, +] +# When creating the dependency graph used as the source of truth when checks are +# executed, this field can be used to prune crates from the graph, removing them +# from the view of cargo-deny. This is an extremely heavy hammer, as if a crate +# is pruned from the graph, all of its dependencies will also be pruned unless +# they are connected to another crate in the graph that hasn't been pruned, +# so it should be used with care. The identifiers are [Package ID Specifications] +# (https://doc.rust-lang.org/cargo/reference/pkgid-spec.html) +#exclude = [] +# If true, metadata will be collected with `--all-features`. Note that this can't +# be toggled off if true, if you want to conditionally enable `--all-features` it +# is recommended to pass `--all-features` on the cmd line instead +all-features = false +# If true, metadata will be collected with `--no-default-features`. The same +# caveat with `all-features` applies +no-default-features = false +# If set, these feature will be enabled when collecting metadata. If `--features` +# is specified on the cmd line they will take precedence over this option. +#features = [] +# When outputting inclusion graphs in diagnostics that include features, this +# option can be used to specify the depth at which feature edges will be added. +# This option is included since the graphs can be quite large and the addition +# of features from the crate(s) to all of the graph roots can be far too verbose. +# This option can be overridden via `--feature-depth` on the cmd line +feature-depth = 1 + +# This section is considered when running `cargo deny check advisories` +# More documentation for the advisories section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html +[advisories] +# The path where the advisory database is cloned/fetched into +db-path = "~/.cargo/advisory-db" +# The url(s) of the advisory databases to use +db-urls = ["https://github.com/rustsec/advisory-db"] +# The lint level for security vulnerabilities +vulnerability = "deny" +# The lint level for unmaintained crates +unmaintained = "warn" +# The lint level for crates that have been yanked from their source registry +yanked = "warn" +# The lint level for crates with security notices. Note that as of +# 2019-12-17 there are no security notice advisories in +# https://github.com/rustsec/advisory-db +notice = "warn" +# A list of advisory IDs to ignore. Note that ignored advisories will still +# output a note when they are encountered. +ignore = [ + #"RUSTSEC-0000-0000", +] +# Threshold for security vulnerabilities, any vulnerability with a CVSS score +# lower than the range specified will be ignored. Note that ignored advisories +# will still output a note when they are encountered. +# * None - CVSS Score 0.0 +# * Low - CVSS Score 0.1 - 3.9 +# * Medium - CVSS Score 4.0 - 6.9 +# * High - CVSS Score 7.0 - 8.9 +# * Critical - CVSS Score 9.0 - 10.0 +#severity-threshold = + +# If this is true, then cargo deny will use the git executable to fetch advisory database. +# If this is false, then it uses a built-in git library. +# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support. +# See Git Authentication for more information about setting up git authentication. +#git-fetch-with-cli = true + +# This section is considered when running `cargo deny check licenses` +# More documentation for the licenses section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html +[licenses] +# The lint level for crates which do not have a detectable license +unlicensed = "deny" +# List of explicitly allowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. +allow = [ + "MIT", + "Apache-2.0", + "Unicode-DFS-2016", + "BSD-3-Clause" +] +# List of explicitly disallowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. +deny = [ + #"Nokia", +] +# Lint level for licenses considered copyleft +copyleft = "warn" +# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses +# * both - The license will be approved if it is both OSI-approved *AND* FSF +# * either - The license will be approved if it is either OSI-approved *OR* FSF +# * osi - The license will be approved if it is OSI approved +# * fsf - The license will be approved if it is FSF Free +# * osi-only - The license will be approved if it is OSI-approved *AND NOT* FSF +# * fsf-only - The license will be approved if it is FSF *AND NOT* OSI-approved +# * neither - This predicate is ignored and the default lint level is used +allow-osi-fsf-free = "neither" +# Lint level used when no other predicates are matched +# 1. License isn't in the allow or deny lists +# 2. License isn't copyleft +# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither" +default = "deny" +# The confidence threshold for detecting a license from license text. +# The higher the value, the more closely the license text must be to the +# canonical license text of a valid SPDX license file. +# [possible values: any between 0.0 and 1.0]. +confidence-threshold = 0.8 +# Allow 1 or more licenses on a per-crate basis, so that particular licenses +# aren't accepted for every possible crate as with the normal allow list +exceptions = [ + # Each entry is the crate and version constraint, and its specific allow + # list + #{ allow = ["Zlib"], name = "adler32", version = "*" }, +] + +# Some crates don't have (easily) machine readable licensing information, +# adding a clarification entry for it allows you to manually specify the +# licensing information +#[[licenses.clarify]] +# The name of the crate the clarification applies to +#name = "ring" +# The optional version constraint for the crate +#version = "*" +# The SPDX expression for the license requirements of the crate +#expression = "MIT AND ISC AND OpenSSL" +# One or more files in the crate's source used as the "source of truth" for +# the license expression. If the contents match, the clarification will be used +# when running the license check, otherwise the clarification will be ignored +# and the crate will be checked normally, which may produce warnings or errors +# depending on the rest of your configuration +#license-files = [ + # Each entry is a crate relative path, and the (opaque) hash of its contents + #{ path = "LICENSE", hash = 0xbd0eed23 } +#] + +[licenses.private] +# If true, ignores workspace crates that aren't published, or are only +# published to private registries. +# To see how to mark a crate as unpublished (to the official registry), +# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field. +ignore = false +# One or more private registries that you might publish crates to, if a crate +# is only published to private registries, and ignore is true, the crate will +# not have its license(s) checked +registries = [ + #"https://sekretz.com/registry +] + +# This section is considered when running `cargo deny check bans`. +# More documentation about the 'bans' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html +[bans] +# Lint level for when multiple versions of the same crate are detected +multiple-versions = "warn" +# Lint level for when a crate version requirement is `*` +wildcards = "allow" +# The graph highlighting used when creating dotgraphs for crates +# with multiple versions +# * lowest-version - The path to the lowest versioned duplicate is highlighted +# * simplest-path - The path to the version with the fewest edges is highlighted +# * all - Both lowest-version and simplest-path are used +highlight = "all" +# The default lint level for `default` features for crates that are members of +# the workspace that is being checked. This can be overridden by allowing/denying +# `default` on a crate-by-crate basis if desired. +workspace-default-features = "allow" +# The default lint level for `default` features for external crates that are not +# members of the workspace. This can be overridden by allowing/denying `default` +# on a crate-by-crate basis if desired. +external-default-features = "allow" +# List of crates that are allowed. Use with care! +allow = [ + #{ name = "ansi_term", version = "=0.11.0" }, +] +# List of crates to deny +deny = [ + # Each entry the name of a crate and a version range. If version is + # not specified, all versions will be matched. + #{ name = "ansi_term", version = "=0.11.0" }, + # + # Wrapper crates can optionally be specified to allow the crate when it + # is a direct dependency of the otherwise banned crate + #{ name = "ansi_term", version = "=0.11.0", wrappers = [] }, +] + +# List of features to allow/deny +# Each entry the name of a crate and a version range. If version is +# not specified, all versions will be matched. +#[[bans.features]] +#name = "reqwest" +# Features to not allow +#deny = ["json"] +# Features to allow +#allow = [ +# "rustls", +# "__rustls", +# "__tls", +# "hyper-rustls", +# "rustls", +# "rustls-pemfile", +# "rustls-tls-webpki-roots", +# "tokio-rustls", +# "webpki-roots", +#] +# If true, the allowed features must exactly match the enabled feature set. If +# this is set there is no point setting `deny` +#exact = true + +# Certain crates/versions that will be skipped when doing duplicate detection. +skip = [ + #{ name = "ansi_term", version = "=0.11.0" }, +] +# Similarly to `skip` allows you to skip certain crates during duplicate +# detection. Unlike skip, it also includes the entire tree of transitive +# dependencies starting at the specified crate, up to a certain depth, which is +# by default infinite. +skip-tree = [ + #{ name = "ansi_term", version = "=0.11.0", depth = 20 }, +] + +# This section is considered when running `cargo deny check sources`. +# More documentation about the 'sources' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html +[sources] +# Lint level for what to happen when a crate from a crate registry that is not +# in the allow list is encountered +unknown-registry = "warn" +# Lint level for what to happen when a crate from a git repository that is not +# in the allow list is encountered +unknown-git = "warn" +# List of URLs for allowed crate registries. Defaults to the crates.io index +# if not specified. If it is specified but empty, no registries are allowed. +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +# List of URLs for allowed Git repositories +allow-git = [] + +#[sources.allow-org] +# 1 or more github.com organizations to allow git sources for +#github = ["Infineon"] +# 1 or more gitlab.com organizations to allow git sources for +#gitlab = [""] +# 1 or more bitbucket.org organizations to allow git sources for +#bitbucket = [""] diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..5c602d4 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +components = [ "rustfmt", "clippy","llvm-tools","rust-analyzer" ] +targets = ["thumbv7em-none-eabihf"] # Required to test cortex-m code generation target \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..0e95b9c --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,543 @@ +//! Tool to generate Peripheral Access Crates from SVD files +//! +//! # Why another PAC generator ? +//! +//! This tool has a very different approach compared to `svd2rust` and it is inspired by [chiptool](https://github.com/embassy-rs/chiptool). +//! +//! ## Motivation +//! +//! - Register access should be unsafe because we consider it as C FFI and many times theres HW undefined behaviour that can be solved +//! only at driver level. (e.g. sometimes also the order of writing register bitfields is important. +//! discussion on this topic available here ). +//! - No ownership because owned registers are an obstacle to writing low level drivers (LLD). Anyway writing +//! LLDs requires a lot of unsafe code and ownership makes it more complex to access registers from interrupts +//! and other threads. LLDs shall present safe APIs because only they can implement all logic for a safe usage of peripherals. +//! - Support [tracing](#tracing) of register accesses and additionally mocking of registers on non-embedded devices through +//! external libraries. This allows the execution unit tests for code that uses the generated libraries on non-embedded devices. +//! - PAC shall have ideally 0 dependencies to any other crates. +//! +//! # chiptool features implemented by `svd2pac` +//! +//! - No owned data structure -> unsafe api that can be used from any interrupts or thread. +//! - Register values are represented by structs. No write to register when updating a bitfield. +//! - Enumerated values are represented with a struct + associated constants. +//! - Essentially same API to access registers that chiptool uses. +//! - Logging of register accesses. +//! +//! # Major differences to chiptool +//! +//! - Support for modify atomic assembly instruction (only Aurix). +//! - Bitfields are structs with setters and getters. This prevents naming conflicts with bitfield names like `set_xxx`. +//! - Bitfield setters consume the register struct and support a fluent api. Lower coding in closure. +//! - Support for the "Cluster" tag in SVD files. +//! - Support also for 8,16,64 bit size registers. +//! - Avoid long type and bitfield names (chiptool concatenates identifiers) by generating modules for registers and svd clusters. +//! - No support for SVD transformation. +//! +//! # Limitations +//! +//! * Inheritance via `derivedFrom` attribute is supported only in `cluster` declaration and requires +//! that child is not overriding anything except `name`, `description` and `offset` +//! * `headerStructName` tag is considered only in `cluster`` tag +//! * `resetMask` tag is ignored +//! * `protection` tag is ignored +//! * `writeConstraint` tag is ignored +//! * `modifiedWriteValues` tag is ignored +//! * `readAction` tag is ignored +//! * `headerEnumName` tag is ignored +//! * in `enumeratedValue` only `value` tag is supported. No support for _don't care bits_ and `isDefault` tag +//! +//! # How to install & prerequisite +//! +//! ```bash +//! cargo install cargo-svd2pac +//! ``` +//! +//! if automatic code formatting is desired install `rustfmt`. +//! +//! ```bash +//! rustup component add rustfmt +//! ``` +//! +//! +//! # How to use the tool +//! +//! Get a full overview for all cli flags: +//! ```bash +//! svd2pac -h +//! ``` +//! +//! Generate PAC without any platform specific code: +//! ```bash +//! svd2pac +//! ``` +//! +//! To generated Aurix PACs use: +//! ```bash +//! svd2pac --target aurix +//! ``` +//! +//! By default `svd2pac` performs strict validation of svd files. +//! +//! It is possible to relax or disable svd validation by using option `--svd-validation-level` +//! ```bash +//! svd2pac --svd-validation-level weak +//! ``` +//! ## Notable CLI flags +//! +//! --- +//! ### Select target :`--target` option +//! This option allows to have target specific code generation +//! +//! #### `--target=generic` +//! This target allows generation of generic code that is independent from any architecture. +//! It ignores nvicPrioBits, fpuPresent,mpuPresent, vendorSystickConfig attributes and interrupt tag. +//! +//! #### `--target=aurix` +//! +//! Generate the PAC with Aurix platform specific `lmst` instruction support in addition to +//! normal `read/write` instructions. +//! +//! #### `--target=cortex-m` +//! +//! The purpose of this option is generating a PAC that can be used with common cortex-m framework as RTIC. +//! Developer can use CPU register with same API generated by `svd2rust` but for peripheral he shall use the API of `svd2pac` +//! In this way he can reuse the code related to CPU and develop peripheral driver using `svd2pac` style. +//! +//! Extra feature compared to `generic` target +//! +//! - Re-export of cortex-m core peripherals +//! - Peripherals type but now it is possible to call Peripheral::take without limitations. +//! - Interrupt table +//!--- +//! ### Enable register mocking: `--tracing` option +//! Enable with the `--tracing` cli flag. +//! Generate the PAC with a non-default feature flag to allow for tracing reads/writes, [see below](#tracing-feature) +//! +//! # How to use the generated code +//! +//! The generator outputs a complete crate into the provided folder. +//! In the generated PACs all peripherals modules are gated by a feature and therefore by default no peripheral modules is compiled. +//! This is speed-up the compilation process. The `features=["all"]` enable the compilations of all modules. +//! +//! ## Naming +//! +//! Some examples showing naming/case, given the timer module in `test_svd/simple.xml`: +//! - `TIMER` instance of a module struct for a peripheral called "timer" +//! - `timer::Timer` type of the module instance above +//! - `TIMER::bitfield_reg()` access function for a register +//! - `timer::bitfield_reg` module containing bitfield structs for the "BITFIELD_REG" register +//! - `timer::bitfield_reg::Run` module containing enumeration values for the "RUN" bitfield +//! - `timer::bitfield_reg::Run::RUNNING` bitfield value constant +//! +//! ## Examples +//! +//! >**Note** +//! > +//! >The following examples are based on the `test_svd/simple.xml` svd used for testing. +//! >In this example we mostly use a `TIMER` module with a few registers, among them: +//! >- `SR` a status register that is mostly read-only +//! >- `BITFIELD_REG` which is a register with multiple bitfields +//! >- `NONBITFIELD_REG`, a register without bitfields +//! +//! ### Read +//! +//! A register is read using the `.read()` function. It returns a struct with convenient functions to access +//! bitfield values. Each bitfield is represented by a struct that is optimized away, the actual values can +//! be retrieved by calling `.get()` +//! +//! ```rust,ignore +//! use test_pac::{timer, TIMER}; +//! +//! // Read register `SR` and check `RUN` bitfield +//! let status = unsafe { TIMER.sr().read() }; +//! if status.run().get() == timer::sr::Run::RUNNING { /* do something */ } +//! +//! // Access bitfield directly inline +//! while unsafe { TIMER.sr().read().run().get() == timer::sr::Run::RUNNING } { /* ... */ } +//! +//! // Check bitfield with enumeration +//! // (r# as prefix must be used here since `match` is a rust keyword) +//! match unsafe { TIMER.sr().read().r#match().get() } { +//! timer::sr::Match::NO_MATCH => (), +//! timer::sr::Match::MATCH_HIT => (), +//! // since .get() returns a struct, match does not recognize +//! // an exhaustive match and a wildcard is needed +//! _ => panic!("impossible"), +//! } +//! +//! // a register might not have a bitfield at all, then we access the value directly +//! let numeric_value = unsafe { TIMER.prescale_rd().read() }; +//! ``` +//! +//! ### Modify (read/modify/write) +//! +//! The `modify` function takes a closure/function that is passed to the current register value. +//! The closure must modify the passed value and return the value to be written. +//! +//! ```rust,ignore +//! use test_pac::{timer, TIMER} +//! +//! // read `BITFIELD_REG` register, set `BoolRw` to true, `BitfieldRw` to 0x3, +//! // then write back to register +//! unsafe { +//! TIMER +//! .bitfield_reg() +//! .modify(|r| r.boolrw().set(true).bitfieldrw().set(0x3)) +//! } +//! +//! // write with dynamic value and enum +//! let x: bool = get_some_bool_value(); +//! unsafe { +//! TIMER.bitfield_reg().modify(|r| { +//! r.bitfieldenumerated() +//! .set(timer::bitfield_reg::BitfieldEnumerated::GPIOA_6) +//! .boolrw() +//! .set(x) +//! }) +//! } +//! ``` +//! > Note: The register is not modified when the `set()` function is called. `set()` modifies the value +//! stored in the CPU and returns the modified struct. The register is only written once with +//! the value returned by the closure. +//! +//! > Note: `modify()`, due to doing a read and write with modification of read data in between is not +//! atomic and can be subject to race conditions and may be interrupted by an interrupt. +//! +//! ### Write +//! +//! A register can be written with an instance of the appropriate struct. The struct instance can be obtained +//! from a read by calling `.default()` (to start off with the register default value) or from a previous +//! register read/write. +//! +//! ```rust,ignore +//! use test_pac::{timer, TIMER} +//! +//! // start with default value, configure some stuff and write to +//! // register. +//! let reg = timer::BitfieldReg::default() +//! .bitfieldrw() +//! .set(1) +//! .boolw() +//! .set(true); +//! unsafe { TIMER.bitfield_reg().write(reg) }; +//! +//! /* do some other initialization */ +//! +//! // set `BoolRw` in addition to the settings before and write that +//! // note that .set() returns a new instance of the BitfieldReg struct +//! // with the old being consumed +//! // additional changes could be chained after .set() as above +//! let reg = reg.boolrw().set(true); +//! unsafe { TIMER.bitfield_reg().write(reg) }; +//! ``` +//! +//! ### Initialization & write-only registers +//! +//! `.init()` allows for the same functionality as `.write()`, but it is limited to start with the register +//! default value. It can also be used as a shorthand for write-only registers. +//! +//! The closure passed to the `.init()` function gets the default value as input and writes back +//! the return value of the closure to the register. +//! +//! ```rust,ignore +//! use test_pac::{timer, TIMER} +//! +//! // do some initializations, write `BoolW` and `BoolRW` with given values, +//! // write others with defaults +//! unsafe { +//! TIMER +//! .bitfield_reg() +//! .init(|r| r.boolw().set(true).boolrw().set(false)) +//! } +//! +//! // use init also for write-only registers +//! unsafe { +//! TIMER.int().init(|r| { +//! r.en() +//! .set(timer::int::En::ENABLE) +//! .mode() +//! .set(timer::int::Mode::OVERFLOW) +//! }) +//! }; +//! ``` +//! ### Combine all the things +//! Especially the read and write functionality can be combined, e.g. +//! +//! ```rust,ignore +//! let status = unsafe { TIMER.bitfield_reg().read() }; +//! if status.boolr().get() { +//! let modified = status.boolrw().set(true); +//! unsafe { TIMER.bitfield_reg().write(modified) } +//! } +//! ``` +//! +//! ### Raw access +//! For use cases like logging, initializing from a table, etc. it is +//! possible to read/write registers as plain integers. +//! +//! ```rust,ignore +//! // get register value as integer value +//! let to_log:u32 = unsafe { TIMER.sr().read().get_raw() }; +//! +//! // write register with integer value, e.g. read from table +//! unsafe { TIMER.bitfield_reg().modify(|r| r.set_raw(0x1234)) }; +//! ``` +//! +//! ### Modify Atomic (only Aurix) +//! This function is available only for Aurix microcontrollers. It uses the `ldmst` instruction +//! to read-modify-write a value in a register. This instruction blocks the bus until the end of +//! the transaction. Therefore it affects the other masters on the bus. +//! +//! ```rust,ignore +//! TIMER.bitfield_reg().modify_atomic(|f| { +//! f.bitfieldenumerated() +//! .set(bitfield_reg::BitfieldEnumerated::GPIOA_0) +//! .bitfieldw() +//! .set(3) +//! }); +//! ``` +//! Code generation for Aurix is enabled using `--target aurix ` +//! +//! ### Array of peripherals +//! +//! SVD arrays of peripherals are modeled using Rust arrays. +//! +//! ```rust,ignore +//! for peri in UART { +//! unsafe { +//! peri.reg16bitenum().modify(|r| { +//! r.bitfield9bitsenum() +//! .set(uart::reg16bitenum::Bitfield9BitsEnum::VAL_0) +//! }) +//! }; +//! } +//! ``` +//! +//! ### Array of registers +//! Arrays of registers are modeled as an array of register structs in the module. +//! +//! ```rust,ignore +//! let reg_array = TIMER.arrayreg(); +//! for reg in reg_array { +//! let reg_val = unsafe { r.read() }; +//! let old_val = reg_val.get(); +//! unsafe { r.write(reg_val.set(old_val + 1)) }; +//! } +//! ``` +//! +//! ### Array of bitfields +//! Arrays of bitfields are modeled as an array of bitfield structs in the register. +//! +//! ```rust,ignore +//! let mut reg_value = unsafe { TIMER.bitfield_reg().read() }; +//! for x in 0..2 { +//! reg_value = reg_value.fieldarray(x).set(bitfield_reg::FieldArray::FALLING); +//! } +//! unsafe { TIMER.bitfield_reg().write(reg_value) }; +//! ``` +//! +//! ### Write an enumerated bitfield by passing an integer literal +//! The size of value cannot exceed bit field size. +//! Here the associated struct type can be created from the integer, +//! as the `From` trait implementation is available for the bitfield structure. +//! +//! ```rust,ignore +//! TIMER.bitfield_reg().modify(|f| { +//! f.bitfieldenumerated() +//! .set(0.into()) +//! }); +//! ``` +//! +//! ### Get mask and offset of a bitfield +//! It is possible to get mask and offset of a single bitfield using `mask` and `offset`. The returned mask is aligned to the LSB and not shifted (i.e. a 3-bit wide field has a mask of `0x7`, independent of position of the field). +//! ```rust,ignore +//! let register_bitfield = TIMER.bitfield_reg().read().bitfieldr(); +//! let _offset = register_bitfield.offset(); +//! let _mask = register_bitfield.mask(); +//! ``` +//! +//! # Tracing feature +//! When generating the PAC with the `--tracing` cli-flag, the PAC is generated with +//! an optional feature flag `tracing`. Enabling the feature provides the following +//! additional functionalities: +//! - an interface where register accesses can be piped though, enabling +//! developers to log accesses to registers or even mock registers outright. +//! An implementaion of that interface is provided by [`regmock-rs`](https://bitbucket.vih.infineon.com/projects/OXIDE/repos/regmock-rs/browse). +//! - a special `RegisterValue` trait that allows constructing values of +//! registers from integers. +//! - an additional `insanely_unsafe` module which allows reading and writing, write-only and +//! read-only registers (intended for mocking state in tests). +//! - an additional `reg_name` module that contains a perfect hash map of physical +//! addresses to string names of all registers that reside at an address. +//! +//! ## Examples +//! Below, some simple examples on how to use the tracing APIs are shown. +//! For a complete example of how to use the tracing features for +//! e.g. unittesting see the documentation of [`regmock-rs`](https://bitbucket.vih.infineon.com/projects/OXIDE/repos/regmock-rs/browse). +//! +//! ### Construcing a register value from a raw value with tracing +//! When implementing tests using the tracing feature we want to be +//! able to provide arbitrary data during those tests. +//! +//! ```rust,ignore +//! use pac::common::RegisterValue; +//! let value = pac::peripheral::register::new(0xC0FFEE); +//! unsafe{ pac::PERIPHERAL.register().write(value) }; +//! ``` +//! +//! ### Reading a value from a **write-only** register with tracing +//! Again for testing: in a testcase we need to do the exact opposite +//! of what normal code does, i.e. we need to "write" read-only registers +//! and "read" write-only registers. +//! +//! Tracing provides a backdoor to allow those actions that are not +//! allowed in normal code. +//! +//! ```rust,ignore +//! use pac::tracing::insanely_unsafe; +//! let value = unsafe{ pac::PERIPHERAL.write_only_register().read_write_only() }; +//! ``` +//! +//! ### Get the names of registers at a specific address +//! For better logging a map of address to name translation is generated/available +//! if tracing is enabled. +//! +//! ```rust,ignore +//! let regs_at_c0ffee = pac::reg_name::reg_name_from_addr(0xC0FFEE); +//! println!("{regs_at_c0ffee:?}"); +//! ``` +//! +//! +//! # Running tests +//! +//! To execute the tests it is required to add as target "thumbv7em-none-eabihf". +//! This can be done using +//! ```bash +//! rustup target add thumbv7em-none-eabihf +//! ``` +//! +//! To test the generation of Aurix PAC it is necessary to install Hightec Rust Aurix compiler and select it as default compiler. +//! `build.rs` detects automatically the toolchain and add the configuration option to enable Aurix specific tests. +//! +//! # Credits +//! +//! A small portion of template common.tera is copied from +//! [Link to commit from where code has been copies](https://github.com/embassy-rs/chiptool/commit/4834a9b35982b393beae84a04960c9add886c1f7) + +mod rust_gen; +mod svd_util; +use crate::rust_gen::{generate_rust_package, GenPkgSettings}; +use clap::{Parser, ValueEnum}; +use env_logger::Env; +use log::{error, info, warn}; +use serde::Serialize; +use std::ffi::OsString; +use std::fs; +use std::path::PathBuf; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)] +pub enum SvdValidationLevel { + Disabled, + Weak, + Strict, +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug, Serialize)] +pub enum Target { + /// Only generic access to registers. No support for interrupt vector and NVIC priority bits. + Generic, + /// Generic access to register + atomic read modify store of register values. Dependant on tricore crate. + Aurix, + /// Support for interrupt vector and NVIC priority bits. Compatible with existing cortex-m-rt crate + CortexM, +} + +/// Generate peripheral access crate from SVD file +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Disable formatting of generated code using rustfmt mainly for debugging + #[arg(long,value_parser=clap::value_parser!(bool),default_value_t=false)] + disable_rust_fmt: bool, + /// Register description file + #[arg(value_parser=clap::value_parser!(PathBuf))] + register_description_file_name: PathBuf, + /// Destination folder of package + #[arg(value_parser=clap::value_parser!(PathBuf))] + destination_folder: PathBuf, + //SVD validation level + #[arg(long,value_enum,default_value_t=SvdValidationLevel::Weak)] + svd_validation_level: SvdValidationLevel, + /// Architecture target of the PAC. + #[arg(long,value_enum,default_value_t=Target::Generic)] + target: Target, + /// Enable the generation of a PAC with the tracing interface. + #[arg(long,value_parser=clap::value_parser!(bool),default_value_t=false)] + tracing: bool, + /// Define package name in toml. Default is name stored in register description file + #[arg(long,value_parser=clap::value_parser!(String),default_value=None)] + package_name: Option, + /// Specify a license file whose content is used instead of one defined in SVD. + #[arg(long,value_parser=clap::value_parser!(PathBuf),default_value=None)] + license_file: Option, +} + +/// Main function that parses command line parameters. +/// +/// # Arguments +/// +/// * `args` - List of command line arguments. The first argument should be the path of executable, but it is ignored by this function. +/// +/// # Examples +/// +/// ```ignore +/// let args = ["", "./test_svd/simple.xml", "./generated_code"]; +/// main(args); +/// ``` +pub fn main(args: I) +where + I: IntoIterator, + T: Into + Clone, +{ + // Use + let env = Env::default() + .filter_or("PAL_LOG_LEVEL", "info") + .write_style_or("PAL_LOG_STYLE", "always"); + + // During test cases the logger is already initialized. + // Just show a warn + if let Err(error) = env_logger::try_init_from_env(env) { + warn!("{}", error); + } + let args = Args::parse_from(args); + info!( + "Reading register description file {}", + args.register_description_file_name.to_str().unwrap() + ); + let destination_folder = args.destination_folder; + + if !destination_folder.exists() { + info!("Create folder {}", &destination_folder.to_str().unwrap()); + if let Err(err) = fs::create_dir_all(&destination_folder) { + error!("Failed to create destination folder: {}", err); + panic!("Failed to create folder") + }; + } + + if let Err(err) = generate_rust_package( + &args.register_description_file_name, + &destination_folder, + GenPkgSettings { + run_rustfmt: !args.disable_rust_fmt, + svd_validation_level: args.svd_validation_level, + target: args.target, + tracing: args.tracing, + package_name: args.package_name, + license_file: args.license_file, + }, + ) { + error!("Failed to generate code with err {}", err); + panic!("Failed to generate code"); + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..fb3e27a --- /dev/null +++ b/src/main.rs @@ -0,0 +1,5 @@ +use std::env::args; + +pub fn main() { + svd2pac::main(args()); +} diff --git a/src/rust_gen.rs b/src/rust_gen.rs new file mode 100644 index 0000000..47f84e7 --- /dev/null +++ b/src/rust_gen.rs @@ -0,0 +1,598 @@ +mod ir; +mod util; +mod xml2ir; +use std::{ + fs::create_dir_all, + path::{Path, PathBuf}, +}; + +use self::util::ToSanitizedSymbol; +use crate::{SvdValidationLevel, Target}; +use anyhow::{anyhow, Context, Result}; +use ir::PeripheralMod; +use lazy_regex::regex; +use linked_hash_map::LinkedHashMap; +use log::{error, info, warn}; +use std::collections::HashMap; +use std::error::Error; +use std::fmt::Write; +use std::fs; +use std::fs::File; +use std::io::Read; +use std::io::{BufRead, BufReader}; +use std::process::Command; +use tera::{to_value, try_get_value, Tera, Value}; + +/// Convert [`Vec`] to a string representation of a register path. +fn filter_render_path(value: &Value, _args: &HashMap) -> tera::Result { + match serde_json::from_value::>(value.clone()) { + Ok(path) => { + let rendered = path.iter() + .enumerate() + .fold(String::new(),|mut output,(index, path_chunk)|{ + let _ = write!(output, + "{}{}{}", + match index { + // check first element + 0 => path_chunk.path.clone(), + _ => path_chunk.path.clone() +"()", + }, + match path_chunk.index { + Some(index) => format!("[{}]",index), + None => "".to_owned(), + }, + match index { + _i if (_i == path.len() -1) => String::default(), + _ => ".".to_owned(), + } + ); + output + + } + ); + Ok(Value::String(rendered)) + }, + Err(e)=>{ + Err(tera::Error::msg(format!( + "filter_render_path only acceptes Vec as input.\nCound not deserialize value:{} because:\nerror:{}", + value, + e + ))) + } + } +} + +/// Convert a String to array of line splitting it at \n or \r\n and prepend each line with `prefix` +/// This filter is intended to create multiple line comments from a String +fn filter_prepend_lines(value: &Value, args: &HashMap) -> tera::Result { + let reg_ex = regex!(r#"(\r\n)|(\n)"#); + let input_string = try_get_value!("prepend_lines", "value", String, value.clone()); + let prefix_string = match args.get("prefix") { + Some(val) => try_get_value!("prepend_lines", "prefix", String, val), + None => { + return Err(tera::Error::msg( + "Filter `prepend_lines` expected an arg called `prefix`", + )) + } + }; + let splits = to_value( + reg_ex + .split(&input_string) + .map(|s| prefix_string.clone() + s) + .collect::>(), + ) + .unwrap(); + Ok(splits) +} + +/// Convert JSON number to hexadecimal String filter for tera template +fn filter_to_hex(value: &Value, _args: &HashMap) -> tera::Result { + if let Value::Number(number) = value { + if let Some(u64_val) = number.as_u64() { + Ok(Value::String(format!("0x{:x}", u64_val))) + } else { + Err(tera::Error::msg("to_hex accept only unsigned numbers")) + } + } else { + Err(tera::Error::msg(format!( + "to_hex accept only numbers as input. value:{}", + value + ))) + } +} + +/// Convert stringified number to hex value. Useful when iterating over maps +/// in tera files as tera converts the key to strings regardless of the type. +fn filter_num_str_to_hex(value: &Value, _args: &HashMap) -> tera::Result { + if let Value::String(number_str) = value { + if let Ok(u64_val) = number_str.parse::() { + Ok(Value::String(format!("0x{:x}", u64_val))) + } else { + Err(tera::Error::msg(format!( + "num_str_to_hex could not parse value:{} as number", + value + ))) + } + } else { + Err(tera::Error::msg(format!( + "num_str_to_hex only accepts strings. value:{}", + value + ))) + } +} + +fn filter_to_struct_id(value: &Value, _args: &HashMap) -> tera::Result { + if let Value::String(string) = value { + Ok(Value::String(string.to_owned().to_sanitized_struct_ident())) + } else { + Err(tera::Error::msg(format!( + "filter_to_struct_id only supports String as argument. value:{}", + value + ))) + } +} + +fn filter_to_mod_id(value: &Value, _args: &HashMap) -> tera::Result { + if let Value::String(string) = value { + Ok(Value::String(string.to_owned().to_sanitized_mod_ident())) + } else { + Err(tera::Error::msg(format!( + "filter_to_mod_id only supports String as argument. value:{}", + value, + ))) + } +} + +#[allow(dead_code)] +fn filter_to_enum_id(value: &Value, _args: &HashMap) -> tera::Result { + if let Value::String(string) = value { + Ok(Value::String(string.to_owned().to_sanitized_enum_ident())) + } else { + Err(tera::Error::msg(format!( + "filter_to_enum_id case support only String as argument. value:{}", + value, + ))) + } +} + +fn filter_to_const_id(value: &Value, _args: &HashMap) -> tera::Result { + if let Value::String(string) = value { + Ok(Value::String(string.to_owned().to_sanitized_const_ident())) + } else { + Err(tera::Error::msg(format!( + "filter_to_const_id only supports String as argument. value:{}", + value, + ))) + } +} + +fn filter_to_func_id(value: &Value, _args: &HashMap) -> tera::Result { + if let Value::String(string) = value { + Ok(Value::String(string.to_owned().to_sanitized_func_ident())) + } else { + Err(tera::Error::msg(format!( + "filter_to_func_id only supports String as argument. value:{}", + value + ))) + } +} + +/// Sanitize a string so it can be used in doc attribute +fn filter_svd_description_to_doc( + value: &Value, + _args: &HashMap, +) -> tera::Result { + if let Value::String(doc_string) = value { + Ok(Value::String( + doc_string + .replace('[', r"\[") + .replace(']', r"\]") + .escape_debug() + .to_string(), + )) + } else { + Err(tera::Error::msg( + "svd_description_to_doc accepts only string", + )) + } +} + +fn execute_template( + tera: &Tera, + template_name: &str, + context: &tera::Context, + output_path: &Path, +) -> anyhow::Result<()> { + let result = match tera.render(template_name, context) { + Ok(s) => Ok(s), + Err(e) => { + error!("Render Error: {}", e); + let mut cause = e.source(); + while let Some(e) = cause { + error!("Render Reason: {}", e); + cause = e.source(); + } + Err(anyhow!("Failed to render")) + } + }?; + let folder = output_path + .parent() + .unwrap_or_else(|| panic!("No parent folder for {:?}", output_path)); + create_dir_all(folder)?; + fs::write(output_path, result).context(format!("Error while writing {:?}", output_path))?; + Ok(()) +} + +/// Get instance of Tera that includes required templates +fn get_tera_instance() -> anyhow::Result { + let mut tera = Tera::default(); + tera.add_raw_templates(vec![ + ( + "Cargo_toml.tera", + include_str!("../templates/rust/Cargo_toml.tera"), + ), + ("lib.tera", include_str!("../templates/rust/lib.tera")), + ( + "tracing.tera", + include_str!("../templates/rust/tracing.tera"), + ), + ( + "reg_name.tera", + include_str!("../templates/rust/reg_name.tera"), + ), + ( + "peri_mod.tera", + include_str!("../templates/rust/peri_mod.tera"), + ), + ( + "aurix_core.tera", + include_str!("../templates/rust/aurix_core.tera"), + ), + ("common.tera", include_str!("../templates/rust/common.tera")), + ("macros.tera", include_str!("../templates/rust/macros.tera")), + ( + "build_cortex.tera", + include_str!("../templates/rust/build_cortex.tera"), + ), + ( + "device_x.tera", + include_str!("../templates/rust/device_x.tera"), + ), + ])?; + Ok(tera) +} + +fn get_xml_string(path: &Path, xml: &mut String) -> Result<()> { + File::open(path) + .context("Cannot open register description file")? + .read_to_string(xml) + .context("Cannot read register description file")?; + Ok(()) +} + +// check if vendor extension is present in the svd +fn check_for_vendor_extension(path: &Path) -> Result { + let file = File::open(path)?; + let reader = BufReader::new(file); + let mut present = false; + for line in reader.lines() { + match line? { + s if s.contains("vendorExtensions") => present = true, + _ => continue, + } + } + Ok(present) +} + +fn error_with_context() -> Result<()> { + Err(anyhow!("svd parsing error")).context("problem with svd to extract aurix cpu related peripherals, or maybe missing?") +} + +pub fn get_aurix_csfr_svd(path: &Path, svd_string: &mut String) -> Result<()> { + let xml = &mut String::new(); + File::open(path) + .context("Cannot open register description file")? + .read_to_string(xml) + .context("Cannot read register description file")?; + + let common_svd_tags: Vec<&str> = xml.split("").collect(); + let svd_split_vec: Vec<&str> = xml.split("").collect(); + let mut extended_peripherals: Vec<&str> = Vec::new(); + if svd_split_vec.len() > 1 { + extended_peripherals = svd_split_vec[1].split("").collect(); + } else { + error_with_context()?; + } + *svd_string = format!( + "{} {} {} {} {}", + common_svd_tags[0], + "", + extended_peripherals[0], + "\n", + "" + ); + Ok(()) +} + +pub struct GenPkgSettings { + pub run_rustfmt: bool, + pub svd_validation_level: SvdValidationLevel, + pub target: Target, + pub tracing: bool, + pub package_name: Option, + pub license_file: Option, +} + +fn precompile_tera(tera: &mut Tera) { + tera.register_filter("to_hex", filter_to_hex); + tera.register_filter("num_str_to_hex", filter_num_str_to_hex); + tera.register_filter("render_path", filter_render_path); + tera.register_filter("to_struct_id", filter_to_struct_id); + tera.register_filter("to_func_id", filter_to_func_id); + tera.register_filter("to_mod_id", filter_to_mod_id); + tera.register_filter("to_enumerated_const_id", filter_to_const_id); + tera.register_filter("prepend_lines", filter_prepend_lines); + tera.register_filter("svd_description_to_doc", filter_svd_description_to_doc); +} + +fn generate_lib_rs_module( + tera: &Tera, + destination_folder: &Path, + context: &tera::Context, +) -> anyhow::Result<()> { + let lib_path = destination_folder.join("src/lib.rs"); + execute_template(tera, "lib.tera", context, &lib_path).context("Failed generation of code")?; + Ok(()) +} + +fn generate_cargo_toml( + tera: &Tera, + destination_folder: &Path, + context: &tera::Context, +) -> anyhow::Result<()> { + execute_template( + tera, + "Cargo_toml.tera", + context, + &destination_folder.join("Cargo.toml"), + ) + .context("Failed generation of Cargo.toml")?; + Ok(()) +} + +fn generate_tracing_module( + tera: &Tera, + ir: &ir::IR, + destination_folder: &Path, + context: &tera::Context, +) -> anyhow::Result<()> { + // tracing module + let lib_path = destination_folder.join("src/tracing.rs"); + execute_template(tera, "tracing.tera", context, &lib_path) + .context("Failed generation of tracing.rs")?; + // reg_name module + // + // # Issue + // + // When using `feature=[tracing]`, the exact name of accesses registers + // is lost, due to registers being accessed though their raw address. + // When writing test this is sufficient as accesses happen to the same + // addresses as on embedded anyway (regardless if registers are aliased + // or not). + // When evaluating failed tests however, having a human readable name + // of a register is extremely valuable. + // + // # Solution + // + // When tracing is enabled, we generate a hash map of all physical + // addresses to a string name of registers at a specific address. + // + // Due to SVD supporting aliasing (i.e. the same physical address can be + // reused by multiple different peripherals, clusters and registers), + // the string name contains **all** possible aliases that resolve to + // a specific address. + // + // # How + // + // A [`phf`](https://crates.io/crate/phf) of physical addresses to + // associated register names is generated as `reg_name.rs` module. + // + // This is done by flattening the SVD-tree structure into a map + // of `Vec` to `RegisterAbs`, which is then inverted to + // a map of `address` to Vec>. + // + // This map is passed to the tera module where it is rendered + // into the respective hash map entries. + let mut context = tera::Context::new(); + let lib_path = destination_folder.join("src/reg_name.rs"); + context.insert("register_addresses", &ir.register_addresses); + context.insert("ir", &ir); + execute_template(tera, "reg_name.tera", &context, &lib_path) + .context("Failed generation of reg_name.rs")?; + Ok(()) +} + +fn generate_common_module( + tera: &Tera, + _ir: &ir::IR, + destination_folder: &Path, + context: &tera::Context, +) -> anyhow::Result<()> { + let lib_path = destination_folder.join("src/common.rs"); + execute_template(tera, "common.tera", context, &lib_path) + .context("Failed generation of common.rs")?; + Ok(()) +} + +fn generate_peripheral_module( + tera: &Tera, + ir: &ir::IR, + template_name: &str, + destination_folder: &Path, +) -> anyhow::Result<()> { + // Generate one module for each peripheral + for (peri_name, peri) in &ir.peripheral_mod { + let mut context = tera::Context::new(); + context.insert("peri", peri); + context.insert("ir", &ir); + execute_template( + tera, + template_name, + &context, + &destination_folder.join(format!("src/{}.rs", peri_name.to_lowercase())), + ) + .context("Failed generation of code")?; + } + Ok(()) +} + +fn change_peripheral_module_name(ir: &mut ir::IR) -> anyhow::Result<()> { + let mut result = LinkedHashMap::::new(); + // change peripheral module to have prefix csfr_ + for (peri_name, peri) in &mut ir.peripheral_mod { + peri.name = format!("{}_{}", "csfr", peri_name); + result.insert(peri.name.clone(), std::mem::take(peri)); + } + ir.peripheral_mod = result; + Ok(()) +} + +fn generate_aurix_core_ir( + xml_path: &Path, + settings: &GenPkgSettings, +) -> anyhow::Result> { + let GenPkgSettings { + run_rustfmt: _, + svd_validation_level, + target: _, + tracing: _, + package_name: _, + license_file, + } = settings; + + info!("Start generating csfr rust code"); + // Read license file if specified + let custom_license_text = license_file.as_ref().map(|path| { + fs::read_to_string(path).unwrap_or_else(|_| panic!("Unable to read license file {path:?}")) + }); + // If target is aurix, create csfr + let result = check_for_vendor_extension(xml_path)?; + if result { + let svd_csfr_xml = &mut String::with_capacity(500); + get_aurix_csfr_svd(xml_path, svd_csfr_xml)?; + let mut ir_csfr = + xml2ir::parse_xml2ir(svd_csfr_xml, *svd_validation_level, &custom_license_text)?; + change_peripheral_module_name(&mut ir_csfr)?; + Ok(Some(ir_csfr)) + } else { + Ok(None) + } +} + +pub(crate) fn generate_rust_package( + xml_path: &Path, + destination_folder: &Path, + settings: GenPkgSettings, +) -> anyhow::Result<()> { + let GenPkgSettings { + run_rustfmt, + svd_validation_level, + target, + tracing, + ref package_name, + ref license_file, + } = settings; + + info!("Start generating rust code"); + // Read license file if specified + let custom_license_text = license_file.as_ref().map(|path| { + fs::read_to_string(path).unwrap_or_else(|_| panic!("Unable to read license file {path:?}")) + }); + + let xml = &mut String::new(); + get_xml_string(xml_path, xml)?; + let ir = xml2ir::parse_xml2ir(xml, svd_validation_level, &custom_license_text)?; + //Precompile templates + let mut tera = get_tera_instance()?; + precompile_tera(&mut tera); + + let package_name: String = match package_name { + None => ir.device.name.clone().to_lowercase(), + Some(ref package_name) => package_name.clone(), + }; + + let mut context = tera::Context::new(); + context.insert("ir", &ir); + context.insert("target", &target); + context.insert("tracing", &tracing); + context.insert("package_name", &package_name); + context.insert("description", "Description tests"); + + // Generate peripheral modules + generate_peripheral_module(&tera, &ir, "peri_mod.tera", destination_folder)?; + + //Generate common module + generate_common_module(&tera, &ir, destination_folder, &context)?; + + // Generate tracing related modules + if tracing { + generate_tracing_module(&tera, &ir, destination_folder, &context)?; + } + + // If target is aurix, create csfr modules + if settings.target == Target::Aurix { + let ir_csfr = generate_aurix_core_ir(xml_path, &settings)?; + + // Generate cpu peripheral modules + if let Some(ref ir) = ir_csfr { + generate_peripheral_module(&tera, ir, "aurix_core.tera", destination_folder)?; + context.insert("ir_csfr", &ir_csfr); + } + } + + //generate lib.rs + generate_lib_rs_module(&tera, destination_folder, &context)?; + + //generate Cargo.toml + generate_cargo_toml(&tera, destination_folder, &context)?; + + // If cortex-m add build.rs and device.x + if settings.target == Target::CortexM { + execute_template( + &tera, + "device_x.tera", + &context, + &destination_folder.join("device.x"), + ) + .context("Failed to generate device.x file")?; + execute_template( + &tera, + "build_cortex.tera", + &context, + &destination_folder.join("build.rs"), + ) + .context("Failed to generate build.rs file")?; + } + + let lib_path = destination_folder.join("src/lib.rs"); + // Run rustfmt on generated code + if run_rustfmt { + // Check rustfmt is available + match Command::new("rustfmt").arg("-V").output() { + // If available format code and return + Ok(_) => { + info!("Formatting code with rustfmt"); + Command::new("rustfmt").arg(lib_path).status()?; + } + // if not able to run with --help proceed just with a warning. Generated code is anyway valid. + Err(_) => { + warn!("Error while detecting presence of rustfmt. Generated code is valid but not formatted"); + } + } + }; + // Add license file + fs::write(destination_folder.join("LICENSE.txt"), ir.license_text)?; + + info!("Completed code generation"); + Ok(()) +} diff --git a/src/rust_gen/ir.rs b/src/rust_gen/ir.rs new file mode 100644 index 0000000..56c8d04 --- /dev/null +++ b/src/rust_gen/ir.rs @@ -0,0 +1,156 @@ +use linked_hash_map::LinkedHashMap; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Device { + pub name: String, + pub description: String, +} + +#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct EnumeratedSigleValue { + pub name: String, + pub value: u64, + pub description: String, +} + +#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct EnumeratedValueType { + pub name: String, + pub size: BitSize, // Used generate the smallest numeric type to contain the value + pub values: Vec, +} + +#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct FieldGetterSetter { + pub name: String, + pub description: String, + pub offset: u32, + pub mask: u32, + pub size: BitSize, + pub enum_type: Option, + pub access: RegisterBitfieldAccess, + pub dim: u32, + pub dim_increment: u32, +} + +#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum RegisterAccess { + #[default] + R, + W, + RW, +} + +#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum RegisterBitfieldAccess { + #[default] + R, + W, + RW, +} + +#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum BitSize { + BIT64, + #[default] + BIT32, + BIT16, + BIT8, +} + +impl BitSize { + pub fn val_2_bit_size(val: u64) -> BitSize { + if val <= u8::MAX.into() { + BitSize::BIT8 + } else if val <= u16::MAX.into() { + BitSize::BIT16 + } else if val <= u32::MAX.into() { + BitSize::BIT32 + } else { + BitSize::BIT64 + } + } +} + +#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Register { + pub name: String, + pub description: String, + pub offset: u32, + pub dim: u32, + pub dim_increment: u32, + pub access: RegisterAccess, + pub fields: Vec, + pub size: BitSize, + pub reset_value: u64, + pub has_enumerated_fields: bool, +} + +#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Cluster { + pub name: String, + pub description: String, + pub offset: u32, + pub dim: u32, + pub dim_increment: u32, + pub registers: LinkedHashMap, + pub clusters: LinkedHashMap, + pub is_derived_from: Option, + pub struct_id: String, + pub struct_path: String, +} + +#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct PeripheralMod { + pub name: String, + pub description: String, + pub clusters: LinkedHashMap, + pub registers: LinkedHashMap, + pub base_addr: Vec, + pub interrupts: Vec, +} + +/// Represents a part of a fully qualified path name for registers. +/// +/// Used to flatten the SVD tree into a vector of paths to registers while +/// preserving their index information if parts of the path are arrays of +/// peripherals/clusters/registers. +#[derive(Clone, Serialize, Deserialize, Debug, Hash, PartialEq, Eq)] +pub struct PathChunk { + /// Identifier of the path chunk + pub path: String, + /// Optional index if the current path is an array. + /// Necessary because SVD supports arrays on all levels: peripherals, clusters + /// and registers. + pub index: Option, +} + +/// Description of single interrupt +#[derive(Clone, Serialize, Deserialize, Debug, Hash, PartialEq, Eq)] +pub struct Interrupt { + pub name: String, + pub value: u32, + pub description: String, +} + +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct IR { + pub device: Device, + pub peripheral_mod: LinkedHashMap, + pub register_addresses: LinkedHashMap>>, + pub license_text: String, + /// Interrupt table to be created in the lib.rs. Interrupt table hole has value None + pub interrupt_table: Vec>, + /// used only for cortex m target + /// This could be none if no CPU is defined. + /// If not defined NVIC_PRIO_BITS constant will be not generated + pub nvic_prio_bits: Option, + /// used only for cortex m target. If it is false or None cortex-m::Systick module will be re-exported + /// This could be none if no CPU is defined. + pub vendor_systick_config: Option, + /// This could be none if no CPU is defined. + pub fpu_present: Option, + /// This could be none if no CPU is defined. + pub mpu_present: Option, +} diff --git a/src/rust_gen/util.rs b/src/rust_gen/util.rs new file mode 100644 index 0000000..47da2e5 --- /dev/null +++ b/src/rust_gen/util.rs @@ -0,0 +1,71 @@ +use convert_case::{Case, Casing}; +use lazy_regex::regex; +use log::warn; +pub trait ToSanitizedSymbol { + fn to_sanitized_mod_ident(&self) -> String; + fn to_sanitized_struct_ident(&self) -> String; + fn to_sanitized_func_ident(&self) -> String; + fn to_sanitized_enum_ident(&self) -> String; + fn to_sanitized_const_ident(&self) -> String; + fn to_sanitized_ident(&self) -> String; + fn to_internal_ident(&self) -> String; + fn remove_invalid_char(&self) -> String; +} + +impl ToSanitizedSymbol for str { + fn to_sanitized_mod_ident(&self) -> String { + self.to_internal_ident() + .remove_invalid_char() + .to_lowercase() + .to_sanitized_ident() + } + fn to_sanitized_struct_ident(&self) -> String { + self.to_internal_ident() + .remove_invalid_char() + .to_case(Case::Pascal) + .to_sanitized_ident() + } + fn to_sanitized_func_ident(&self) -> String { + self.to_internal_ident() + .remove_invalid_char() + .to_lowercase() + .to_sanitized_ident() + } + fn to_sanitized_enum_ident(&self) -> String { + self.to_internal_ident() + .remove_invalid_char() + .to_case(Case::Pascal) + .to_sanitized_ident() + } + fn to_sanitized_const_ident(&self) -> String { + self.to_internal_ident() + .remove_invalid_char() + .to_case(Case::ScreamingSnake) + .to_sanitized_ident() + } + fn to_sanitized_ident(&self) -> String { + // Use RAW_IDENTIFIER (i.e. prepend 'r#') if string is a Rust keyword. + // Prepend a _ if string does not start with XID_Start character. + let result = match syn::parse_str::(self) { + Ok(_) => self.to_owned(), + Err(_) => match syn::parse_str::(&("r#".to_owned() + self)) { + Ok(_) => "r#".to_owned() + self, + Err(_) => "_".to_owned() + self, + }, + }; + if result != self { + warn!("Identifier {self} sanitized to {result}"); + } + result + } + fn to_internal_ident(&self) -> String { + // FIXME: We assume that nobody creates different array of registers that differs + // only for index position. Is this a good assumption ? + self.replace("[%s]", "").replace("%s", "") + } + fn remove_invalid_char(&self) -> String { + // Remove all char that are not valid for Rust identifier + let reg_ex = regex!("[^a-zA-Z0-9_]"); + reg_ex.replace_all(self, "_").into_owned() + } +} diff --git a/src/rust_gen/xml2ir.rs b/src/rust_gen/xml2ir.rs new file mode 100644 index 0000000..9634075 --- /dev/null +++ b/src/rust_gen/xml2ir.rs @@ -0,0 +1,447 @@ +mod svd2temp; +use super::ir::*; +use super::util::*; +use crate::svd_util::*; +use crate::SvdValidationLevel; +use anyhow::Result; +use linked_hash_map::LinkedHashMap; +use log::{debug, error, warn}; +use svd2temp::*; +use svd_parser::svd; + +trait RegisterHelper { + /// Get name of register considering the presence of alternate group + /// Alternate group is appended to the id of register + fn get_name_id_internal(&self) -> String; +} + +impl RegisterHelper for svd::RegisterInfo { + fn get_name_id_internal(&self) -> String { + match self.alternate_group { + None => self.name.to_internal_ident(), + Some(ref alt_group_name) => { + (self.name.to_owned() + "_" + alt_group_name).to_internal_ident() + } + } + } +} + +/// Utility function to get number of instances and increment between the distances +/// This function can be used anytime in svd::array::MaybeArray is used +/// +/// +/// # Arguments +/// +/// * `array` any MaybeArray type +/// +/// # Result +/// +/// (`dimension of array`,`increment between two element of array`) If `array`=Single() the result default to (1,0) +fn get_dim_dim_increment(array: &svd::array::MaybeArray) -> (u32, u32) { + match array { + svd::array::MaybeArray::Single(_) => (1, 0), + svd::array::MaybeArray::Array(_, dim_element) => { + (dim_element.dim, dim_element.dim_increment) + } + } +} + +/// Create the intermediate representation of device used by template engine +fn get_device(device: &svd::Device) -> Device { + Device { + name: device.name.clone(), + description: device.description.clone(), + } +} + +fn get_register(reg: &svd::Register) -> Register { + let register_name = reg.get_name_id_internal(); + let (dim, dim_increment) = get_dim_dim_increment(reg); + // Get fields + let mut fields = vec![]; + for field in reg.fields() { + let description = field.description.clone().unwrap_or_default(); + let offset = field.bit_range.offset; + let mask = (0..field.bit_range.width - 1).fold(0x1u32, |acc, _| (acc << 1) | 0x1); + let name = field.name.to_internal_ident(); + let svd_field_access = match field.access { + None => { + error!("Inheritance of access is not supported. Bitfield: {} access shall be specified. Bitfield skipped",name); + continue; + } + Some(acc) => acc, + }; + let access = match svd_field_access { + svd::Access::ReadOnly => RegisterBitfieldAccess::R, + svd::Access::WriteOnly => RegisterBitfieldAccess::W, + svd::Access::ReadWrite => RegisterBitfieldAccess::RW, + svd::Access::WriteOnce => RegisterBitfieldAccess::W, + svd::Access::ReadWriteOnce => RegisterBitfieldAccess::RW, + }; + let enum_type = get_values_types(field); + let (dim, dim_increment) = get_dim_dim_increment(field); + fields.push(FieldGetterSetter { + name, + description, + offset, + mask, + enum_type, + access, + size: BitSize::val_2_bit_size(mask.into()), + dim, + dim_increment, + }) + } + let size = match reg + .properties + .size + .expect("All registers shall have a defined size") + { + 32 => BitSize::BIT32, + 16 => BitSize::BIT16, + 8 => BitSize::BIT8, + register_size => { + panic!("Unsupported register size {register_size}") + } + }; + let reset_value = reg + .properties + .reset_value + .expect("All registers shall have a reset value defined"); + let has_enumerated_fields = fields.iter().any(|f| f.enum_type.is_some()); + + let access = match reg.properties.access { + Some(reg_access) => match reg_access { + svd::Access::ReadOnly => RegisterAccess::R, + svd::Access::WriteOnly => RegisterAccess::W, + svd::Access::ReadWrite => RegisterAccess::RW, + svd::Access::WriteOnce => RegisterAccess::W, + svd::Access::ReadWriteOnce => RegisterAccess::RW, + }, + // If register access mode is not defined. The value is inferred from access mode of bitfields + None => { + warn!( + "Access mode is not defined for register ({}) inferring from bitfield", + register_name + ); + let is_register_writable = fields.iter().any(|f| { + f.access == RegisterBitfieldAccess::W || f.access == RegisterBitfieldAccess::RW + }); + let is_register_readable = fields.iter().any(|f| { + f.access == RegisterBitfieldAccess::R || f.access == RegisterBitfieldAccess::RW + }); + match (is_register_readable, is_register_writable) { + (true, true) => RegisterAccess::RW, + (true, false) => RegisterAccess::R, + (false, true) => RegisterAccess::W, + (false, false) => { + error!("No bitfield in register '{}' specifies an access mode. Not able to infer register access mode", ®ister_name); + RegisterAccess::R + } + } + } + }; + Register { + name: register_name, + offset: reg.address_offset, + dim, + dim_increment, + access, + description: reg.description.clone().unwrap_or_default(), + fields, + size, + reset_value, + has_enumerated_fields, + } +} + +fn get_values_types(field: &svd::Field) -> Option { + if field.enumerated_values.is_empty() { + return None; + }; + + let name = field.name.to_internal_ident(); + let mut values = Vec::new(); + let mut max_value = 0u64; // Compute max value of bitfiled to define the size of bitfiled in bits. + for enum_values in &field.enumerated_values { + for val_entry in &enum_values.values { + assert!( + !val_entry.name.is_empty(), + "Value of enumeration shall have a name" + ); + let description = val_entry.description.clone().unwrap_or_default(); + let val_name: String = if let Some(ref enumerated_values_name) = enum_values.name { + format!("{}_{}", enumerated_values_name, val_entry.name) + } else { + val_entry.name.clone() + }; + + let value = if let Some(value) = val_entry.value { + value + } else { + panic!("Unsupport is default, all value in enumeration shall have a value defined") + }; + + values.push(EnumeratedSigleValue { + name: val_name, + value, + description, + }); + max_value = max_value.max(value); + } + } + Some(EnumeratedValueType { + name, + size: BitSize::val_2_bit_size(max_value), + values, + }) +} + +fn get_parent_struct_name_cluster( + device: &svd::Device, + container: &T, + derived_from: &str, +) -> String { + let splitted: Vec<&str> = derived_from.split('.').collect(); + if splitted.len() == 1 { + /* Accordingly with cmsis svd spec when there is a single string. The name shall be found in + the container scope + */ + if let Some(parent) = container.get_clusters().find(|&c| c.name == splitted[0]) { + let mut struct_name = parent.struct_name().to_sanitized_struct_ident(); + struct_name.insert_str(0, "self::"); + struct_name + } else { + panic!("{} is referenced in a derivedFrom attribute but it doesn't exist a cluster with this name",derived_from); + } + } else { + let mut result: Vec = Vec::new(); + // In this case we expect an absolute path starting from device level + let mut present_item: &dyn PeripheralClusterT = + match device.peripherals.iter().find(|p| p.name == splitted[0]) { + Some(item) => item, + None => panic!( + "in a derivedFrom={} attribute is referenced an item {} that cannot be found", + derived_from, splitted[0] + ), + }; + + result.push(present_item.struct_name()); + + splitted.iter().skip(1).for_each(|&item| { + let item = match present_item.get_clusters().find(|c| c.name == item) { + Some(item) => item, + None => panic!( + "in a derivedFrom={} attribute is referenced an item {} that cannot be found", + derived_from, item + ), + }; + result.push(item.struct_name()); + present_item = item; + }); + /* + Modules and struct have different coding guidelines + */ + for x in 0..result.len() { + if x == result.len() - 1 { + result[x] = result[x].to_sanitized_struct_ident() + } else { + result[x] = result[x].to_sanitized_mod_ident() + } + } + result.insert(0, "crate".to_string()); + result.join("::") + } +} + +fn get_cluster( + device: &svd::Device, + container: &T, + cluster: &svd::Cluster, +) -> Cluster { + let name = cluster.name.to_internal_ident(); + let (dim, dim_increment) = get_dim_dim_increment(cluster); + let (registers, clusters) = get_register_clusters(device, container, &cluster.children); + let struct_id = cluster.struct_name(); + let struct_path: String = if let Some(ref derived_path) = cluster.derived_from { + if !registers.is_empty() || !clusters.is_empty() { + error!("Cluster with derivedFrom attributes are supported only if they doesn't contains registers and/or clusters. Included registers and clusters are ignored") + } + get_parent_struct_name_cluster(device, container, &derived_path) + } else { + let mut struct_name = cluster.struct_name().to_sanitized_struct_ident(); + struct_name.insert_str(0, "self::"); + struct_name + }; + Cluster { + name, + description: cluster.description.clone().unwrap_or_default(), + offset: cluster.address_offset, + dim, + dim_increment, + registers, + clusters, + is_derived_from: cluster.derived_from.as_ref().cloned(), + struct_id, + struct_path, + } +} + +fn get_register_clusters( + device: &svd::Device, + container: &T, + registers_clusters: &Vec, +) -> ( + LinkedHashMap, + LinkedHashMap, +) { + let mut registers = LinkedHashMap::new(); + let mut clusters = LinkedHashMap::new(); + for reg_clu in registers_clusters { + match reg_clu { + svd::RegisterCluster::Register(reg_svd) => { + let register = get_register(reg_svd); + registers.insert(register.name.clone(), register); + } + svd::RegisterCluster::Cluster(cluster_svd) => { + let cluster = get_cluster(device, container, cluster_svd); + clusters.insert(cluster_svd.name.clone(), cluster); + } + } + } + (registers, clusters) +} + +fn get_peripherals_types( + entity_db: &EntityDb, + svd_device: &svd::Device, +) -> LinkedHashMap { + let mut result = LinkedHashMap::new(); + + for (svd_name, &p) in &entity_db.peripherals { + /*I don't generate any type if the peripheral has derivedFrom attribute. + Overriding of peripheral content is not supported*/ + assert!( + p.derived_from.is_none(), + "derived_from is not supported in peripherals" + ); + debug!("Parsing peripheral: {}", svd_name); + let (registers, clusters) = + get_register_clusters(svd_device, p, p.registers.as_ref().unwrap_or(&Vec::new())); + let peripheral_struct_name = svd_name.to_internal_ident(); + let (dim, dim_increment) = get_dim_dim_increment(p); + let base_addr = (0..dim) + .map(|index| p.base_address + (index * dim_increment) as u64) + .collect(); + let interrupts = p + .interrupt + .iter() + .map(|x| Interrupt { + name: x.name.clone(), + value: x.value, + description: x + .description + .as_ref() + .map_or_else(String::new, |x| x.clone()), + }) + .collect(); + let peripheral_mod = PeripheralMod { + name: peripheral_struct_name, + description: p.description.clone().unwrap_or_default(), + clusters, + registers, + base_addr, + interrupts, + }; + result.insert(peripheral_mod.name.clone(), peripheral_mod); + } + result +} + +/// Parse xml and trasform to device description of svd_rs module +/// +/// # Arguments +/// +/// * `path` path to svd file +/// +/// # Result +/// +/// Device containing all information of svd file +fn parse_xml(xml: &mut String, svd_validation_level: SvdValidationLevel) -> Result { + let mut parser_config = svd_parser::Config::default(); + parser_config.expand_properties = true; + parser_config.ignore_enums = false; + parser_config.validate_level = match svd_validation_level { + SvdValidationLevel::Disabled => svd::ValidateLevel::Disabled, + SvdValidationLevel::Weak => svd::ValidateLevel::Weak, + SvdValidationLevel::Strict => svd::ValidateLevel::Strict, + }; + let result = svd_parser::parse_with_config(xml, &parser_config); + if let Err(err) = &result { + if let Some(error_at) = err.downcast_ref::() { + error!("Error while parsing {}", error_at); + } + } + result +} + +/// Generate interrupt table including holes that will be used to create required function for cortex-m-rt +fn get_interrupt_table( + peripheral_types: &LinkedHashMap, +) -> Vec> { + match peripheral_types + .values() + .flat_map(|x| x.interrupts.iter().map(|x| x.value)) + .max() + { + None => Vec::new(), + Some(max_int_index) => { + let mut result = vec![None; max_int_index as usize + 1]; + for interrupt in peripheral_types.values().flat_map(|x| x.interrupts.iter()) { + if result[interrupt.value as usize].is_some() { + error!( + "Duplicated interrupt definition at index {}", + interrupt.value + ); + } + result[interrupt.value as usize] = Some(interrupt.clone()); + } + result + } + } +} + +pub(super) fn parse_xml2ir( + xml: &mut String, + svd_validation_level: SvdValidationLevel, + custom_license_text: &Option, +) -> Result { + let svd_device = parse_xml(xml, svd_validation_level)?; + let entity_db = get_entity_db(&svd_device); + let peripheral_types = get_peripherals_types(&entity_db, &svd_device); + // Use custom license if available otherwise use license in svd and if it not present use empty string. + let license_text = custom_license_text.as_ref().map_or_else( + || { + svd_device.license_text.as_ref().map_or_else( + || { + error!("No license defined in SVD. Use --license-file option in command line"); + String::new() + }, + |license_txt| license_txt.replace("\\n", "\n"), + ) + }, + |file_license| file_license.clone(), + ); + let interrupt_table = get_interrupt_table(&peripheral_types); + Ok(IR { + device: get_device(&svd_device), + peripheral_mod: peripheral_types, + register_addresses: entity_db.register_addresses, + license_text, + interrupt_table, + nvic_prio_bits: svd_device.cpu.as_ref().map(|x| x.nvic_priority_bits), + vendor_systick_config: svd_device.cpu.as_ref().map(|x| x.has_vendor_systick), + fpu_present: svd_device.cpu.as_ref().map(|x| x.fpu_present), + mpu_present: svd_device.cpu.as_ref().map(|x| x.mpu_present), + }) +} diff --git a/src/rust_gen/xml2ir/svd2temp.rs b/src/rust_gen/xml2ir/svd2temp.rs new file mode 100644 index 0000000..4502b32 --- /dev/null +++ b/src/rust_gen/xml2ir/svd2temp.rs @@ -0,0 +1,221 @@ +use super::super::ir::PathChunk; +use super::super::util::*; +use super::RegisterHelper; +use linked_hash_map::LinkedHashMap; +use svd_parser::svd::{self, MaybeArray}; + +pub(super) struct EntityDb<'a> { + /// Flat map of peripheral names to peripherals. + pub peripherals: LinkedHashMap, + /// Flat map of absolute addresses to paths of registers at that address. + pub register_addresses: LinkedHashMap>>, +} + +/// Register struct wrapper with base address. +#[derive(Copy, Clone)] +pub(super) struct RegisterAbs<'a> { + pub register: &'a svd::RegisterInfo, + pub base_addr: u64, +} + +/// Cluster struct wrapper with base address. +#[derive(Copy, Clone)] +pub(super) struct ClusterAbs<'a> { + pub cluster: &'a svd::ClusterInfo, + pub base_addr: u64, +} + +/// Trait to get the absolute address of a [`RegisterAbs`] and [`ClusterAbs`]. +trait AbsoluteAddress { + fn abs_address(&self) -> u64; +} +impl<'a> AbsoluteAddress for RegisterAbs<'a> { + fn abs_address(&self) -> u64 { + self.base_addr + self.register.address_offset as u64 + } +} +impl<'a> AbsoluteAddress for ClusterAbs<'a> { + fn abs_address(&self) -> u64 { + self.base_addr + self.cluster.address_offset as u64 + } +} + +/// Generate complete flat map of paths to registers and clusters in an SVD file. +/// Maps include possible indices if path contains an array of peripherals/clusters/registers. +/// Values in maps store the respective base address of clusters/registers. +struct FQNFlatMaps<'a> { + registers: LinkedHashMap, RegisterAbs<'a>>, + #[allow(dead_code)] + clusters: LinkedHashMap, ClusterAbs<'a>>, +} +impl<'svd> FQNFlatMaps<'svd> { + /// Build [`FQNFlatMaps`] from [`svd::Device`] reference. + /// + /// Iterates over all (arrays of-) peripherals and collects their content + /// into `registers` and `clusters` respectively. + pub(super) fn generate(device: &'svd svd::Device) -> Self { + let mut ret: Self = Self { + registers: LinkedHashMap::new(), + clusters: LinkedHashMap::new(), + }; + + for p in &device.peripherals { + let p_name = p.name.to_internal_ident().to_sanitized_const_ident(); + match p { + MaybeArray::Single(p) => { + let prefix: Vec = vec![PathChunk { + path: p_name, + index: None, + }]; + for register_cluster in p.registers.as_deref().unwrap_or_default() { + ret.collect_register_cluster_arrays( + &prefix, + register_cluster, + p.base_address, + ); + } + } + MaybeArray::Array(p, dim) => { + for p_index in 0..dim.dim { + let prefix: Vec = vec![PathChunk { + path: p_name.clone(), + index: Some(p_index), + }]; + for register_cluster in p.registers.as_deref().unwrap_or_default() { + ret.collect_register_cluster_arrays( + &prefix, + register_cluster, + p.base_address + (p_index * dim.dim_increment) as u64, + ); + } + } + } + } + } + ret + } + + /// Collect individual [`svd::RegisterCluster`] objects into [`FQNFlatMaps`]. + /// Calls respective collector functions. + /// Recursion point. + pub(super) fn collect_register_cluster_arrays<'prefix>( + &mut self, + prefix: &'prefix [PathChunk], + rg: &'svd svd::RegisterCluster, + base_addr: u64, + ) { + match rg { + svd::RegisterCluster::Register(register) => { + self.collect_register_array(prefix, register, base_addr); + } + svd::RegisterCluster::Cluster(cluster) => { + self.collect_cluster_array(prefix, cluster, base_addr); + } + } + } + /// Collect individual [`svd::Register`]s into [`FQNFlatMaps.registers`]. + pub(super) fn collect_register_array<'prefix>( + &mut self, + prefix: &'prefix [PathChunk], + register: &'svd svd::Register, + base_addr: u64, + ) { + match register { + MaybeArray::Single(register) => { + let mut key = prefix.to_owned(); + key.push(PathChunk { + path: register.get_name_id_internal().to_sanitized_func_ident(), + index: None, + }); + self.registers.insert( + key, + RegisterAbs { + register, + base_addr, + }, + ); + } + MaybeArray::Array(register, dim) => { + for register_index in 0..dim.dim { + let mut key = prefix.to_owned(); + key.push(PathChunk { + path: register.get_name_id_internal().to_sanitized_func_ident(), + index: Some(register_index), + }); + self.registers.insert( + key, + RegisterAbs { + register, + base_addr: base_addr + (register_index * dim.dim_increment) as u64, + }, + ); + } + } + } + } + /// Collect individual [`svd::Cluster`] into the FQN register_map. + pub(super) fn collect_cluster_array<'prefix>( + &mut self, + prefix: &'prefix [PathChunk], + cluster: &'svd svd::Cluster, + base_addr: u64, + ) { + match cluster { + MaybeArray::Single(cluster) => { + let mut key = prefix.to_owned(); + key.push(PathChunk { + path: cluster.name.to_internal_ident().to_sanitized_func_ident(), + index: None, + }); + for child in &cluster.children { + self.collect_register_cluster_arrays(&key, child, base_addr); + } + } + MaybeArray::Array(cluster, dim) => { + // `cluster.address_offset` is relative to the containing + // element, even if the docs of `svd::ClusterInfo` state + // otherwise. See SVD spec: https://www.keil.com/pack/doc/CMSIS/SVD/html/elem_registers.html#elem_cluster + for cluster_index in 0..dim.dim { + let mut key = prefix.to_owned(); + key.push(PathChunk { + path: cluster.name.to_internal_ident().to_sanitized_func_ident(), + index: Some(cluster_index), + }); + for child in &cluster.children { + self.collect_register_cluster_arrays( + &key, + child, + base_addr + (cluster_index * dim.dim_increment) as u64, + ); + } + } + } + } + } +} + +pub(super) fn get_entity_db(device: &svd::Device) -> EntityDb { + let peripherals: LinkedHashMap = device + .peripherals + .iter() + .map(|p| (p.name.to_internal_ident(), p)) + .collect(); + + let flat_maps = FQNFlatMaps::generate(device); + + // Build flat map of enumerated_values and addresses mapping to register names. + // + // This is needed for + let mut register_addresses: LinkedHashMap>> = LinkedHashMap::new(); + for (reg_name, ®) in &flat_maps.registers { + register_addresses + .entry(reg.abs_address()) + .or_default() + .push(reg_name.clone()); + } + + EntityDb { + peripherals, + register_addresses, + } +} diff --git a/src/svd_util.rs b/src/svd_util.rs new file mode 100644 index 0000000..2b7f698 --- /dev/null +++ b/src/svd_util.rs @@ -0,0 +1,41 @@ +use svd_parser::svd; + +pub trait PeripheralClusterT: svd::Name + svd::Description { + fn get_clusters(&self) -> svd::registercluster::ClusterIter<'_>; + fn get_registers(&self) -> svd::registercluster::RegisterIter<'_>; + fn struct_name(&self) -> String; +} + +impl PeripheralClusterT for svd::Peripheral { + fn get_clusters(&self) -> svd::registercluster::ClusterIter<'_> { + self.clusters() + } + + fn get_registers(&self) -> svd::registercluster::RegisterIter<'_> { + self.registers() + } + + fn struct_name(&self) -> String { + match self.header_struct_name { + Some(ref struct_name) => struct_name.clone(), + None => self.name.clone(), + } + } +} + +impl PeripheralClusterT for svd::Cluster { + fn get_clusters(&self) -> svd::registercluster::ClusterIter<'_> { + self.clusters() + } + + fn get_registers(&self) -> svd::registercluster::RegisterIter<'_> { + self.registers() + } + + fn struct_name(&self) -> String { + match self.header_struct_name { + Some(ref struct_name) => struct_name.clone(), + None => self.name.clone(), + } + } +} diff --git a/templates/rust/Cargo_toml.tera b/templates/rust/Cargo_toml.tera new file mode 100644 index 0000000..05e9a38 --- /dev/null +++ b/templates/rust/Cargo_toml.tera @@ -0,0 +1,51 @@ +{% for line in ir.license_text | prepend_lines(prefix="# ") -%} +{{line}} +{% endfor -%} +[package] +name = "{{package_name}}" +version = "0.0.1" +authors = ["Infineon developers"] +edition = "2021" +rust-version = "1.64" +description = "{{description}}" +keywords = ["no_std", "infineon"{%- if target=="Aurix" -%}, "aurix"{%- endif -%}] +categories = ["embedded","hardware-support","no-std","no-std::no-alloc"] +license-file = "LICENSE.txt" + +[lib] +test = false +bench = false + +{% if tracing or target=="CortexM"%} +[dependencies] +{%- endif %} +{%- if tracing %} +phf = { version = "0.11", features = ["macros"], optional = true } +{%- endif %} +{%- if target=="CortexM" %} +cortex-m-rt= { version = "0.7", optional = true } +cortex-m = "0.7.6" +{%- endif %} + + + +[features] +{%- for peri_mod_name, peri in ir.peripheral_mod %} +{{peri.name | to_mod_id}} = [] +{%- endfor %} +{% if ir_csfr %} +{%- for peri_mod_name, peri in ir_csfr.peripheral_mod %} +{{peri.name | to_mod_id}} = [] +{%- endfor %} +{%- endif %} +all = [{%- for peri_mod_name, peri in ir.peripheral_mod -%}"{{peri.name | to_mod_id }}",{%- endfor -%}] +{%- if tracing %} +tracing = ["dep:phf"] +tracing_dummy = [] +{%- endif %} +{%- if target=="CortexM" %} +rt = ["cortex-m-rt/device"] +{%- endif %} + +[package.metadata.docs.rs] +features = ["all"{% if target=="CortexM" %},"rt"{%endif%}] \ No newline at end of file diff --git a/templates/rust/aurix_core.tera b/templates/rust/aurix_core.tera new file mode 100644 index 0000000..c4869c4 --- /dev/null +++ b/templates/rust/aurix_core.tera @@ -0,0 +1,37 @@ +{% import "macros.tera" as macros %} +/* +{{ir.license_text}} +*/ +#![allow(clippy::identity_op)] +#![allow(clippy::module_inception)] +#![allow(clippy::derivable_impls)] +#[allow(unused_imports)] +use crate::common::{*}; +#[allow(unused_imports)] +use crate::common::sealed; +#[doc = r"{{peri.description | svd_description_to_doc}}"] +#[derive(Copy, Clone, Eq, PartialEq)] +{% set peri_struct = "CsfrCpu" | to_struct_id -%} +{% set reg_base_addr = peri.base_addr[0] -%} +pub struct {{ peri_struct }}(pub(super) *mut u8); +unsafe impl core::marker::Send for CsfrCpu {} +unsafe impl core::marker::Sync for CsfrCpu {} +impl CsfrCpu { +{%- for register_name,reg in peri.registers %} +{{macros::register_core_func(types_mod="self",reg=reg, base_addr=reg_base_addr)}} +{% endfor -%} +{% for cluster_name,cluster in peri.clusters -%} +{{macros::cluster_func(types_mod="self",cluster=cluster)}} +{% endfor %} +} +{% for register_name,reg in peri.registers -%} +{{macros::register_struct(reg=reg)}} +{% endfor %} +{% for cluster_name,cluster in peri.clusters -%} +{{macros::cluster_struct(cluster=cluster)}} +{% endfor %} + + + + + diff --git a/templates/rust/build_cortex.tera b/templates/rust/build_cortex.tera new file mode 100644 index 0000000..597923f --- /dev/null +++ b/templates/rust/build_cortex.tera @@ -0,0 +1,16 @@ +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; +fn main() { + if env::var_os("CARGO_FEATURE_RT").is_some() { + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("device.x")) + .unwrap() + .write_all(include_bytes!("device.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + println!("cargo:rerun-if-changed=device.x"); + } + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/templates/rust/common.tera b/templates/rust/common.tera new file mode 100644 index 0000000..6114371 --- /dev/null +++ b/templates/rust/common.tera @@ -0,0 +1,782 @@ +/* +{{ir.license_text}} +*/ +use core::convert::From; +use core::marker::PhantomData; + +{% if tracing %} +#[cfg(feature = "tracing")] +use crate::tracing; +{% endif %} + +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct RW; +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct R; +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct W; + +pub(crate) mod sealed { + use super::*; + pub trait Access {} + impl Access for R {} + impl Access for W {} + impl Access for RW {} + use core::ops::{BitAnd, BitAndAssign, BitOrAssign, Not, Shl, Shr}; + + // It would be better with const fn + // waiting for RFC: const functions in traits #3490 + pub trait CastFrom { + fn cast_from(val: A) -> Self; + } + + impl CastFrom for u8 { + #[inline(always)] + fn cast_from(val: u64) -> Self { + val as Self + } + } + + impl CastFrom for u16 { + #[inline(always)] + fn cast_from(val: u64) -> Self { + val as Self + } + } + + impl CastFrom for u32 { + #[inline(always)] + fn cast_from(val: u64) -> Self { + val as Self + } + } + + impl CastFrom for u64 { + #[inline(always)] + fn cast_from(val: u64) -> Self { + val as Self + } + } + + pub trait RegNumberT: + Copy + + From + + Into + + CastFrom + + Shr + + Shl + + BitAndAssign + + BitAnd + + Not + + BitOrAssign +{ +} +impl RegNumberT for u8 {} +impl RegNumberT for u16 {} +impl RegNumberT for u32 {} +impl RegNumberT for u64 {} + + pub trait RegSpec { + type DataType: RegNumberT; + } +} + +pub trait Access: sealed::Access + Copy {} +impl Access for R {} +impl Access for W {} +impl Access for RW {} + +pub trait Read: Access {} +impl Read for RW {} +impl Read for R {} + +pub trait Write: Access {} +impl Write for RW {} +impl Write for W {} + +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct Reg { + ptr: *mut u8, + phantom: PhantomData<*mut (T, A)>, +} +unsafe impl Send for Reg {} +unsafe impl Sync for Reg {} + + + +use sealed::CastFrom; + +use sealed::{RegNumberT, RegSpec}; +#[doc(hidden)] +#[derive(Copy, Clone)] +pub struct RegValueT { + pub(crate) data: Reg::DataType, + pub(crate) mask: Reg::DataType, +} + +pub trait RegisterValue { + #[must_use] + fn new(data: T::DataType) -> Self; + /// Get raw register value + #[must_use] + fn get_raw(&self) -> T::DataType; + /// Return a copy with register value set to `value` and write mask fully set + #[must_use] + fn set_raw(self, value: T::DataType) -> Self; +} + +impl RegisterValue for RegValueT { +/// Create a register value from raw value + #[inline(always)] + fn new(data: T::DataType) -> RegValueT { + Self { + data, + mask: 0x0u8.into(), + } + } + /// Get raw register value + #[inline(always)] + fn get_raw(&self) -> T::DataType { + self.data + } + /// Return a copy with register value set to `value` and write mask fully set + #[inline(always)] + fn set_raw(mut self, value: T::DataType) -> Self { + self.data = value; + self.mask = !(Into::::into(0x0u8)); + self + } +} + +pub trait NoBitfieldReg: RegisterValue +where + Self: Sized, +{ + #[inline(always)] + #[must_use] + fn get(&self) -> Reg::DataType { + self.get_raw() + } + #[inline(always)] + #[must_use] + fn set(self, value: Reg::DataType) -> Self { + self.set_raw(value) + } +} + +impl Reg +where + T: RegSpec, + A: Access, +{ + #[inline(always)] + #[must_use] + pub(crate) const fn from_ptr(ptr: *mut u8) -> Self { + Self { + ptr, + phantom: PhantomData, + } + } + + #[inline(always)] + #[must_use] + pub const fn ptr(&self) -> *mut T::DataType { + self.ptr as _ + } + {% if tracing %} + /// Returns the address of the register. + pub fn addr(&self) -> usize { + self.ptr as usize + } + {% endif %} +} +impl Reg +where + T: RegSpec, + A: Read, +{ + /// Read register and return a register value + /// + /// # Safety + /// Read operation could cause undefined behavior for some peripheral. Developer shall read device user manual. + /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread. + /// + #[inline(always)] + #[must_use] + pub unsafe fn read(&self) -> RegValueT { + {% if tracing %} + #[cfg(feature = "tracing")] + let val = { + let mut buf: u64 = 0x0; + tracing::READ_FN.with(|rf| { + if let Some(rf) = rf.get() { + buf = rf(self.addr(), std::mem::size_of::()); + } else { + #[cfg(not(feature = "tracing_dummy"))] + panic!("Please, provide an handler for read with tracing::set_read_fn(callback);"); + } + }); + T::DataType::cast_from(buf) + }; + #[cfg(not(feature = "tracing"))] + {% endif %} + let val = (self.ptr as *mut T::DataType).read_volatile(); + RegValueT::::new(val) + } +} + +impl Reg +where + T: RegSpec, + A: Write, +{ + /// Write register value back to register + /// + /// # Arguments + /// + /// * `reg_value` - A string slice that holds the name of the person + /// + /// # Safety + /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual. + /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread. + /// + #[inline(always)] + pub unsafe fn write(&self, reg_value: RegValueT) { + {% if tracing %} + #[cfg(feature = "tracing")] + tracing::WRITE_FN.with(|wf| { + if let Some(wf) = wf.get() { + wf( + self.addr(), + std::mem::size_of::(), + reg_value.data.into(), + ) + } else { + #[cfg(not(feature = "tracing_dummy"))] + panic!("Please, provide an handler for read with tracing::set_read_fn(callback);"); + } + }); + #[cfg(not(feature = "tracing"))] + {% endif %} + (self.ptr as *mut T::DataType).write_volatile(reg_value.data); + } +} + +impl Reg +where + T: RegSpec, + A: Write, +RegValueT: Default, +{ + /// Init register with value returned by the closure. + /// + /// # Arguments + /// + /// * `f` - Closure that receive as input a register value initialized with register value at Power On Reset. + /// + /// # Safety + /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual. + /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread. + /// + #[inline(always)] + /// Write value computed by closure that receive as input the reset value of register + pub unsafe fn init(&self, f: impl FnOnce(RegValueT) -> RegValueT) { + let val = RegValueT::::default(); + let res = f(val); + self.write(res); + } +} + +impl Reg +where + T: RegSpec, + A: Read + Write, +{ + #[inline(always)] + /// Write register with value returned by the closure. + /// + /// # Arguments + /// + /// * `f` - Closure that receive as input a register value read from register. + /// + /// # Safety + /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual. + /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread. + /// + pub unsafe fn modify(&self, f: impl FnOnce(RegValueT) -> RegValueT) { + let val = self.read(); + let res = f(val); + self.write(res); + } +} +{% if target=="Aurix" %} +impl Reg +where + T: RegSpec, + RegValueT: Default, + A: Write, +{ + #[inline(always)] + /// Write register bitfield atomically using value returned by closure. + /// Only the bitfield updated by closure are written back to the register. + /// `modify_atomic` use `ldmst` assembly instruction that stall the bus until update completion. + /// This function can be used only with 32 bits register. + /// + /// # Arguments + /// + /// * `f` - Closure that receive as input register value initialized with register value at Power On Reset. + /// + /// # Safety + /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual. + /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread. + /// + pub unsafe fn modify_atomic(&self, f: impl FnOnce(RegValueT) -> RegValueT) { + let val = RegValueT::::default(); + let res = f(val); + {% if tracing %} + #[cfg(feature="tracing")] + tracing::LDMST.with(|ldmstf| { + if let Some(ldmstf) = ldmstf.get() { + ldmstf(self.addr(), res.data as u64 | ((res.mask as u64) << 32)) + } else { + #[cfg(not(feature = "tracing_dummy"))] + panic!("Please, provide an handler for ldmst with tracing::set_ldmst_fn(callback);"); + } + }); + #[cfg(not(feature="tracing"))] + {% endif -%} + unsafe { + core::arch::tricore::intrinsics::__ldmst(self.ptr as *mut u32, res.data, res.mask); + } + + } +} + +#[cfg(not(feature="tracing"))] +use core::arch::tricore::intrinsics::{__mfcr, __mtcr}; +#[cfg(all(any(target_feature = "tc18", doc),not(feature="tracing")))] +use core::arch::tricore::intrinsics::{__mfdcr, __mtdcr}; + +/// Type of core special register of Aurix (CSFR) +pub struct RegCore { + phantom: PhantomData<*mut (T, A)>, +} + +impl RegCore { + pub const unsafe fn new() -> Self { + RegCore { + phantom: PhantomData, + } + } +} + +unsafe impl Send for RegCore {} +unsafe impl Sync for RegCore {} +impl, A: Access, const ADDR: u16> RegCore + +{ + /// Read Aurix core register (32 bit wide) and return a register value + /// + /// # Safety + /// Read operation could cause undefined behavior for some core register. Developer shall read device user manual. + /// Function must be executed from proper core. + /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread. + /// + #[inline(always)] + #[must_use] + pub unsafe fn read(&self) -> RegValueT + where + A: Read, + { + + #[cfg(feature = "tracing")] + let val = { + let mut buf: u64 = 0x0; + tracing::READ_FN.with(|rf| { + buf = rf.get().unwrap()(ADDR as usize, std::mem::size_of::()); + }); + T::DataType::cast_from(buf) + }; + + #[cfg(not(feature = "tracing"))] + let val: T::DataType = __mfcr::(); + RegValueT::::new(val) + } + /// Write Aurix core register (32 bit wide) value back to register + /// + /// # Arguments + /// + /// * `reg_value` - A string slice that holds the name of the person + /// + /// # Safety + /// Write operation could cause undefined behavior for some core register. Developer shall read device user manual. + /// Function must be executed from proper core. + /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread. + /// + #[inline(always)] + pub unsafe fn write(&self, reg_value: RegValueT) + where + A: Write, + { + #[cfg(feature = "tracing")] + tracing::WRITE_FN.with(|wf| { + wf.get().unwrap()( + ADDR as usize, + std::mem::size_of::(), + reg_value.data.into(), + ) + }); + #[cfg(not(feature = "tracing"))] + __mtcr::(reg_value.data); + } + /// Init register with value returned by the closure. + /// + /// # Arguments + /// + /// * `f` - Closure that receive as input a register value initialized with register value at Power On Reset. + /// + /// # Safety + /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual. + /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread. + /// + #[inline(always)] + /// Write value computed by closure that receive as input the reset value of register + pub unsafe fn init(&self, f: impl FnOnce(RegValueT) -> RegValueT) + where + A: Write, + RegValueT: Default, + { + let val = Default::default(); + let res = f(val); + self.write(res); + } + #[inline(always)] + /// Write register with value returned by the closure. + /// + /// # Arguments + /// + /// * `f` - Closure that receive as input a register value read from register. + /// + /// # Safety + /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual. + /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread. + /// + pub unsafe fn modify(&self, f: impl FnOnce(RegValueT) -> RegValueT) + where + A: Read + Write, + { + let val = self.read(); + let res = f(val); + self.write(res); + } +} + +#[cfg(any(target_feature = "tc18", doc))] +impl, A: Access, const ADDR: u16> RegCore { + /// Read Aurix core register (64 bit wide) and return a register value + /// + /// # Safety + /// Read operation could cause undefined behavior for some core register. Developer shall read device user manual. + /// Function must be executed from proper core. + /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread. + /// + #[inline(always)] + #[must_use] + pub unsafe fn read(&self) -> RegValueT + where + A: Read, + { + #[cfg(feature = "tracing")] + let val = { + let mut buf: u64 = 0x0; + tracing::READ_FN.with(|rf| { + buf = rf.get().unwrap()(self.addr(), std::mem::size_of::()); + }); + T::DataType::cast_from(buf) + }; + #[cfg(not(feature = "tracing"))] + let val: T::DataType = __mfdcr::(); + RegValueT::::new(val) + } + /// Write Aurix core register (64 bit wide) value back to register + /// + /// # Arguments + /// + /// * `reg_value` - A string slice that holds the name of the person + /// + /// # Safety + /// Write operation could cause undefined behavior for some core register. Developer shall read device user manual. + /// Function must be executed from proper core. + /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread. + /// + #[inline(always)] + pub unsafe fn write(&self, reg_value: RegValueT) + where + A: Write, + { + + #[cfg(feature = "tracing")] + tracing::WRITE_FN.with(|wf| { + wf.get().unwrap()( + self.addr(), + std::mem::size_of::(), + reg_value.data().into(), + ) + }); + #[cfg(not(feature = "tracing"))] + __mtdcr::(reg_value.data); + } + /// Init register with value returned by the closure. + /// + /// # Arguments + /// + /// * `f` - Closure that receive as input a register value initialized with register value at Power On Reset. + /// + /// # Safety + /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual. + /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread. + /// + #[inline(always)] + /// Write value computed by closure that receive as input the reset value of register + pub unsafe fn init(&self, f: impl FnOnce(RegValueT) -> RegValueT) + where + A: Write, + RegValueT: Default, + { + let val = Default::default(); + let res = f(val); + self.write(res); + } + #[inline(always)] + /// Write register with value returned by the closure. + /// + /// # Arguments + /// + /// * `f` - Closure that receive as input a register value read from register. + /// + /// # Safety + /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual. + /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread. + /// + pub unsafe fn modify(&self, f: impl FnOnce(T) -> T) + where + A: Read + Write, + { + let val = self.read(); + let res = f(val); + self.write(res); + } +} + +{% endif %} +#[repr(transparent)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] +pub struct EnumBitfieldStruct(pub Q, PhantomData); + +impl EnumBitfieldStruct { + pub const fn new(value: Q) -> Self { + Self(value, PhantomData) + } +} + +impl From> for u64 { + #[inline(always)] + fn from(value: EnumBitfieldStruct) -> Self { + value.0.into() + } +} +impl CastFrom for EnumBitfieldStruct { + #[inline(always)] + fn cast_from(val: u64) -> Self { + Self(Q::cast_from(val), PhantomData) + } +} + +impl From for EnumBitfieldStruct { + #[inline(always)] + fn from(value: Q) -> Self { + Self(value, PhantomData) + } +} +pub struct RegisterField< + const START_OFFSET: usize, + const MASK: u64, + const DIM: u8, + const DIM_INCREMENT: u8, + ValueType, + T, + A, +> where + T: RegSpec, + A: Access, +{ + data: RegValueT, + index: u8, + marker: PhantomData<(ValueType, A)>, +} + +impl< + const START_OFFSET: usize, + const MASK: u64, + const DIM: u8, + const DIM_INCREMENT: u8, + ValueType, + T, + A, + > RegisterField +where + T: RegSpec, + A: Access, +{ + #[allow(dead_code)] + #[inline(always)] + pub(crate) fn from_register(data: RegValueT, index: u8) -> Self { + Self { + data, + index, + marker: PhantomData, + } + } + + #[inline(always)] + #[must_use] + pub fn mask(&self) -> T::DataType { + T::DataType::cast_from(MASK) + } + + #[inline(always)] + #[must_use] + pub const fn offset(&self) -> usize { + START_OFFSET + (self.index * DIM_INCREMENT) as usize + } +} + +impl< + const START_OFFSET: usize, + const MASK: u64, + const DIM: u8, + const DIM_INCREMENT: u8, + ValueType, + T, + A, + > RegisterField +where + T: RegSpec, + A: Read, + ValueType: CastFrom, +{ + #[inline(always)] + pub fn get(&self) -> ValueType { + let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize; + let filtered: T::DataType = (self.data.data >> offset) & T::DataType::cast_from(MASK); + ValueType::cast_from(filtered.into()) + } +} + +impl< + const START_OFFSET: usize, + const MASK: u64, + const DIM: u8, + const DIM_INCREMENT: u8, + ValueType, + T, + A, + > RegisterField +where + T: RegSpec, + A: Write, + u64: From, +{ + #[inline(always)] + #[must_use] + pub fn set(mut self, value: ValueType) -> RegValueT { + let mask = T::DataType::cast_from(MASK); + let value: T::DataType = T::DataType::cast_from(Into::::into(value)) & mask; + let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize; + let masked_offset: T::DataType = mask << offset; + self.data.mask |= masked_offset; + self.data.data &= !masked_offset; + self.data.data |= value << offset; + self.data + } +} + +pub struct RegisterFieldBool< + const START_OFFSET: usize, + const DIM: u8, + const DIM_INCREMENT: u8, + T, + A, +> where + T: RegSpec, + A: Access, +{ + data: RegValueT, + index: u8, + marker: PhantomData, +} + +impl + RegisterFieldBool +where + T: RegSpec, + A: Read, +{ + #[inline(always)] + pub fn get(&self) -> bool { + let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize; + let filtered = (self.data.data.into() >> offset) & 1; + filtered == 1 + } +} + +impl + RegisterFieldBool +where + T: RegSpec, + A: Write, +{ + #[inline(always)] + #[must_use] + pub fn set(mut self, value: bool) -> RegValueT { + let value: T::DataType = if value { + T::DataType::cast_from(1u64) + } else { + T::DataType::cast_from(0u64) + }; + let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize; + let masked_offset = T::DataType::cast_from(0x1u64) << offset; + self.data.mask |= masked_offset; + self.data.data &= !masked_offset; + self.data.data |= value << offset; + self.data + } +} + +impl + RegisterFieldBool +where + T: RegSpec, + A: Access, +{ + #[inline(always)] + #[allow(dead_code)] + pub(crate) fn from_register(data: RegValueT, index: u8) -> Self { + Self { + data, + index, + marker: PhantomData, + } + } + #[inline(always)] + #[must_use] + pub fn mask(&self) -> T::DataType { + T::DataType::cast_from(1) + } + + #[inline(always)] + #[must_use] + pub const fn offset(&self) -> usize { + START_OFFSET + (self.index * DIM_INCREMENT) as usize + } +} diff --git a/templates/rust/device_x.tera b/templates/rust/device_x.tera new file mode 100644 index 0000000..1e0e7e0 --- /dev/null +++ b/templates/rust/device_x.tera @@ -0,0 +1,5 @@ +{% for interrupt in ir.interrupt_table -%} +{% if interrupt -%} +PROVIDE({{interrupt.name | upper}} = DefaultHandler); +{% endif -%} +{% endfor %} \ No newline at end of file diff --git a/templates/rust/lib.tera b/templates/rust/lib.tera new file mode 100644 index 0000000..917fba5 --- /dev/null +++ b/templates/rust/lib.tera @@ -0,0 +1,183 @@ +/* +{{ir.license_text}} +*/ +{%- if tracing %} +#![cfg_attr(not(feature = "tracing"), no_std)] +{%- else %} +#![no_std] +{%- endif %} +{% if target=="Aurix" %} +#![cfg_attr(target_arch = "tricore", feature(stdsimd))] +{% endif %} +#![allow(non_camel_case_types)] +#![doc = "{{ir.device.description | svd_description_to_doc}}"] +pub mod common; +pub use common::*; + +{% if tracing %} +#[cfg(feature = "tracing")] +pub mod reg_name; +#[cfg(feature = "tracing")] +pub mod tracing; +{% endif %} +{% for peri_mod_name, peri in ir.peripheral_mod -%} +{%- set module_name = peri.name | to_mod_id -%} +#[cfg(feature = "{{module_name}}")] +pub mod {{module_name}}; +{% endfor -%} +{% if ir_csfr %} +{% for peri_mod_name, peri in ir_csfr.peripheral_mod -%} +{%- set module_name = peri.name | to_mod_id -%} +#[cfg(feature = "{{module_name}}")] +pub mod {{module_name}}; +#[cfg(feature = "{{module_name}}")] +pub use {{module_name}} as csfr_cpu; +{% endfor -%} +{% endif %} + + +{% for name,p in ir.peripheral_mod %} +{%- set module_name = p.name | to_mod_id -%} +{%- set module_struct = p.name | to_struct_id -%} +{%- set full_path_struct = module_name ~ "::" ~ module_struct -%} +#[cfg(feature = "{{module_name}}")] +{%- if p.base_addr | length == 1 %} +pub const {{name | upper}}: {{full_path_struct}} = {{full_path_struct}}({{p.base_addr[0] | to_hex }}u32 as _); +{% else %} +pub const {{name | upper}}:[{{full_path_struct}};{{ p.base_addr | length }}] = [{%- for addr in p.base_addr %} {{full_path_struct}}({{addr | to_hex }}u32 as _), {% endfor -%}]; +{%- endif -%} +{%- endfor -%} +{% if ir_csfr %} +#[cfg(any( +{%- set module_struct = "csfr_cpu" | to_struct_id -%} +{%- set full_path_struct = "csfr_cpu" ~ "::" ~ module_struct -%} +{% for name,p in ir_csfr.peripheral_mod %} +{%- set module_name = p.name | to_mod_id -%} +{% if not loop.last %}feature = "{{module_name}}",{% else %}feature = "{{module_name}}"))] +{%- if p.base_addr | length == 1 %} +pub const {{"csfr_cpu" | upper}}: {{full_path_struct}} = {{full_path_struct}}({{p.base_addr[0] | to_hex }}u32 as _); +{% else %} +pub const {{"csfr_cpu" | upper}}:[{{full_path_struct}};{{ p.base_addr | length }}] = [{%- for addr in p.base_addr %} {{full_path_struct}}({{addr | to_hex }}u32 as _), {% endfor -%}]; +{% endif %} +{% endif %} +{%- endfor -%} + + +{% endif %} + +{#- Block to support Cortex-m-rt #} +{% if target=="CortexM" -%} +pub use cortex_m::peripheral::Peripherals as CorePeripherals; +pub use cortex_m::peripheral::{CBP, CPUID, DCB, DWT, FPB, {%if ir.fpu_present %}FPU ,{%endif%} ITM, {%if ir.mpu_present %}MPU ,{%endif%} NVIC, SCB, {%if not ir.vendor_systick_config %}SYST,{%endif%} TPIU}; +{%- if ir.nvic_prio_bits %} +#[doc = "Number available in the NVIC for configuring priority"] +pub const NVIC_PRIO_BITS: u8 = {{ir.nvic_prio_bits}}; +{%- endif %} +#[doc(hidden)] +pub union Vector { + _handler: unsafe extern "C" fn(), + _reserved: u32, +} +{%- if ir.interrupt_table | length > 0 %} +#[cfg(feature = "rt")] +pub use self::Interrupt as interrupt; +#[cfg(feature = "rt")] +pub use cortex_m_rt::interrupt; +#[cfg(feature = "rt")] +extern "C" { + {% for interrupt in ir.interrupt_table -%} + {% if interrupt -%} + fn {{interrupt.name | upper}}(); + {% endif -%} + {% endfor -%} + +} +#[cfg(feature = "rt")] +#[doc(hidden)] +#[link_section = ".vector_table.interrupts"] +#[no_mangle] +pub static __INTERRUPTS: [Vector; {{ir.interrupt_table | length}}] = [ + {% for interrupt in ir.interrupt_table -%} + {% if interrupt -%} + Vector { _handler: {{interrupt.name | upper}} }, + {% else -%} + Vector { _reserved: 0 }, + {% endif -%} + {% endfor -%} +]; +#[doc = "Enumeration of all the interrupts."] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[repr(u16)] +pub enum Interrupt { + {% for interrupt in ir.interrupt_table -%} + {% if interrupt -%} + #[doc = "{{interrupt.description | svd_description_to_doc}}"] + {{interrupt.name | upper}} = {{interrupt.value}}, + {% endif -%} + {% endfor -%} +} +unsafe impl cortex_m::interrupt::InterruptNumber for Interrupt { + #[inline(always)] + fn number(self) -> u16 { + self as u16 + } +} +{% endif -%} +#[allow(non_snake_case)] +/// Required for compatibility with RTIC and other frameworks +pub struct Peripherals { + {% for name,p in ir.peripheral_mod %} + {%- set module_name = p.name | to_mod_id -%} + {%- set module_struct = p.name | to_struct_id -%} + {%- set full_path_struct = module_name ~ "::" ~ module_struct -%} + #[cfg(feature = "{{module_name}}")] + {%- if p.base_addr | length == 1 %} + pub {{name | upper}}: {{full_path_struct}}, + {% else %} + pub {{name | upper}}:[{{full_path_struct}};{{ p.base_addr | length }}], + {%- endif -%} + {%- endfor -%} + {% if ir_csfr %} + {% for name,p in ir_csfr.peripheral_mod %} + {%- set module_name = p.name | to_mod_id -%} + {%- set module_struct = p.name | to_struct_id -%} + {%- set full_path_struct = module_name ~ "::" ~ module_struct -%} + #[cfg(feature = "{{module_name}}")] + {%- if p.base_addr | length == 1 %} + pub {{name | upper}}: {{full_path_struct}}, + {% else %} + pub {{name | upper}}:[{{full_path_struct}};{{ p.base_addr | length }}], + {%- endif -%} + {%- endfor -%} + {%- endif -%} + + +} + +impl Peripherals { + /// Returns Peripheral struct multiple times + /// Required for compatibility with RTIC and other frameworks + #[inline] + pub fn take() -> Option { + Some(Self::steal()) + } + + /// Returns Peripheral struct multiple times + /// Required for compatibility with RTIC and other frameworks + #[inline] + pub fn steal() -> Self { + + Peripherals{ + {% for name,p in ir.peripheral_mod %} + {%- set module_name = p.name | to_mod_id -%} + {%- set module_struct = p.name | to_struct_id -%} + {%- set full_path_struct = module_name ~ "::" ~ module_struct %} + #[cfg(feature = "{{module_name}}")] + {{name | upper}}: crate::{{name | upper}}, + {%- endfor %} + + } + + } +} +{% endif -%} \ No newline at end of file diff --git a/templates/rust/macros.tera b/templates/rust/macros.tera new file mode 100644 index 0000000..c88261d --- /dev/null +++ b/templates/rust/macros.tera @@ -0,0 +1,183 @@ +{%- macro reg_size2num_type(bit_size) -%} +{%- if bit_size=="BIT8" -%} +u8 +{%- elif bit_size=="BIT16" -%} +u16 +{%- elif bit_size=="BIT32" -%} +u32 +{%- else -%} +Unsupported register size +{%- endif -%} +{%- endmacro reg_size2num_type -%} + +{# Generated register function #} +{%- macro register_func(types_mod,reg) -%} +{%- set reg_struct = reg.name | to_struct_id -%} +{%- set reg_struct_name = types_mod ~ "::" ~ reg_struct -%} +{%- set reg_mod_name = reg.name | to_mod_id -%} +#[doc = "{{reg.description | svd_description_to_doc}}"] +#[inline(always)] +{% if reg.dim == 1 -%} +pub const fn {{reg.name | to_func_id }}(&self) -> crate::common::Reg<{{reg_struct_name}}_SPEC, crate::common::{{reg.access}}> { + unsafe { crate::common::Reg::from_ptr(self.0.add({{reg.offset}}usize)) } +} +{%- else -%} +pub const fn {{reg.name | to_func_id }}(&self) -> [crate::common::Reg<{{reg_struct_name}}_SPEC, crate::common::{{reg.access}}>;{{reg.dim}}] { + unsafe { [ + {%- for index in range(end=reg.dim) -%} + crate::common::Reg::from_ptr(self.0.add({{reg.offset | to_hex }}usize + {{index * reg.dim_increment | to_hex }}usize )), + {% endfor -%} + ] } +} +{%- endif -%} +{%- endmacro -%} + + +{# Generated core register function #} +{%- macro register_core_func(types_mod,reg, base_addr) -%} +{%- set reg_struct = reg.name | to_struct_id -%} +{%- set reg_struct_name = types_mod ~ "::" ~ reg_struct -%} +{%- set reg_mod_name = reg.name | to_mod_id -%} +{%- set reg_addr = base_addr+reg.offset | to_hex -%} +#[doc = r"{{reg.description | svd_description_to_doc}}"] +#[inline(always)] +{% if reg.dim == 1 -%} +pub const fn {{reg.name | to_func_id }}(&self) -> crate::common::RegCore<{{reg_struct_name}}_SPEC, crate::common::{{reg.access}}, {{reg_addr}}> { + unsafe { crate::common::RegCore::new() } +} +{%- endif -%} +{%- endmacro -%} + + +{%- macro bitfield_type(field,reg_struct_name,reg_mod_name,turbofish) -%} +{%-if turbofish %}{%set separator = "::"%}{%else%}{%set separator = ""%}{%endif-%} +{%- if not field.enum_type and field.mask == 1 %} + crate::common::RegisterFieldBool{{separator}}<{{field.offset}},{{field.dim}},{{field.dim_increment}},{{reg_struct_name}}_SPEC,crate::common::{{field.access}}> +{%- else -%} + {%- if field.enum_type -%} + {%- set enum_name_type= field.enum_type.name | to_struct_id -%} + {%- set field_type= reg_mod_name ~ "::" ~ enum_name_type -%} + {%- else %} + {%- set field_type= self::reg_size2num_type(bit_size=field.size) -%} + {%- endif -%} + crate::common::RegisterField{{separator}}<{{field.offset}},{{field.mask | to_hex}},{{field.dim}},{{field.dim_increment}},{{field_type}}, {{reg_struct_name}}_SPEC,crate::common::{{field.access}}> +{%- endif -%} +{%- endmacro -%} + + +{%- macro register_struct(reg) -%} +{%- set reg_struct_name = reg.name | to_struct_id -%} +{%- set reg_mod_name = reg.name | to_mod_id -%} + +#[doc(hidden)] +#[derive(Copy, Clone,Eq, PartialEq)] +pub struct {{reg_struct_name}}_SPEC; +impl crate::sealed::RegSpec for {{reg_struct_name}}_SPEC { + type DataType = {{self::reg_size2num_type(bit_size=reg.size)}}; +} +#[doc = "{{reg.description | svd_description_to_doc}}"] +pub type {{reg_struct_name}} = crate::RegValueT<{{reg_struct_name}}_SPEC>; + +{% if not reg.fields %} +impl NoBitfieldReg<{{reg_struct_name}}_SPEC> for {{reg_struct_name}} {} +{% else -%} +impl {{reg_struct_name}} { + {%- for field in reg.fields %} + #[doc = "{{field.description | svd_description_to_doc}}"] + #[inline(always)] + {%- if field.dim > 1 -%} + pub fn {{field.name | to_func_id }}(self,index:u8) -> {{self::bitfield_type(field=field,reg_struct_name=reg_struct_name,reg_mod_name=reg_mod_name,turbofish=false)}} { + assert!(index < {{field.dim}}); + {{self::bitfield_type(field=field,reg_struct_name=reg_struct_name,reg_mod_name=reg_mod_name,turbofish=true)}}::from_register(self,index) + + } + {%- else %} + pub fn {{field.name | to_func_id }}(self) -> {{self::bitfield_type(field=field,reg_struct_name=reg_struct_name,reg_mod_name=reg_mod_name,turbofish=false)}} { + {{self::bitfield_type(field=field,reg_struct_name=reg_struct_name,reg_mod_name=reg_mod_name,turbofish=true)}}::from_register(self,0) + } + {%- endif -%} + {%- endfor %} +} +{% endif -%} +impl core::default::Default for {{reg_struct_name}} { + #[inline(always)] + fn default() -> {{reg_struct_name}} { + as RegisterValue<_>>::new({{reg.reset_value}}) + } +} +{% if reg.has_enumerated_fields -%} +pub mod {{reg_mod_name}} { + {% for field in reg.fields -%} + {%-if field.enum_type -%} + {%- set enum_name_type= field.enum_type.name | to_struct_id %} + #[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] + pub struct {{enum_name_type}}_SPEC; + pub type {{enum_name_type}} = crate::EnumBitfieldStruct<{{self::reg_size2num_type(bit_size=field.enum_type.size)}},{{enum_name_type}}_SPEC>; + impl {{enum_name_type}} { + {%- for val in field.enum_type.values %} + #[doc = "{{val.description | svd_description_to_doc}}"] + pub const {{val.name | to_enumerated_const_id }}:Self =Self::new({{val.value}}); + {%- endfor %} + } + {%- endif -%} + {% endfor %} +} +{%- endif -%} +{%- endmacro -%} + +{# Generate getter for clusters #} +{%- macro cluster_func(types_mod,cluster) -%} +{%- if cluster.is_derived_from -%} +{%- set cluster_struct_path = cluster.struct_path -%} +{%- else -%} +{%- set cluster_struct_id = cluster.struct_id | to_struct_id -%} +{%- set cluster_struct_path = types_mod ~ "::" ~ cluster_struct_id -%} +{%- endif -%} +{%- set cluster_func = cluster.name | to_func_id -%} +#[doc = "{{cluster.description | svd_description_to_doc}}"] +#[inline(always)] +{%- if cluster.dim == 1 %} +pub fn {{cluster_func}}(self) -> {{cluster_struct_path}}{ + unsafe { {{cluster_struct_path}}(self.0.add({{cluster.offset}}usize)) } +} +{%- else %} +pub fn {{cluster_func}}(self) -> [{{cluster_struct_path}};{{cluster.dim}}] { + unsafe { [ + {%- for index in range(end=cluster.dim) -%} + {{cluster_struct_path}}(self.0.add({{cluster.offset | to_hex}}usize + {{index*cluster.dim_increment | to_hex }}usize)), + {% endfor -%} + ] } +} +{%- endif -%} +{%- endmacro -%} + +{# Macro to generate structure and module for a cluster#} +{%- macro cluster_struct(cluster) -%} +{%- if not cluster.is_derived_from -%} +{%- set cluster_struct = cluster.struct_id | to_struct_id -%} +{%- set cluster_mod = cluster.struct_id | to_mod_id -%} +#[doc = "{{cluster.description | svd_description_to_doc}}"] +#[derive(Copy, Clone, Eq, PartialEq)] +pub struct {{ cluster_struct }}(pub(super) *mut u8); +unsafe impl core::marker::Send for {{ cluster_struct}} {} +unsafe impl core::marker::Sync for {{ cluster_struct }} {} +impl {{cluster_struct}} { + {% for register_name,reg in cluster.registers -%} + {{self::register_func(types_mod=cluster_mod,reg=reg)}} + {% endfor -%} + {% for cluster_name,cluster in cluster.clusters -%} + {{self::cluster_func(types_mod=cluster_mod,cluster=cluster)}} + {% endfor -%} +} +pub mod {{cluster_mod}} { + #[allow(unused_imports)] + use crate::common::{*}; + {% for register_name,reg in cluster.registers -%} + {{self::register_struct(reg=reg)}} + {% endfor -%} + {% for cluster_name,cluster in cluster.clusters -%} + {{self::cluster_struct(cluster=cluster) }} + {% endfor -%} +} +{%- endif -%} +{%- endmacro -%} diff --git a/templates/rust/peri_mod.tera b/templates/rust/peri_mod.tera new file mode 100644 index 0000000..1b1948e --- /dev/null +++ b/templates/rust/peri_mod.tera @@ -0,0 +1,37 @@ +{% import "macros.tera" as macros %} +/* +{{ir.license_text}} +*/ +#![allow(clippy::identity_op)] +#![allow(clippy::module_inception)] +#![allow(clippy::derivable_impls)] +#[allow(unused_imports)] +use crate::common::{*}; +#[allow(unused_imports)] +use crate::common::sealed; +#[doc = r"{{peri.description | svd_description_to_doc}}"] +#[derive(Copy, Clone, Eq, PartialEq)] +{% set peri_struct = peri.name | to_struct_id -%} +pub struct {{ peri_struct }}(pub(super) *mut u8); +unsafe impl core::marker::Send for {{ peri_struct }} {} +unsafe impl core::marker::Sync for {{ peri_struct }} {} +impl {{ peri_struct }} { +{%- for register_name,reg in peri.registers %} +{{macros::register_func(types_mod="self",reg=reg)}} +{% endfor -%} +{% for cluster_name,cluster in peri.clusters -%} +{{macros::cluster_func(types_mod="self",cluster=cluster)}} +{% endfor %} +} +{% for register_name,reg in peri.registers -%} +{{macros::register_struct(reg=reg)}} +{% endfor %} +{% for cluster_name,cluster in peri.clusters -%} +{{macros::cluster_struct(cluster=cluster)}} +{% endfor %} + + + + + + diff --git a/templates/rust/reg_name.tera b/templates/rust/reg_name.tera new file mode 100644 index 0000000..2f16213 --- /dev/null +++ b/templates/rust/reg_name.tera @@ -0,0 +1,29 @@ +/* +{{ir.license_text}} +*/ +//! Contains perfect hash function that maps form raw addresses to +//! a string containing the names of all registers that point to an address. +//! +//! When using tracing feature to record accesses to registers, the exact +//! API path, though which a specific address was accessed gets lost. +//! This poses a problem when recorded register accesses contain accesses +//! to unexpected registers. [`reg_name_from_addr`] can be used to make +//! logs of raw register accesses more readable to humans by providing a list +//! of names of registers that alias a specific physical address. +//! +use phf::phf_map; + +/// Get a &str name of a register given it's address. +pub fn reg_name_from_addr(addr: u64) -> Option<&'static &'static str> { + REGISTER_NAMES.get(&addr) +} + +static REGISTER_NAMES: phf::Map = phf_map! { + {%- for address, registers in register_addresses %} + {{ address | num_str_to_hex }}u64 => " + {%- for register_path in registers %} + {{ register_path | render_path }}, + {%- endfor %} + ", + {%- endfor %} +}; diff --git a/templates/rust/tracing.tera b/templates/rust/tracing.tera new file mode 100644 index 0000000..328aef5 --- /dev/null +++ b/templates/rust/tracing.tera @@ -0,0 +1,229 @@ +/* +{{ir.license_text}} +*/ +use std::sync::OnceLock; + +thread_local! { + /// Function that will be called when reading from a register using + /// though the PAC API. + /// + /// The function parameters are the following: + /// - a u64 representing the register address + /// - a u64 representing the read mask (i.e. how many bits are read) + /// This is necessary due to the way that the generated PACs handles + /// generic register sizes. + pub(crate) static READ_FN: OnceLocku64> = OnceLock::new(); + /// Function that will be called when writing to a register using + /// though the PAC API. + /// + /// The function parameters are the following: + /// - a u64 representing the register address + /// - a u64 representing the write mask (i.e. how many bits are read) + /// This is necessary due to the way that the generated PACs handles + /// generic register sizes. + /// - a u64 representing the value that gets written to the register + pub (crate) static WRITE_FN: OnceLock = OnceLock::new(); + + pub (crate) static LDMST: OnceLock = OnceLock::new(); +} + +/// Macro to generate the setters for the thread_local static +/// register access functions. +macro_rules! set_access_fn { + ($CONST_ID:ident,$fn_id:ident,$fn_literal:literal,$access_fn_type:ty,$doc:literal) => { + #[doc=$doc] + pub fn $fn_id(fun: $access_fn_type) -> Result<(), String> { + $CONST_ID.with(|function| { + function.set(fun).or_else(|_| { + Err(format!( + "The thread local {} can only be set once.", + $fn_literal + )) + }) + }) + } + }; +} + +set_access_fn!(READ_FN, set_read_fn, "read_fn", fn(usize, usize) -> u64, "Set the function that is called when a read to a register happens\n through the PAC API.\n The function is called with the following arguments (in order):\n - a u64 representing the register address\n - a u64 representing the read mask (i.e. how many bits are read)\n This is necessary due to the way that the generated PACs handle\n generic register sizes.\n"); +set_access_fn!(WRITE_FN, set_write_fn, "write_fn", fn(usize, usize, u64),"Set the function that is called when a write to a register happens\n through the PAC API.\n The function is called with the following arguments (in order):\n - a u64 representing the register address\n - a u64 representing the write mask (i.e. how many bits are read)\n This is necessary due to the way that the generated PACs handle\n generic register sizes.\n - a u64 representing the value that gets written to the register\n"); +{% if target == "Aurix" %} +set_access_fn!(LDMST, set_ldmst_fn, "ldmst_fn", fn(usize, u64),"Set the function that is called when a LDMST access to a register happens\n through the PAC API.\n **TODO**: validate if this API is even correct. Is it necessary to\n pass the mask to or is the value sufficient?\n The function is called with the following arguments (in order):\n - a u64 representing the register address\n - a u64 representing the ldmst mask (i.e. how many bits are read)\n This is necessary due to the way that the generated PACs handle\n generic register sizes.\n - a u64 representing the value that gets written to the register\n"); +{% endif %} + + + +// # Why does this exist? +// +// When writing tests, it is useful to be able to read/write registers that +// are normally **read-only/write-only**. +// Especially when simulating registers on non-embedded targets +// one might want to provide a test value to an input buffer register, or +// read a value from a write only resister to check its value. +// +// The two traits: `ReadOnlyWrite` and `WriteOnlyRead` defined in this +// module, provide exactly that functionality to every [`Reg`](crate::common::Reg). +// +// By importing this module, all read-only registers become `ReadOnlyWrite` +// and all write-only registers become `WriteOnlyRead`. +// With these new markers the following functions are unlocked: +// - `read_write_only` (like read but for **write-only** registers) +// - `write_read_only` (like write but for **read-only** registers) +// - `init_read_only` (like init but for **read-only** registers) +// - `modify_read_only` (like modify but for **read-only** registers) +// - `modify_write_only` (like modify but for **write-only** registers) +// +// This separates these special register accesses form the ones allowed as by +// the SVD-spec of the target device. The separation is reinforced by keeping +// the trait in a separate module, requiring an explicit import of the module. +// The module should not be imported in productive code, only in test code. +// +// # Alternative Solution +// +// In previous commits, an alternative solution in common.rs as tested: +// ```rust,ignore +// #[cfg(feature = "tracing")] +// impl Read for W {} +// #[cfg(feature = "tracing")] +// impl Write for R {} +// ``` +// We found that the usual setup for projects that depend on the generated PAC +// ends up looking like this: +// ```toml +// [dependencies] +// pac_for_chip = { version = "x.x.x" } +// [dev-dependencies] +// pac_for_chip = { version = "x.x.x", features = ["tracing"] } +// ``` +// +// Unfortunately, rust-analyzer was not smart enough to **not** suggest +// `read()/write()` for registers that are write-only/read-only when writing +// **non**-test code (i.e. code that would end up in an embedded build). +// `cargo` would not allow you to build in release mode (i.e. for embedded) +// and spit out errors that some registers cannot be read from/written to. +// +// This could cause confusion as to why rust-analyzer suggests these functions +// and cargo failing to build. + +/// Allow reading and writing registers that are read-only/write-only. +/// +/// Don't ever use this module unless you know what you are doing. This allows +/// reading/writing registers that are write-/read-only respectively. +/// +/// Use this module when writing tests where you want to read/write simulated +/// registers to check their contents or simulate an external input to a +/// read-only buffer register. +#[cfg(feature = "tracing")] +pub mod insanely_unsafe{ + use crate::common::{Access, R, W, Read, Write, Reg}; + use crate::common::sealed::{CastFrom,RegSpec}; + use crate::{RegValueT, RegisterValue}; + + pub trait WriteOnlyRead: Access{} + impl WriteOnlyRead for W {} + pub trait ReadOnlyWrite: Access{} + impl ReadOnlyWrite for R {} + + impl Reg { + /// Read a **write-only** register. + /// + /// # Safety + /// Reading from a write-only register can cause undefined behavior on target devices. + /// This function shall only ever be used on non-embedded devices when simulating registers. + #[inline(always)] + pub unsafe fn read_write_only(&self) -> RegValueT { + let val = { + let mut buf: u64 = 0x0; + super::READ_FN.with(|rf| { + buf = rf.get().unwrap()(self.addr(), std::mem::size_of::()); + }); + T::DataType::cast_from(buf) + }; + as RegisterValue<_>>::new(val) + } + } + + impl Reg { + /// Write register value back to **read-only** register. + /// + /// # Arguments + /// + /// * `reg_value` - A string slice that holds the name of the person + /// + /// # Safety + /// Write operation on a **read-only** register can cause undefined + /// behavior. This function shall only ever be used on non-embedded targets + /// (e.g. when simulating registers). + #[inline(always)] + pub unsafe fn write_read_only(&self, reg_value: RegValueT) { + super::WRITE_FN.with(|wf|{ + wf.get().unwrap()(self.addr(), std::mem::size_of::(), reg_value.data.into()) + }); + } + } + + impl Reg + where + RegValueT:Default + { + /// Init **read-only** register with value returned by the closure. + /// + /// # Arguments + /// + /// * `f` - Closure that receive as input a register value initialized with register value at Power On Reset. + /// + /// # Safety + /// This is extremely unsafe and shall only ever be used on non-embedded + /// devices in order init simulated registers. + /// + #[inline(always)] + /// Write value computed by closure that receive as input the reset value of register + pub unsafe fn init_read_only(&self, f: impl FnOnce(RegValueT) -> RegValueT) { + let val = RegValueT::::default(); + let res = f(val); + self.write_read_only(res); + } + } + + impl Reg { + #[inline(always)] + /// Don't ever use this on embedded targets. Only use for unit tests on + /// host machines. + /// Write register with value returned by the closure. + /// + /// # Arguments + /// + /// * `f` - Closure that receive as input a register value read from register. + /// + /// # Safety + /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual. + /// Register is Send and Sync to allow complete freedom. Developer is responsible for proper use with multithreaded tests. + /// + pub unsafe fn modify_write_only(&self, f: impl FnOnce(RegValueT) -> RegValueT) { + let val = self.read_write_only(); + let res = f(val); + self.write(res); + } + } + + impl Reg { + #[inline(always)] + /// Write a **read-only** register with value returned by the closure. + /// + /// # Arguments + /// + /// * `f` - Closure that receive as input a register value read from register. + /// + /// # Safety + /// Write operation on **read-only** registers can cause undefined + /// behavior on embedded devices. See module level safety warnings for explanation when to use this function. + /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual. + /// Register is Send and Sync to allow complete freedom. Developer is responsible for proper use with multithreaded tests. + /// + pub unsafe fn modify_read_only(&self, f: impl FnOnce(RegValueT) -> RegValueT) { + let val = self.read(); + let res = f(val); + self.write_read_only(res); + } + } +} diff --git a/test_svd/simple.xml b/test_svd/simple.xml new file mode 100644 index 0000000..ec486aa --- /dev/null +++ b/test_svd/simple.xml @@ -0,0 +1,821 @@ + + + + + Infineon + + IFX + + ARM_Example + + ARMCM3 + + 1.2 + + SVD Test for Rust PAC generator + + Test license\n + + + CM3 + r1p0 + little + true + true + 3 + false + + 8 + + 32 + + + + 32 + read-write + + 0x00000000 + + 0xFFFFFFFF + + + + + TIMER + 1.0 + Description of peripheral + TIMER + 0x40010000 + read-write + + 0 + 0x100 + registers + + + TIMER0 + Timer 0 interrupt + 0 + + + + BITFIELD_REG + Register to test basic bitfield features + 0x00 + read-write + 0x1337F7F + + + BoolR + Boolean Bitfield Read Only + [0:0] + read-only + + + BoolW + Boolean Bitfield Write Only + [1:1] + write-only + + + BoolRW + Boolean bitfield Read Write + [2:2] + read-write + + + BitfieldR + Raw Bitfield Read Only + [5:3] + read-only + + + BitfieldW + Bitfield Raw Write Only + [7:6] + write-only + + + BitfieldRW + BitField Raw Read Write + [11:8] + read-write + + + BitfieldEnumerated + Bitfield with enumerated field + [15:12] + read-write + + + CClk + Core Clock + 0 + + + GPIOA_0 + GPIO A, PIN 0 + 1 + + + GPIOA_1 + GPIO A, PIN 1 + 2 + + + GPIOA_2 + GPIO A, PIN 2 + 3 + + + GPIOA_3 + GPIO A, PIN 3 + 4 + + + GPIOA_4 + GPIO A, PIN 4 + 5 + + + GPIOA_5 + GPIO A, PIN 5 + 6 + + + GPIOA_6 + GPIO A, PIN 6 + 7 + + + GPIOA_7 + GPIO A, PIN 7 + 8 + + + GPIOB_0 + GPIO B, PIN 0 + 9 + + + GPIOB_1 + GPIO B, PIN 1 + 10 + + + GPIOB_2 + GPIO B, PIN 2 + 11 + + + GPIOB_3 + GPIO B, PIN 3 + 12 + + + GPIOC_0 + GPIO C, PIN 0 + 13 + + + GPIOC_5 + GPIO C, PIN 1 + 14 + + + GPIOC_6 + GPIO C, PIN 2 + 15 + + + + + 8 + 1 + Field%sArray + Array of bitfields + [17:16] + read-write + + + RISING + Only rising edges result in a counter increment or decrement + 0 + + + FALLING + Only falling edges result in a counter increment or decrement + 1 + + + BOTH + Rising and falling edges result in a counter increment or decrement + 2 + + + + + + + SR + Status Register + 0x04 + 16 + read-only + 0x00000000 + 0xD701 + + + + RUN + Shows if Timer is running or not + [0:0] + read-only + + + Stopped + Timer is not running + 0 + + + Running + Timer is running + 1 + + + + + + MATCH + Shows if the MATCH was hit + [8:8] + read-write + + + No_Match + The MATCH condition was not hit + 0 + + + Match_Hit + The MATCH condition was hit + 1 + + + + + + UN + Shows if an underflow occured. This flag is sticky + [9:9] + read-write + + + No_Underflow + No underflow occured since last clear + 0 + + + Underflow + A minimum of one underflow occured since last clear + 1 + + + + + + OV + Shows if an overflow occured. This flag is sticky + [10:10] + read-write + + + No_Overflow + No overflow occured since last clear + 0 + + + Overflow_occured + A minimum of one overflow occured since last clear + 1 + + + + + + RST + Shows if Timer is in RESET state + [12:12] + read-only + + + Ready + Timer is not in RESET state and can operate + 0 + + + In_Reset + Timer is in RESET state and can not operate + 1 + + + + + + RELOAD + Shows the currently active RELOAD Register + [15:14] + read-only + + + RELOAD0 + Reload Register number 0 is active + 0 + + + RELOAD1 + Reload Register number 1 is active + 1 + + + RELOAD2 + Reload Register number 2 is active + 2 + + + RELOAD3 + Reload Register number 3 is active + 3 + + + + + + + INT + Interrupt Register + 0x10 + 16 + write-only + 0x00000000 + 0x0771 + + + + EN + Interrupt Enable + [0:0] + read-write + + + Disabled + Timer does not generate Interrupts + 0 + + + Enable + Timer triggers the TIMERn Interrupt + 1 + + + + + + MODE + Interrupt Mode, selects on which condition the Timer should generate an Interrupt + [6:4] + read-write + + + Match + Timer generates an Interrupt when the MATCH condition is hit + 0 + + + Underflow + Timer generates an Interrupt when it underflows + 1 + + + Overflow + Timer generates an Interrupt when it overflows + 2 + + + + + + + NOBITFIELD_REG + The Counter Register reflects the actual Value of the Timer/Counter + 0x20 + read-write + 0x00000000 + 0xFFFFFFFF + + + MATCH + The Match Register stores the compare Value for the MATCH condition + 0x24 + read-writeOnce + + + PRESCALE_RD + The Prescale Register stores the Value for the prescaler. The cont event gets divided by this value + 0x28 + read-only + + + PRESCALE_WR + The Prescale Register stores the Value for the prescaler. The cont event gets divided by this value + 0x28 + write-only + 0x00000000 + 0xFFFFFFFF + + + 4 + 4 + ARRAYREG[%s] + Array of register + 0x50 + read-write + 0x00000000 + 0xFFFFFFFF + + + BITFIELD_REG + Another defintion register using alternate group + alt_group + 0x00 + + + Cluster1 + Test Cluster + 0x100 + + Cluster1 + A cluster inside another cluster + 0x100 + + NestedReg + 0x00 + read-write + 0x12345 + + + + CR + 0x00 + read-write + 0x0 + + + filed1 + 0 + 2 + read-write + + + PSC + 3 + 4 + read-write + + + val1 + 1 + + + + + + + + 4 + 0x100 + ClusterDim[%s] + Test Cluster array + 0x200 + + CR + 0x00 + read-write + 0x1000 + + + filed1 + 0 + 2 + read-write + + + PSC + 3 + 4 + read-write + + + val1 + 1 + + + + + + + + + + + + 3 + 0x1000 + UART[%s] + 1.0 + Test cluster + 0x50000000 + read-write + + UartInt + Uart interrupt + 2 + + + + 2 + 0x100 + Reg1_[%s] + read-write reg + 0x0 + read-write + 0x000 + 0xFFFFFFFF + + + RegBitfieldRaw + Register with bitfields without enumeration + 0x100 + read-write + 0x000 + 0xFFFFFFFF + + + Bitfield9bits + 0 + 8 + read-write + + + Bitfield17bits + 9 + 26 + read-write + + + Bool + 27 + 27 + read-write + + + + + Reg16bitEnum + read write reg enum + 0x104 + 16 + read-write + 0x000 + 0xFFFF + + + Bitfield9bitsEnum + Check when bitfield size is not standard + 0 + 8 + read-write + + + Val0 + 0 + + + Val256 + 256 + + + + + Boolenum + Boolean with enum + 9 + 16 + read-write + + + bool0 + 0 + + + bool1 + 1 + + + + + + + Reg8bitRaw + Read write whithout enum + 0x106 + 8 + read-write + 0x00 + 0xFF + + + Reg16bitRaw + Read write without enum + 0x107 + 16 + read-write + 0x0000 + 0xFFFF + + + Reg32bitRaw + Read write without enum + 0x109 + read-write + 0x0000000 + 0xFFFFFFFF + + + + + + + + FOO + 1.0 + Fake peripheral containing registers with names starting with non XID_Start characters that cannot be directly used as Rust identifier names. + FOO + 0x60000000 + read-write + + 0 + 0x100 + registers + + + INT_FOO + Foo interrupt + 3 + + + + IN + FOO Input Register + 0x0 + 8 + read-write + 0x0 + 0xFF + + + SELF + SELF element of FOO + 1 + 1 + read-write + + + 0_VALUE + Input is on low level. + 0 + + + 1_VALUE + Input is on high level. + 1 + + + + + + + + + EscapeTest + 1.0 + Fake peripheral containing register with characters that may need to be escaped (and some UTF-8) when documentation is inserted. + 0x60000000 + read-write + + 0 + 0x100 + registers + + + interrupt + []\"😀"\n\a + multi-line + \r'𒀀𒀽 + 42 + + + + register + []\"😀"\n\a\r'𒀀𒀽 + 0x0 + 8 + read-write + 0x0 + 0xFF + + + field + []\"😀"\n\a\r'𒀀𒀽 + 1 + 1 + read-write + + + enum_value + []\"😀"\n\a\r'𒀀𒀽 + 0 + + + + + + + + + DerivedTest + 1.0 + Fake Peripheral to test cluster and register with derivedFrom attribute + 0xA0000 + read-write + + 0 + 0x100 + registers + + + + BaseCluster + Cluster that defines the base type + BaseClusterType + 0x0 + + Reg1 + 0x00 + + + Reg2 + 0x4 + + + + 4 + 16 + ArrayCluster[%s] + ArrayCluster + 0x8 + + + + + \ No newline at end of file diff --git a/test_svd/simple_csfr.svd b/test_svd/simple_csfr.svd new file mode 100644 index 0000000..d7d1bf8 --- /dev/null +++ b/test_svd/simple_csfr.svd @@ -0,0 +1,11708 @@ + + + + + Infineon + + IFX + + ARM_Example + + ARMCM3 + + 1.2 + + SVD Test for Rust PAC generator + + Test license\n + + + CM3 + r1p0 + little + true + true + 3 + false + + 8 + + 32 + + + + 32 + read-write + + 0x00000000 + + 0xFFFFFFFF + + + + + TIMER + 1.0 + Description of peripheral + TIMER + 0x40010000 + read-write + + 0 + 0x100 + registers + + + TIMER0 + Timer 0 interrupt + 0 + + + + BITFIELD_REG + Register to test basic bitfield features + 0x00 + read-write + 0x1337F7F + + + BoolR + Boolean Bitfield Read Only + [0:0] + read-only + + + BoolW + Boolean Bitfield Write Only + [1:1] + write-only + + + BoolRW + Boolean bitfield Read Write + [2:2] + read-write + + + BitfieldR + Raw Bitfield Read Only + [5:3] + read-only + + + BitfieldW + Bitfield Raw Write Only + [7:6] + write-only + + + BitfieldRW + BitField Raw Read Write + [11:8] + read-write + + + BitfieldEnumerated + Bitfield with enumerated field + [15:12] + read-write + + + CClk + Core Clock + 0 + + + GPIOA_0 + GPIO A, PIN 0 + 1 + + + GPIOA_1 + GPIO A, PIN 1 + 2 + + + GPIOA_2 + GPIO A, PIN 2 + 3 + + + GPIOA_3 + GPIO A, PIN 3 + 4 + + + GPIOA_4 + GPIO A, PIN 4 + 5 + + + GPIOA_5 + GPIO A, PIN 5 + 6 + + + GPIOA_6 + GPIO A, PIN 6 + 7 + + + GPIOA_7 + GPIO A, PIN 7 + 8 + + + GPIOB_0 + GPIO B, PIN 0 + 9 + + + GPIOB_1 + GPIO B, PIN 1 + 10 + + + GPIOB_2 + GPIO B, PIN 2 + 11 + + + GPIOB_3 + GPIO B, PIN 3 + 12 + + + GPIOC_0 + GPIO C, PIN 0 + 13 + + + GPIOC_5 + GPIO C, PIN 1 + 14 + + + GPIOC_6 + GPIO C, PIN 2 + 15 + + + + + 8 + 1 + Field%sArray + Array of bitfields + [17:16] + read-write + + + RISING + Only rising edges result in a counter increment or decrement + 0 + + + FALLING + Only falling edges result in a counter increment or decrement + 1 + + + BOTH + Rising and falling edges result in a counter increment or decrement + 2 + + + + + + + SR + Status Register + 0x04 + 16 + read-only + 0x00000000 + 0xD701 + + + + RUN + Shows if Timer is running or not + [0:0] + read-only + + + Stopped + Timer is not running + 0 + + + Running + Timer is running + 1 + + + + + + MATCH + Shows if the MATCH was hit + [8:8] + read-write + + + No_Match + The MATCH condition was not hit + 0 + + + Match_Hit + The MATCH condition was hit + 1 + + + + + + UN + Shows if an underflow occured. This flag is sticky + [9:9] + read-write + + + No_Underflow + No underflow occured since last clear + 0 + + + Underflow + A minimum of one underflow occured since last clear + 1 + + + + + + OV + Shows if an overflow occured. This flag is sticky + [10:10] + read-write + + + No_Overflow + No overflow occured since last clear + 0 + + + Overflow_occured + A minimum of one overflow occured since last clear + 1 + + + + + + RST + Shows if Timer is in RESET state + [12:12] + read-only + + + Ready + Timer is not in RESET state and can operate + 0 + + + In_Reset + Timer is in RESET state and can not operate + 1 + + + + + + RELOAD + Shows the currently active RELOAD Register + [15:14] + read-only + + + RELOAD0 + Reload Register number 0 is active + 0 + + + RELOAD1 + Reload Register number 1 is active + 1 + + + RELOAD2 + Reload Register number 2 is active + 2 + + + RELOAD3 + Reload Register number 3 is active + 3 + + + + + + + INT + Interrupt Register + 0x10 + 16 + write-only + 0x00000000 + 0x0771 + + + + EN + Interrupt Enable + [0:0] + read-write + + + Disabled + Timer does not generate Interrupts + 0 + + + Enable + Timer triggers the TIMERn Interrupt + 1 + + + + + + MODE + Interrupt Mode, selects on which condition the Timer should generate an Interrupt + [6:4] + read-write + + + Match + Timer generates an Interrupt when the MATCH condition is hit + 0 + + + Underflow + Timer generates an Interrupt when it underflows + 1 + + + Overflow + Timer generates an Interrupt when it overflows + 2 + + + + + + + NOBITFIELD_REG + The Counter Register reflects the actual Value of the Timer/Counter + 0x20 + read-write + 0x00000000 + 0xFFFFFFFF + + + MATCH + The Match Register stores the compare Value for the MATCH condition + 0x24 + read-writeOnce + + + PRESCALE_RD + The Prescale Register stores the Value for the prescaler. The cont event gets divided by this value + 0x28 + read-only + + + PRESCALE_WR + The Prescale Register stores the Value for the prescaler. The cont event gets divided by this value + 0x28 + write-only + 0x00000000 + 0xFFFFFFFF + + + 4 + 4 + ARRAYREG[%s] + Array of register + 0x50 + read-write + 0x00000000 + 0xFFFFFFFF + + + BITFIELD_REG + Another defintion register using alternate group + alt_group + 0x00 + + + Cluster1 + Test Cluster + 0x100 + + Cluster1 + A cluster inside another cluster + 0x100 + + NestedReg + 0x00 + read-write + 0x12345 + + + + CR + 0x00 + read-write + 0x0 + + + filed1 + 0 + 2 + read-write + + + PSC + 3 + 4 + read-write + + + val1 + 1 + + + + + + + + 4 + 0x100 + ClusterDim[%s] + Test Cluster array + 0x200 + + CR + 0x00 + read-write + 0x1000 + + + filed1 + 0 + 2 + read-write + + + PSC + 3 + 4 + read-write + + + val1 + 1 + + + + + + + + + + + + 3 + 0x1000 + UART[%s] + 1.0 + Test cluster + 0x50000000 + read-write + + UartInt + Uart interrupt + 2 + + + + 2 + 0x100 + Reg1_[%s] + read-write reg + 0x0 + read-write + 0x000 + 0xFFFFFFFF + + + RegBitfieldRaw + Register with bitfields without enumeration + 0x100 + read-write + 0x000 + 0xFFFFFFFF + + + Bitfield9bits + 0 + 8 + read-write + + + Bitfield17bits + 9 + 26 + read-write + + + Bool + 27 + 27 + read-write + + + + + Reg16bitEnum + read write reg enum + 0x104 + 16 + read-write + 0x000 + 0xFFFF + + + Bitfield9bitsEnum + Check when bitfield size is not standard + 0 + 8 + read-write + + + Val0 + 0 + + + Val256 + 256 + + + + + Boolenum + Boolean with enum + 9 + 16 + read-write + + + bool0 + 0 + + + bool1 + 1 + + + + + + + Reg8bitRaw + Read write whithout enum + 0x106 + 8 + read-write + 0x00 + 0xFF + + + Reg16bitRaw + Read write without enum + 0x107 + 16 + read-write + 0x0000 + 0xFFFF + + + Reg32bitRaw + Read write without enum + 0x109 + read-write + 0x0000000 + 0xFFFFFFFF + + + + + + + + FOO + 1.0 + Fake peripheral containing registers with names starting with non XID_Start characters that cannot be directly used as Rust identifier names. + FOO + 0x60000000 + read-write + + 0 + 0x100 + registers + + + INT_FOO + Foo interrupt + 3 + + + + IN + FOO Input Register + 0x0 + 8 + read-write + 0x0 + 0xFF + + + SELF + SELF element of FOO + 1 + 1 + read-write + + + 0_VALUE + Input is on low level. + 0 + + + 1_VALUE + Input is on high level. + 1 + + + + + + + + + + + + CPU0 + 100 + CPU + 0 + + 0 + 65472 + registers + + + + 18 + 8 + DPR[%s] + DPR + 49152 + + DPRy_L + CPUx Data Protection Range 0 Lower Bound Register + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + LOWBND + DPRy Lower Boundary Address LOWBND + 3 + 31 + read-write + + + + + DPRy_U + CPUx Data Protection Range 0 Upper Bound Register + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + UPPBND + DPRy Upper Boundary Address UPPBND + 3 + 31 + read-write + + + + + + 10 + 8 + CPR[%s] + CPR + 53248 + + CPRy_L + CPUx Code Protection Range 0 Lower Bound Register + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + LOWBND + CPRy Lower Boundary Address LOWBND + 5 + 31 + read-write + + + + + CPRy_U + CPUx Code Protection Range 0 Upper Bound Register + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + UPPBND + CPR0 m Upper Boundary Address UPPBND + 5 + 31 + read-write + + + + + + TPS + TPS + 58368 + + CON + CPUx Temporal Protection System Control Register + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + TEXP0 + Timer0 Expired Flag TEXP0. Set when the corresponding timer expires. Cleared on any write to the TIMER0 register. + 0 + 0 + read-only + + + TEXP1 + Timer1 Expired Flag TEXP1. Set when the corresponding timer expires. Cleared on any write to the TIMER1 register. + 1 + 1 + read-only + + + TEXP2 + Timer1 Expired Flag TEXP2. Set when the corresponding timer expires. Cleared on any write to the TIMER1 register. + 2 + 2 + read-only + + + TTRAP + Temporal Protection Trap TTRAP. If set indicates that a TAE trap has been requested. Any subsequent TAE traps are disabled. A write clears the flag and re enables TAE traps. + 16 + 16 + read-only + + + + + 3 + 4 + TIMER[%s] + CPUx Temporal Protection System Timer Register 0 + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + Timer + Temporal Protection Timer Timer. Writing zero de activates the Timer. Writing a non zero value starts the Timer. Any write clears the corresponding TPS CON.TEXP flag. Read returns the current Timer value. + 0 + 31 + read-write + + + + + + TPS_EXTIM + TPS EXTIM + 58432 + + ENTRY_LVAL + CPUx Exception Entry Timer Load Value + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + ENTRY_LVAL + Exception Entry Timer Load value ENTRY LVAL. Value loaded into the exception entry timer on detection of an enabled exception. Bits 3 0 are constrained to be 0 + 4 + 11 + read-write + + + + + ENTRY_CVAL + CPUx Exception Entry Timer Current Value + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + ENTRY_CVAL + Exception Entry Timer Current Value ENTRY CVAL. Current value of the exception entry timer. + 0 + 11 + read-only + + + + + EXIT_LVAL + CPUx Exception Exit Timer Load Value + resetvalue={Application Reset:0x0} + 8 + 32 + 0 + 4294967295 + + + EXIT_LVAL + Exception Exit Timer Load value EXIT LVAL. Value loaded into the exception exit timer on detection of an enabled exception. Bits 3 0 are constrained to be 0 + 4 + 23 + read-write + + + + + EXIT_CVAL + CPUx Exception Exit Timer Current Value + resetvalue={Application Reset:0x0} + 12 + 32 + 0 + 4294967295 + + + EXIT_CVAL + Exception Exit Timer Current Value EXIT CVAL. Current value of the exception exit timer. + 0 + 23 + read-only + + + + + CLASS_EN + CPUx Exception Timer Class Enable Register + resetvalue={Application Reset:0x0} + 16 + 32 + 0 + 4294967295 + + + EXTIM_CLASS_EN + Exception Timer Class Enables EXTIM CLASS EN. Trap Class enables for exception timer. + 0 + 7 + read-write + + + + + STAT + CPUx Exception Timer Status Register + resetvalue={Application Reset:0x0} + 20 + 32 + 0 + 4294967295 + + + EXIT_TIN + Exception Exit Timer TIN EXIT TIN. Exception Exit Timer TIN of triggering trap. + 0 + 7 + read-write + + + EXIT_CLASS + Exception Exit Timer Class EXIT CLASS. Exception exit Timer Class of triggering trap. + 8 + 10 + read-write + + + EXIT_AT + Exception Exit Timer Alarm Triggered EXIT AT. Exception Exit Timer Alarm triggered sticky bit. Alarm triggered since last cleared. + 15 + 15 + read-only + + + ENTRY_TIN + Exception Entry Timer TIN ENTRY TIN. Exception Entry Timer TIN of triggering trap. + 16 + 23 + read-write + + + ENTRY_CLASS + Exception Entry Timer Class ENTRY CLASS. Exception Entry Timer Class of triggering trap. + 24 + 26 + read-write + + + ENTRY_AT + Exception Entry Timer Alarm Triggered ENTRY AT. Exception Entry Timer Alarm triggered sticky bit. Alarm triggered since last cleared. + 31 + 31 + read-only + + + + + FCX + CPUx Exception Timer FCX Register + resetvalue={Application Reset:0x0} + 24 + 32 + 0 + 4294967295 + + + EXIT_FCX + Exception Exit Timer FCX EXIT FCX. Exception Exit Timer FCX of triggering trap. + 0 + 19 + read-only + + + + + + FPU_TRAP + FPU TRAP + 40960 + + CON + CPUx Trap Control Register + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + TST + Trap Status TST + 0 + 0 + read-only + + + Const_00 + 0 No instruction captured. The next enabled exception will cause the exceptional instruction to be captured. + 0 + + + Const_11 + 1 Instruction captured. No further enabled exceptions will be captured until TST is cleared. + 1 + + + + + TCL + Trap Clear TCL. Read always reads as 0. + 1 + 1 + write-only + + + Const_00 + 0 No effect. + 0 + + + Const_11 + 1 Clears the trapped instruction TST will be negated . + 1 + + + + + RM + Captured Rounding Mode RM. The rounding mode of the captured instruction. Only valid when TST is asserted. Note that this is the rounding mode supplied to the FPU for the exceptional instruction. UPDFL instructions may cause a trap and change the rounding mode. In this case the RM bits capture the input rounding mode + 8 + 9 + read-only + + + FXE + FX Trap Enable FXE. When set an instruction generating an FX exception will trigger a trap. + 18 + 18 + read-write + + + FUE + FU Trap Enable FUE. When set an instruction generating an FU exception will trigger a trap. + 19 + 19 + read-write + + + FZE + FZ Trap Enable FZE. When set an instruction generating an FZ exception will trigger a trap. + 20 + 20 + read-write + + + FVE + FV Trap Enable FVE. When set an instruction generating an FV exception will trigger a trap. + 21 + 21 + read-write + + + FIE + FI Trap Enable FIE. When set an instruction generating an FI exception will trigger a trap. + 22 + 22 + read-write + + + FX + Captured FX FX. Asserted if the captured instruction asserted FX. Only valid when TST is asserted. + 26 + 26 + read-only + + + FU + Captured FU FU. Asserted if the captured instruction asserted FU. Only valid when TST is asserted. + 27 + 27 + read-only + + + FZ + Captured FZ FZ. Asserted if the captured instruction asserted FZ. Only valid when TST is asserted + 28 + 28 + read-only + + + FV + Captured FV FV. Asserted if the captured instruction asserted FV. Only valid when TST is asserted + 29 + 29 + read-only + + + FI + Captured FI FI. Asserted if the captured instruction asserted FI. Only valid when TST is asserted + 30 + 30 + read-only + + + + + PC + CPUx Trapping Instruction Program Counter Register + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + PC + Captured Program Counter PC. The program counter virtual address of the captured instruction. Only valid when FPU TRAP CON.TST is asserted. + 0 + 31 + read-only + + + + + OPC + CPUx Trapping Instruction Opcode Register + resetvalue={Application Reset:0x0} + 8 + 32 + 0 + 4294967295 + + + OPC + Captured Opcode OPC. The secondary opcode of the captured instruction. When FPU TRAP OPC.FMT 0 only bits 3 0 are defined. OPC is valid only when FPU TRAP CON.TST is asserted. + 0 + 7 + read-only + + + FMT + Captured Instruction Format FMT. The format of the captured instruction s opcode. Only valid when FPU TRAP CON.TST is asserted. + 8 + 8 + read-only + + + Const_00 + 0 RRR + 0 + + + Const_11 + 1 RR + 1 + + + + + DREG + Captured Destination Register DREG. The destination register of the captured instruction. ... Only valid when FPU TRAP CON.TST is asserted. + 16 + 19 + read-only + + + Const_00 + 0 Data general purpose register 0. + 0 + + + Const_1515 + F Data general purpose register 15. + 15 + + + + + + + SRC1 + CPUx Trapping Instruction Operand Register + resetvalue={Application Reset:0x0} + 16 + 32 + 0 + 4294967295 + + + SRC1 + Captured SRC1 Operand SRC1. The SRC1 operand of the captured instruction. Only valid when FPU TRAP CON.TST is asserted. + 0 + 31 + read-only + + + + + SRC2 + CPUx Trapping Instruction Operand Register + resetvalue={Application Reset:0x0} + 20 + 32 + 0 + 4294967295 + + + SRC2 + Captured SRC2 Operand SRC2. The SRC2 operand of the captured instruction. Only valid when FPU TRAP CON.TST is asserted. + 0 + 31 + read-only + + + + + SRC3 + CPUx Trapping Instruction Operand Register + resetvalue={Application Reset:0x0} + 24 + 32 + 0 + 4294967295 + + + SRC3 + Captured SRC3 Operand SRC3. The SRC3 operand of the captured instruction. Only valid when FPU TRAP CON.TST is asserted. + 0 + 31 + read-only + + + + + + 8 + 8 + TR[%s] + Trigger + 61440 + + TRiEVT + CPUx Trigger Event 0 + resetvalue={Debug Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + EVTA + Event Associated EVTA. Specifies the Debug Action associated with the Debug Event + 0 + 2 + read-write + + + Const_00 + 000 BOD 0 Disabled. BOD 1 Disabled. + 0 + + + Const_11 + 001 BOD 0 Pulse BRKOUT Signal. BOD 1 None. + 1 + + + Const_22 + 010 BOD 0 Halt and pulse BRKOUT Signal. BOD 1 Halt. + 2 + + + Const_33 + 011 BOD 0 Breakpoint trap and pulse BRKOUT Signal. BOD 1 Breakpoint trap. + 3 + + + Const_44 + 100 BOD 0 Breakpoint interrupt 0 and pulse BRKOUT Signal. BOD 1 Breakpoint interrupt 0. + 4 + + + Const_55 + 101 BOD 0 If implemented breakpoint interrupt 1 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 1. If not implemented None. + 5 + + + Const_66 + 110 BOD 0 If implemented breakpoint interrupt 2 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 2. If not implemented None. + 6 + + + Const_77 + 111 BOD 0 If implemented breakpoint interrupt 3 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 3. If not implemented None. + 7 + + + + + BBM + Break Before Make BBM or Break After Make BAM Selection BBM. Code triggers BBM or BAM selection. Data access and data code combination access triggers can only create BAM Debug Events. When these triggers occur TRnEVT.BBM is ignored. + 3 + 3 + read-write + + + Const_00 + 0 Code only triggers Break After Make BAM . + 0 + + + Const_11 + 1 Code only triggers Break Before Make BBM . + 1 + + + + + BOD + Breakout Disable BOD + 4 + 4 + read-write + + + Const_00 + 0 BRKOUT signal asserted according to the action specified in the EVTA field. + 0 + + + Const_11 + 1 BRKOUT signal not asserted. This takes priority over any assertion generated by the EVTA field. + 1 + + + + + SUSP + CDC Suspend Out Signal State SUSP. Value to be assigned to the CDC suspend out signal when the Debug Event is raised. + 5 + 5 + read-write + + + CNT + Counter CNT. When this event occurs adjust the control of the performance counters in task mode as follows + 6 + 7 + read-write + + + Const_00 + 00 No change. + 0 + + + Const_11 + 01 Start the performance counters. + 1 + + + Const_22 + 10 Stop the performance counters. + 2 + + + Const_33 + 11 Toggle the performance counter control i.e. start it if it is currently stopped stop it if it is currently running . + 3 + + + + + TYP + Input Selection TYP + 12 + 12 + read-write + + + Const_00 + 0 Address + 0 + + + Const_11 + 1 PC + 1 + + + + + RNG + Compare Type RNG. Once an even numbered comparator has been set to range the EVTR settings of its associated upper neighbour will be ignored. + 13 + 13 + read-write + + + Const_11 + 1 Range + 1 + + + Const_00 + 0 Equality + 0 + + + + + ASI_EN + Enable ASI Comparison ASI EN + 15 + 15 + read-write + + + Const_00 + 0 No ASI comparison performed. Debug Trigger is valid for all processes. + 0 + + + Const_11 + 1 Enable ASI comparison. Debug Events are only triggered when the current process ASI matches TRnEVT.ASI. + 1 + + + + + ASI + Address Space Identifier ASI. The ASI of the Debug Trigger process. + 16 + 20 + read-write + + + AST + Address Store AST. Used in conjunction with TYP 0 + 27 + 27 + read-write + + + ALD + Address Load ALD. Used in conjunction with TYP 0 + 28 + 28 + read-write + + + + + TRiADR + CPUx Trigger Address 0 + resetvalue={Debug Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + ADDR + Comparison Address ADDR. For PC comparison bit 0 is always zero. + 0 + 31 + read-write + + + + + + SMACON + CPUx SIST Mode Access Control Register + resetvalue={Application Reset:0x0} + 36876 + 32 + 0 + 4294967295 + + + IODT + In Order Data Transactions IODT + 24 + 24 + read-write + + + Const_00 + 0 Normal operation Non dependent loads bypass stores. + 0 + + + Const_11 + 1 In order operation Loads always flush preceding stores processor store buffer disabled. + 1 + + + + + + + DIEAR + CPUx Data Integrity Error Address Register + resetvalue={Application Reset:0x0} + 36896 + 32 + 0 + 4294967295 + + + TA + Transaction Address TA. Physical address being accessed by operation that encountered data integrity error. + 0 + 31 + read-only + + + + + DIETR + CPUx Data Integrity Error Trap Register + resetvalue={Application Reset:0x0} + 36900 + 32 + 0 + 4294967295 + + + IED + Integrity Error Detected IED + 0 + 0 + read-write + + + Const_00 + 0 Write Clear IED bit re enable DIETR and DIEAR update. Read No data integrity error condition occurred + 0 + + + Const_11 + 1 Write No Effect. Read Data integrity error condition detected. DIETR and DIEAR contents valid further DIETR and DIEAR updates disabled.. + 1 + + + + + IE_T + Integrity Error Tag Memory IE T + 1 + 1 + read-only + + + IE_C + Integrity Error Cache Memory IE C + 2 + 2 + read-only + + + IE_S + Integrity Error Scratchpad Memory IE S + 3 + 3 + read-only + + + IE_BI + Integrity Error Bus Interface IE BI + 4 + 4 + read-only + + + E_INFO + Error Information E INFO. If IE BS 1 Bus Master Tag ID of requesting masterIf IE C 1 Cache way. + 5 + 10 + read-only + + + IE_UNC + Dual Bit Error Detected IE UNC + 11 + 11 + read-only + + + IE_SP + Safety Protection Error Detected IE SP + 12 + 12 + read-only + + + IE_BS + Bus Slave Access Indicator IE BS + 13 + 13 + read-only + + + IE_DLMU + Integrity Error DLMU IE DLMU + 14 + 14 + read-only + + + IE_LPB + Integrity Error Local Pflash Bank IE LPB + 15 + 15 + read-only + + + IE_MTMV + Memory Test Mode Violation detected IE MTMV + 16 + 16 + read-only + + + + + PIEAR + CPUx Program Integrity Error Address Register + resetvalue={Application Reset:0x0} + 37392 + 32 + 0 + 4294967295 + + + TA + Transaction Address TA. Physical address being accessed by operation that encountered program integrity error. + 0 + 31 + read-only + + + + + PIETR + CPUx Program Integrity Error Trap Register + resetvalue={Application Reset:0x0} + 37396 + 32 + 0 + 4294967295 + + + IED + Integrity Error Detected IED + 0 + 0 + read-write + + + Const_00 + 0 Write Clear IED bit re enable PIETR and PIEAR update. Read No data integrity error condition occurred + 0 + + + Const_11 + 1 Write No Effect. Read Data integrity error condition detected. PIETR and PIEAR contents valid further PIETR and PIEAR updates disabled.. + 1 + + + + + IE_T + Integrity Error TAG Memory IE T + 1 + 1 + read-only + + + IE_C + Integrity Error Cache Memory IE C + 2 + 2 + read-only + + + IE_S + Integrity Error Scratchpad Memory IE S + 3 + 3 + read-only + + + IE_BI + Integrity Error Bus Interface IE BI + 4 + 4 + read-only + + + E_INFO + Error Information E INFO. If IE BS 1 Bus Master Tag ID of requesting masterIf IE C 1 Cache way. + 5 + 10 + read-only + + + IE_UNC + Integrity Error Uncorrectable Error Detected IE UNC + 11 + 11 + read-only + + + IE_SP + Safety Protection Error Detected IE SP + 12 + 12 + read-only + + + IE_BS + Bus Slave Access Indicator IE BS + 13 + 13 + read-only + + + IE_ADDR + Address Phase error detected at SRI slave interface IE ADDR + 14 + 14 + read-only + + + IE_LPB + Integrity Error Local Pflash bank IE LPB + 15 + 15 + read-only + + + IE_MTMV + Memory Test Mode Violation detected IE MTMV + 16 + 16 + read-only + + + + + TASK_ASI + CPUx Task Address Space Identifier Register + resetvalue={Application Reset:0x1F} + 32772 + 32 + 31 + 4294967295 + + + ASI + Address Space Identifier ASI. The ASI register contains the Address Space Identifier of the current process. + 0 + 4 + read-write + + + + + PMA0 + CPUx Data Access CacheabilityRegister + resetvalue={Application Reset:0x300} + 33024 + 32 + 768 + 4294967295 + + + DAC + Data Access Cacheability Segments FHto 0H DAC. Note segments F H E H D H and A H are constrained to be non cacheable + 0 + 15 + read-write + + + + + PMA1 + CPUx Code Access CacheabilityRegister + resetvalue={Application Reset:0x300} + 33028 + 32 + 768 + 4294967295 + + + CAC + Code Access Cacheability Segments FH 0H CAC. Note Segments F H E H C H A H are constrained to be non cacheable + 0 + 15 + read-write + + + + + PMA2 + CPUx Peripheral Space Identifier register + resetvalue={Application Reset:0x0C000} + 33032 + 32 + 49152 + 4294967295 + + + PSI + Peripheral Space Identifier Segments FH 0H PSI + 0 + 15 + read-only + + + + + COMPAT + CPUx Compatibility Control Register + resetvalue={Application Reset:0x0FFFFFFFF} + 37888 + 32 + 4294967295 + 4294967295 + + + RM + Rounding Mode Compatibility RM + 3 + 3 + read-write + + + Const_00 + 0 PSW.RM not restored by RET. + 0 + + + Const_11 + 1 PSW.RM restored by RET TC1.3 behavior . + 1 + + + + + SP + SYSCON Safety Protection Mode Compatibility SP + 4 + 4 + read-write + + + Const_00 + 0 SYSCON 31 1 safety endinit protected. + 0 + + + Const_11 + 1 SYSCON 31 1 not safety endinit protected TC1.3 behavior . + 1 + + + + + + + PCXI + CPUx Previous Context Information Register + resetvalue={Application Reset:0x0} + 65024 + 32 + 0 + 4294967295 + + + PCXO + Previous Context Pointer Offset Field PCXO. The PCXO and PCXS fields form the pointer PCX which points to the CSA of the previous context. + 0 + 15 + read-write + + + PCXS + Previous Context Pointer Segment Address PCXS. Contains the segment address portion of the PCX. This field is used in conjunction with the PCXO field. + 16 + 19 + read-write + + + UL + Upper or Lower Context Tag UL. Identifies the type of context saved. If the type does not match the type expected when a context restore operation is performed a trap is generated. + 20 + 20 + read-write + + + Const_00 + 0 Lower Context + 0 + + + Const_11 + 1 Upper Context + 1 + + + + + PIE + Previous Interrupt Enable PIE. Indicates the state of the interrupt enable bit ICR.IE for the interrupted task. + 21 + 21 + read-write + + + PCPN + Previous CPU Priority Number PCPN. Contains the priority level number of the interrupted task. + 22 + 29 + read-write + + + + + PSW + CPUx Program Status Word + resetvalue={Application Reset:0x0B80} + 65028 + 32 + 2944 + 4294967295 + + + CDC + Call Depth Counter CDC. Consists of two variable width subfields. The first subfield consists of a string of zero or more initial 1 bits terminated by the first 0 bit. The remaining bits form the second subfield CDC.COUNT which constitutes the Call Depth Count value. The count value is incremented on each Call and is decremented on a Return. 0cccccc B 6 bit counter trap on overflow. 10ccccc B 5 bit counter trap on overflow. 110cccc B 4 bit counter trap on overflow. 1110ccc B 3 bit counter trap on overflow. 11110cc B 2 bit counter trap on overflow. 111110c B 1 bit counter trap on overflow. 1111110 B Trap every call Call Trace mode . 1111111 B Disable Call Depth Counting. When the call depth count CDC.COUNT overflows a trap CDO is generated. Setting the CDC to 1111110 B allows no bits for the counter and causes every call to be trapped. This is used for Call Depth Tracing. Setting the CDC to 1111111 B disables Call Depth Counting. + 0 + 6 + read-write + + + CDE + Call Depth Count Enable CDE. Enables call depth counting provided that the PSW.CDC mask field is not all set to 1. If PSW.CDC 1111111 B call depth counting is disabled regardless of the setting on the PSW.CDE bit. + 7 + 7 + read-write + + + Const_00 + 0 Call depth counting is temporarily disabled. It is automatically re enabled after execution of the next Call instruction. + 0 + + + Const_11 + 1 Call depth counting is enabled. + 1 + + + + + IS + Interrupt Stack Control IS. Determines if the current execution thread is using the shared global interrupt stack or a user stack. + 9 + 9 + read-write + + + Const_00 + 0 User Stack. If an interrupt is taken when the IS bit is 0 then the stack pointer register is loaded from the ISP register before execution starts at the first instruction of the Interrupt Service Routine ISR . + 0 + + + Const_11 + 1 Shared Global Stack. If an interrupt is taken when the PSW.IS bit is 1 then the current value of the stack pointer is used by the Interrupt Service Routine ISR . + 1 + + + + + IO + Access Privilege Level Control I O Privilege IO. Determines the access level to special function registers and peripheral devices. + 10 + 11 + read-write + + + Const_00 + 00 User 0 Mode No peripheral access. Access to memory regions with the peripheral space attribute are prohibited and results in a PSE or MPP trap. This access level is given to tasks that need not directly access peripheral devices. Tasks at this level do not have permission to enable or disable interrupts. + 0 + + + Const_11 + 01 User 1 Mode Regular peripheral access. Enables access to common peripheral devices that are not specially protected including read write access to serial I O ports read access to timers and access to most I O status registers. Tasks at this level may disable interrupts. + 1 + + + Const_22 + 10 Supervisor Mode Enables access to all peripheral devices. It enables read write access to core registers and protected peripheral devices. Tasks at this level may disable interrupts. + 2 + + + + + S + Safe Task Identifier S + 14 + 14 + read-write + + + USB + User Status Bits USB. The eight most significant bits of the PSW are designated as User Status Bits. These bits may be set or cleared as side effects of instruction execution. Refer to the TriCore Architecture manual for details. + 24 + 31 + read-write + + + + + PC + CPUx Program Counter + resetvalue={Application Reset:0x0} + 65032 + 32 + 0 + 0 + + + PC + Program Counter PC + 1 + 31 + read-write + + + + + SYSCON + CPUx System Configuration Register + resetvalue={Application Reset:0x0,Application Reset:0x0} + 65044 + 32 + 0 + 0 + + + FCDSF + Free Context List Depleted Sticky Flag FCDSF. This sticky bit indicates that a FCD Free Context List Depleted trap occurred since the bit was last cleared by software. + 0 + 0 + read-write + + + Const_00 + 0 No FCD trap occurred since the last clear. + 0 + + + Const_11 + 1 An FCD trap occurred since the last clear. + 1 + + + + + PROTEN + Memory Protection Enable PROTEN. Enables the memory protection system. Memory protection is controlled through the memory protection register sets. Note Initialize the protection register sets prior to setting PROTEN to one. + 1 + 1 + read-write + + + Const_00 + 0 Memory Protection is disabled. + 0 + + + Const_11 + 1 Memory Protection is enabled. + 1 + + + + + TPROTEN + Temporal Protection Enable TPROTEN. Enable the Temporal Protection system. + 2 + 2 + read-write + + + Const_00 + 0 Temporal Protection is disabled. + 0 + + + Const_11 + 1 Temporal Protection is enabled. + 1 + + + + + IS + Initial State Interrupt IS. of PSW.S bit in interrupt handle + 3 + 3 + read-write + + + TS + Initial State Trap TS. of PSW.S bit in trap handle + 4 + 4 + read-write + + + ESDIS + Emulator Space Disable. Disable the Emulator Space system + 8 + 8 + read-write + + + U1_IED + User 1 Instruction execution disable U1 IED. Disable the execution of User 1 mode instructions in User 1 IO mode. Disables User 1 ability to enable and disable interrupts. + 16 + 16 + read-write + + + U1_IOS + User 1 Peripheral access as supervisor U1 IOS. Allow User 1 mode tasks to access peripherals as if in Supervisor mode. Enables User 1 access to all peripheral registers. + 17 + 17 + read-write + + + BHALT + Boot Halt BHALT + 24 + 24 + read-write + + + Const_00 + 0 Core is not in boot halt. + 0 + + + Const_11 + 1 Core is in boot halt write to 0 will exit + 1 + + + + + + + CPU_ID + CPUx Identification Register TC1.6.2P + resetvalue={Application Reset:0x0C0C021} + 65048 + 32 + 12632097 + 4294967295 + + + MOD_REV + Revision Number MOD REV + 0 + 7 + read-only + + + Const_3232 + 20 Reset value + 32 + + + + + MOD_32B + 32 Bit Module Enable MOD 32B + 8 + 15 + read-only + + + Const_192192 + C0 A value of C0 H in this field indicates a 32 bit module with a 32 bit module ID register. + 192 + + + + + MOD + Module Identification Number MOD + 16 + 31 + read-only + + + Const_192192 + 00C0 For module identification. + 192 + + + + + + + CORE_ID + CPUx Core Identification Register + resetvalue={Application Reset:0x0} + 65052 + 32 + 0 + 4294967288 + + + CORE_ID + Core Identification Number CORE ID. The identification number of the core. + 0 + 2 + read-only + + + + + BIV + CPUx Base Interrupt Vector Table Pointer + resetvalue={Application Reset:0x0} + 65056 + 32 + 0 + 4294967295 + + + VSS + Vector Spacing Select VSS. 0 32 byte vector spacing. 1 8 Byte vector spacing. + 0 + 0 + read-write + + + BIV + Base Address of Interrupt Vector Table BIV. The address in the BIV register must be aligned to an even byte address halfword address . Because of the simple ORing of the left shifted priority number and the contents of the BIV register the alignment of the base address of the vector table must be to a power of two boundary dependent on the number of interrupt entries used. For the full range of 256 interrupt entries an alignment to an 8 KByte boundary is required. If fewer sources are used the alignment requirements are correspondingly relaxed. + 1 + 31 + read-write + + + + + BTV + CPUx Base Trap Vector Table Pointer + resetvalue={Application Reset:0x0A0000100} + 65060 + 32 + 2684354816 + 4294967295 + + + BTV + Base Address of Trap Vector Table BTV. The address in the BTV register must be aligned to an even byte address halfword address . Also due to the simple ORing of the left shifted trap identification number and the contents of the BTV register the alignment of the base address of the vector table must be to a power of two boundary. There are eight different trap classes resulting in Trap Classes from 0 to 7. The contents of BTV should therefore be set to at least a 256 byte boundary 8 Trap Classes 8 word spacing . + 1 + 31 + read-write + + + + + ISP + CPUx Interrupt Stack Pointer + resetvalue={Application Reset:0x100} + 65064 + 32 + 256 + 4294967295 + + + ISP + Interrupt Stack Pointer ISP + 0 + 31 + read-write + + + + + ICR + CPUx Interrupt Control Register + resetvalue={Application Reset:0x0} + 65068 + 32 + 0 + 4294967295 + + + CCPN + Current CPU Priority Number CCPN. The Current CPU Priority Number CCPN bit field indicates the current priority level of the CPU. It is automatically updated by hardware on entry or exit of Interrupt Service Routines ISRs and through the execution of a BISR instruction. CCPN can also be updated through an MTCR instruction. + 0 + 7 + read-write + + + IE + Global Interrupt Enable Bit IE. The interrupt enable bit globally enables the CPU service request system. Whether a service request is delivered to the CPU depends on the individual Service Request Enable Bits SRE in the SRNs and the current state of the CPU. ICR.IE is automatically updated by hardware on entry and exit of an Interrupt Service Routine ISR . ICR.IE is cleared to 0 when an interrupt is taken and is restored to the previous value when the ISR executes an RFE instruction to terminate itself. ICR.IE can also be updated through the execution of the ENABLE DISABLE MTCR and BISR instructions. + 15 + 15 + read-write + + + Const_00 + 0 Interrupt system is globally disabled + 0 + + + Const_11 + 1 Interrupt system is globally enabled + 1 + + + + + PIPN + Pending Interrupt Priority Number PIPN. A read only bit field that is updated by the ICU at the end of each interrupt arbitration process. It indicates the priority number of the pending service request. ICR.PIPN is set to 0 when no request is pending and at the beginning of each new arbitration process. ... + 16 + 23 + read-only + + + Const_00 + 00 No valid pending request. + 0 + + + Const_11 + 01 Request pending lowest priority. + 1 + + + Const_255255 + FF Request pending highest priority. + 255 + + + + + + + FCX + CPUx Free CSA List Head Pointer + resetvalue={Application Reset:0x0} + 65080 + 32 + 0 + 4294967295 + + + FCXO + FCX Offset Address Field FCXO. The FCXO and FCXS fields together form the FCX pointer which points to the next available CSA. + 0 + 15 + read-write + + + FCXS + FCX Segment Address Field FCXS. Used in conjunction with the FCXO field. + 16 + 19 + read-write + + + + + LCX + CPUx Free CSA List Limit Pointer + resetvalue={Application Reset:0x0} + 65084 + 32 + 0 + 4294967295 + + + LCXO + LCX Offset Field LCXO. The LCXO and LCXS fields form the pointer LCX which points to the last available CSA. + 0 + 15 + read-write + + + LCXS + LCX Segment Address LCXS. This field is used in conjunction with the LCXO field. + 16 + 19 + read-write + + + + + CUS_ID + CPUx Customer ID register + resetvalue={Application Reset:0x0} + 65104 + 32 + 0 + 4294967288 + + + CID + Customer ID CID. See CROSSREFERENCE for the relation between CUS ID and CORE ID for each derivative + 0 + 2 + read-only + + + + + 16 + 4 + Dy[%s] + CPUx Data General Purpose Register 0 + resetvalue={Application Reset:0x0} + 65280 + 32 + 0 + 0 + + + DATA + Data Register DATA. General purpose registers + 0 + 31 + read-write + + + + + 16 + 4 + Ay[%s] + CPUx Address General Purpose Register 0 + resetvalue={Application Reset:0x0} + 65408 + 32 + 0 + 0 + + + ADDR + Address Register ADDR. General purpose registers + 0 + 31 + read-write + + + + + CPXE_0 + CPUx Code Protection Execute Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57344 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + CPXE_1 + CPUx Code Protection Execute Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57348 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + CPXE_2 + CPUx Code Protection Execute Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57352 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + CPXE_3 + CPUx Code Protection Execute Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57356 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + DPRE_0 + CPUx Data Protection Read Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57360 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPRE_1 + CPUx Data Protection Read Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57364 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPRE_2 + CPUx Data Protection Read Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57368 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPRE_3 + CPUx Data Protection Read Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57372 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPWE_0 + CPUx Data Protection Write Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57376 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + DPWE_1 + CPUx Data Protection Write Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57380 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + DPWE_2 + CPUx Data Protection Write Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57384 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + DPWE_3 + CPUx Data Protection Write Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57388 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + CPXE_4 + CPUx Code Protection Execute Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57408 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + CPXE_5 + CPUx Code Protection Execute Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57412 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + DPRE_4 + CPUx Data Protection Read Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57424 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPRE_5 + CPUx Data Protection Read Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57428 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPWE_4 + CPUx Data Protection Write Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57440 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + DPWE_5 + CPUx Data Protection Write Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57444 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + CCTRL + CPUx Counter Control + resetvalue={Debug Reset:0x0} + 64512 + 32 + 0 + 4294967295 + + + CM + Counter Mode CM + 0 + 0 + read-write + + + Const_00 + 0 Normal Mode. + 0 + + + Const_11 + 1 Task Mode. + 1 + + + + + CE + Count Enable CE + 1 + 1 + read-write + + + Const_00 + 0 Disable the counters CCNT ICNT M1CNT M2CNT M3CNT. + 0 + + + Const_11 + 1 Enable the counters CCNT ICNT M1CNT M2CNT M3CNT. + 1 + + + + + M1 + M1CNT Configuration M1 + 2 + 4 + read-write + + + M2 + M2CNT Configuration M2 + 5 + 7 + read-write + + + M3 + M3CNT Configuration M3 + 8 + 10 + read-write + + + + + CCNT + CPUx CPU Clock Cycle Count + resetvalue={Debug Reset:0x0} + 64516 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Current Count of the CPU Clock Cycles. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + ICNT + CPUx Instruction Count + resetvalue={Debug Reset:0x0} + 64520 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Count of the Instructions Executed. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + M1CNT + CPUx Multi Count Register 1 + resetvalue={Debug Reset:0x0} + 64524 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Count of the Selected Event. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + M2CNT + CPUx Multi Count Register 2 + resetvalue={Debug Reset:0x0} + 64528 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Count of the Selected Event. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + M3CNT + CPUx Multi Count Register 3 + resetvalue={Debug Reset:0x0} + 64532 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Count of the Selected Event. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + DBGSR + CPUx Debug Status Register + resetvalue={Debug Reset:0x0} + 64768 + 32 + 0 + 4294967295 + + + DE + Debug Enable DE. Determines whether the CDC is enabled or not. + 0 + 0 + read-only + + + Const_00 + 0 The CDC is disabled. + 0 + + + Const_11 + 1 The CDC is enabled. + 1 + + + + + HALT + CPU Halt Request Status Field HALT. HALT can be set or cleared by software. HALT 0 is the actual Halt bit. HALT 1 is a mask bit to specify whether or not HALT 0 is to be updated on a software write. HALT 1 is always read as 0. HALT 1 must be set to 1 in order to update HALT 0 by software R read W write . + 1 + 2 + read-write + + + Const_00 + 00 R CPU running. W HALT 0 unchanged. + 0 + + + Const_11 + 01 R CPU halted. W HALT 0 unchanged. + 1 + + + Const_22 + 10 R Not Applicable. W reset HALT 0 . + 2 + + + Const_33 + 11 R Not Applicable. W If DBGSR.DE 1 The CDC is enabled set HALT 0 . If DBGSR.DE 0 The CDC is not enabled HALT 0 is left unchanged. + 3 + + + + + SIH + Suspend in Halt SIH. State of the Suspend In signal. + 3 + 3 + read-only + + + Const_00 + 0 The Suspend In signal is negated. The CPU is not in Halt Mode except when the Halt mechanism is set following a Debug Event or a write to DBGSR.HALT . + 0 + + + Const_11 + 1 The Suspend In signal is asserted. The CPU is in Halt Mode. + 1 + + + + + SUSP + Current State of the Core Suspend Out Signal SUSP + 4 + 4 + read-write + + + Const_00 + 0 Core suspend out inactive. + 0 + + + Const_11 + 1 Core suspend out active. + 1 + + + + + PREVSUSP + Previous State of Core Suspend Out Signal PREVSUSP. Updated when a Debug Event causes a hardware update of DBGSR.SUSP. This field is not updated for writes to DBGSR.SUSP. + 6 + 6 + read-only + + + Const_00 + 0 Previous core suspend out inactive. + 0 + + + Const_11 + 1 Previous core suspend out active. + 1 + + + + + PEVT + Posted Event PEVT + 7 + 7 + read-write + + + Const_00 + 0 No posted event. + 0 + + + Const_11 + 1 Posted event. + 1 + + + + + + + EXEVT + CPUx External Event Register + resetvalue={Debug Reset:0x0} + 64776 + 32 + 0 + 4294967295 + + + EVTA + Event Associated EVTA. Specifies the Debug Action associated with the Debug Event + 0 + 2 + read-write + + + Const_00 + 000 BOD 0 Disabled. BOD 1 Disabled. + 0 + + + Const_11 + 001 BOD 0 Pulse BRKOUT Signal. BOD 1 None. + 1 + + + Const_22 + 010 BOD 0 Halt and pulse BRKOUT Signal. BOD 1 Halt. + 2 + + + Const_33 + 011 BOD 0 Breakpoint trap and pulse. BRKOUT Signal. BOD 1 Breakpoint trap. + 3 + + + Const_44 + 100 BOD 0 Breakpoint interrupt 0 and pulse BRKOUT Signal. BOD 1 Breakpoint interrupt 0. + 4 + + + Const_55 + 101 BOD 0 If implemented breakpoint interrupt 1 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 1. If not implemented None. + 5 + + + Const_66 + 110 BOD 0 If implemented breakpoint interrupt 2 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 2. If not implemented None. + 6 + + + Const_77 + 111 BOD 0 If implemented breakpoint interrupt 3 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 3. If not implemented None. + 7 + + + + + BBM + Break Before Make BBM or Break After Make BAM Selection BBM + 3 + 3 + read-write + + + Const_00 + 0 Break after make BAM . + 0 + + + Const_11 + 1 Break before make BBM . + 1 + + + + + BOD + Breakout Disable BOD + 4 + 4 + read-write + + + Const_00 + 0 BRKOUT signal asserted according to the Debug Action specified in the EVTA field. + 0 + + + Const_11 + 1 BRKOUT signal not asserted. This takes priority over any assertion generated by the EVTA field. + 1 + + + + + SUSP + CDC Suspend Out Signal State SUSP. Value to be assigned to the CDC suspend out signal when the Debug Event is raised. + 5 + 5 + read-write + + + CNT + Counter CNT. When this event occurs adjust the control of the performance counters in task mode as follows + 6 + 7 + read-write + + + Const_00 + 00 No change. + 0 + + + Const_11 + 01 Start the performance counters. + 1 + + + Const_22 + 10 Stop the performance counters. + 2 + + + Const_33 + 11 Toggle the performance counter control i.e. start it if it is currently stopped stop it if it is currently running . + 3 + + + + + + + CREVT + CPUx Core Register Access Event + resetvalue={Debug Reset:0x0} + 64780 + 32 + 0 + 4294967295 + + + EVTA + Event Associated EVTA. Debug Action associated with the Debug Event + 0 + 2 + read-write + + + Const_00 + 000 BOD 0 Disabled. BOD 1 Disabled. + 0 + + + Const_11 + 001 BOD 0 Pulse BRKOUT Signal. BOD 1 None. + 1 + + + Const_22 + 010 BOD 0 Halt and pulse BRKOUT Signal. BOD 1 Halt. + 2 + + + Const_33 + 011 BOD 0 Breakpoint trap and pulse BRKOUT Signal. BOD 1 Breakpoint trap. + 3 + + + Const_44 + 100 BOD 0 Breakpoint interrupt 0 and pulse BRKOUT Signal. BOD 1 Breakpoint interrupt 0. + 4 + + + Const_55 + 101 BOD 0 If implemented breakpoint interrupt 1 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 1. If not implemented None. + 5 + + + Const_66 + 110 BOD 0 If implemented breakpoint interrupt 2 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 2. If not implemented None. + 6 + + + Const_77 + 111 BOD 0 If implemented breakpoint interrupt 3 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 3. If not implemented None. + 7 + + + + + BBM + Break Before Make BBM or Break After Make BAM Selection BBM + 3 + 3 + read-write + + + Const_00 + 0 Break after make BAM . + 0 + + + Const_11 + 1 Break before make BBM . + 1 + + + + + BOD + Breakout Disable BOD + 4 + 4 + read-write + + + Const_00 + 0 BRKOUT signal asserted according to the action specified in the EVTA field. + 0 + + + Const_11 + 1 BRKOUT signal not asserted. This takes priority over any assertion generated by the EVTA field. + 1 + + + + + SUSP + CDC Suspend Out Signal State SUSP. Value to be assigned to the CDC suspend out signal when the Debug Event is raised. + 5 + 5 + read-write + + + CNT + Counter CNT. When this event occurs adjust the control of the performance counters in task mode as follows + 6 + 7 + read-write + + + Const_00 + 00 No change. + 0 + + + Const_11 + 01 Start the performance counters. + 1 + + + Const_22 + 10 Stop the performance counters. + 2 + + + Const_33 + 11 Toggle the performance counter control i.e. start it if it is currently stopped stop it if it is currently running . + 3 + + + + + + + SWEVT + CPUx Software Debug Event + resetvalue={Debug Reset:0x0} + 64784 + 32 + 0 + 4294967295 + + + EVTA + Event Associated EVTA. Debug Action associated with the Debug Event + 0 + 2 + read-write + + + Const_00 + 000 BOD 0 Disabled. BOD 1 Disabled. + 0 + + + Const_11 + 001 BOD 0 Pulse BRKOUT Signal. BOD 1 None. + 1 + + + Const_22 + 010 BOD 0 Halt and pulse BRKOUT Signal. BOD 1 Halt. + 2 + + + Const_33 + 011 BOD 0 Breakpoint trap and pulse BRKOUT Signal. BOD 1 Breakpoint trap. + 3 + + + Const_44 + 100 BOD 0 Breakpoint interrupt 0 and pulse BRKOUT Signal. BOD 1 Breakpoint interrupt 0. + 4 + + + Const_55 + 101 BOD 0 If implemented breakpoint interrupt 1 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 1. If not implemented None. + 5 + + + Const_66 + 110 BOD 0 If implemented breakpoint interrupt 2 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 2. If not implemented None. + 6 + + + Const_77 + 111 BOD 0 If implemented breakpoint interrupt 3 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 3. If not implemented None. + 7 + + + + + BBM + Break Before Make BBM or Break After Make BAM Selection BBM + 3 + 3 + read-write + + + Const_00 + 0 Break after make BAM . + 0 + + + Const_11 + 1 Break before make BBM . + 1 + + + + + BOD + Breakout Disable BOD + 4 + 4 + read-write + + + Const_00 + 0 BRKOUT signal asserted according to the action specified in the EVTA field. + 0 + + + Const_11 + 1 BRKOUT signal not asserted. This takes priority over any assertion generated by the EVTA field. + 1 + + + + + SUSP + CDC Suspend Out Signal State SUSP. Value to be assigned to the CDC suspend out signal when the event is raised. + 5 + 5 + read-write + + + CNT + Counter CNT. When this event occurs adjust the control of the performance counters in task mode as follows + 6 + 7 + read-write + + + Const_00 + 00 No change. + 0 + + + Const_11 + 01 Start the performance counters. + 1 + + + Const_22 + 10 Stop the performance counters. + 2 + + + Const_33 + 11 Toggle the performance counter control i.e. start it if it is currently stopped stop it if it is currently running . + 3 + + + + + + + TRIG_ACC + CPUx TriggerAddressx + resetvalue={Debug Reset:0x0} + 64816 + 32 + 0 + 4294967295 + + + T0 + Trigger 0 T0. active since last cleared + 0 + 0 + read-only + + + T1 + Trigger 1 T1. active since last cleared + 1 + 1 + read-only + + + T2 + Trigger 2 T2. active since last cleared + 2 + 2 + read-only + + + T3 + Trigger 3 T3. active since last cleared + 3 + 3 + read-only + + + T4 + Trigger 4 T4. active since last cleared + 4 + 4 + read-only + + + T5 + Trigger 5 T5. active since last cleared + 5 + 5 + read-only + + + T6 + Trigger 6 T6. active since last cleared + 6 + 6 + read-only + + + T7 + Trigger 7 T7. active since last cleared + 7 + 7 + read-only + + + + + DMS + CPUx Debug Monitor Start Address + resetvalue={Application Reset:0x0} + 64832 + 32 + 0 + 0 + + + DMSValue + Debug Monitor Start Address DMSValue. The address at which monitor code execution begins when a breakpoint trap is taken. + 1 + 31 + read-write + + + + + DCX + CPUx Debug Context Save Area Pointer + resetvalue={Application Reset:0x0} + 64836 + 32 + 0 + 0 + + + DCXValue + Debug Context Save Area Pointer DCXValue. Address where the debug context is stored following a breakpoint trap. + 6 + 31 + read-write + + + + + DBGTCR + CPUx Debug Trap Control Register + resetvalue={Application Reset:0x1} + 64840 + 32 + 1 + 4294967295 + + + DTA + Debug Trap Active Bit DTA. A breakpoint trap may only be taken in the condition DTA 0. Taking a breakpoint trap sets the DTA bit to one. Further breakpoint traps are therefore disabled until such time as the breakpoint trap handler clears the DTA bit or until the breakpoint trap handler terminates with a RFM. + 0 + 0 + read-write + + + Const_00 + 0 No breakpoint trap is active. + 0 + + + Const_11 + 1 A breakpoint Trap is active + 1 + + + + + + + SEGEN + CPUx SRI Error Generation Register + resetvalue={Application Reset:0x0} + 4144 + 32 + 0 + 4294967295 + + + ADFLIP + Address ECC Bit Flip ADFLIP. SRI address ECC Bits to be flipped on the next read or write transaction from the DMI when enabled by AE. + 0 + 7 + read-write + + + Const_00 + 0 No Flip + 0 + + + Const_11 + 1 Flip + 1 + + + + + ADTYPE + Type of error ADTYPE + 8 + 9 + read-write + + + Const_00 + 00 Data Master Address Phase + 0 + + + Const_11 + 01 Data Master Write Data + 1 + + + Const_22 + 10 Data Slave Read Data + 2 + + + + + AE + Activate Error Enable AE. Enabled the selective inverting of SRI ECC packet bits defined by ADFLIP. This bit will be cleared by hardware after the next SRI read or write transaction from the DMI. + 31 + 31 + read-write + + + Const_00 + 0 Not Enabled + 0 + + + Const_11 + 1 Enabled + 1 + + + + + + + DCON2 + CPUx Data Control Register 2 + resetvalue={Application Reset:0x0} + 36864 + 32 + 0 + 0 + + + DCACHE_SZE + Data Cache Size DCACHE SZE. In KBytes + 0 + 15 + read-only + + + DSCRATCH_SZE + Data Scratch Size DSCRATCH SZE. In KBytes + 16 + 31 + read-only + + + + + DSTR + CPUx Data Synchronous Trap Register + resetvalue={Application Reset:0x0} + 36880 + 32 + 0 + 4294967295 + + + SRE + Scratch Range Error SRE. A scratch Range Error occurs whenever an access to the data scratch is outside the range of the SRAM. + 0 + 0 + read-write + + + GAE + Global Address Error GAE. Load or store to local code scratch address outside of the lower 1MByte. + 1 + 1 + read-write + + + LBE + Load Bus Error LBE. A Load Bus Error will be set whenever the SRI flags an error due a load from external memory. + 2 + 2 + read-write + + + DRE + Local DLMU Range Error DRE. A DLMU Range Error occurs whenever an access to the local DLMU region is outside the physically implemented memory. + 3 + 3 + read-write + + + CRE + Cache Refill Error CRE. A Cache Refill Error will be set whenever the SRI flags an error due a cache refill from external memory. + 6 + 6 + read-write + + + DTME + DTAG MSIST Error DTME. Access to memory mapped DTAG range outside of physically implemented memory. + 14 + 14 + read-write + + + LOE + Load Overlay Error LOE. Load to invalid overlay address. + 15 + 15 + read-write + + + SDE + Segment Difference Error SDE. Load or store access where base address is in different segment to access address. + 16 + 16 + read-write + + + SCE + Segment Crossing Error SCE. Load or store access across segment boundary. + 17 + 17 + read-write + + + CAC + CSFR Access Error CAC. Load or store to local CSFR space. + 18 + 18 + read-write + + + MPE + Memory Protection Error MPE. Data access violating memory protection. + 19 + 19 + read-write + + + CLE + Context Location Error CLE. Context operation to invalid location. + 20 + 20 + read-write + + + ALN + Alignment Error ALN. Data access causing alignment error. + 24 + 24 + read-write + + + + + DATR + CPUx Data Asynchronous Trap Register + resetvalue={Application Reset:0x0} + 36888 + 32 + 0 + 4294967295 + + + SBE + Store Bus Error SBE + 3 + 3 + read-write + + + CWE + Cache Writeback Error CWE + 9 + 9 + read-write + + + CFE + Cache Flush Error CFE + 10 + 10 + read-write + + + SOE + Store Overlay Error SOE + 14 + 14 + read-write + + + + + DEADD + CPUx Data Error Address Register + resetvalue={Application Reset:0x0} + 36892 + 32 + 0 + 4294967295 + + + ERROR_ADDRESS + Error Address ERROR ADDRESS + 0 + 31 + read-only + + + + + DCON0 + CPUx Data Memory Control Register + resetvalue={Application Reset:0x2} + 36928 + 32 + 2 + 4294967295 + + + DCBYP + Data Cache Bypass DCBYP + 1 + 1 + read-write + + + Const_00 + 0 DCache DRB enabled + 0 + + + Const_11 + 1 DCache DRB Bypass disabled + 1 + + + + + + + PSTR + CPUx Program Synchronous Trap Register + resetvalue={Application Reset:0x0} + 37376 + 32 + 0 + 4294967295 + + + FRE + Fetch Range Error FRE. A Fetch Range Error occurs whenever an access to the Program Scratch is outside the range of the SRAM. + 0 + 0 + read-write + + + FBE + Fetch Bus Error FBE. A Fetch bus error will be set whenever the SRI flags an error due a fetch from external memory. This will be set for both direct fetches from the bus and for cache refills. + 2 + 2 + read-write + + + FPE + Fetch Peripheral Error FPE. A Fetch peripheral error will be flagged whenever a fetch is attempted to peripheral space. + 12 + 12 + read-write + + + FME + Fetch MSIST Error FME. During SIST mode a fetch from the PTAG will cause a PSE trap to occur. + 14 + 14 + read-write + + + + + PCON1 + CPUx Program Control 1 + resetvalue={Application Reset:0x0} + 37380 + 32 + 0 + 4294967295 + + + PCINV + Program Cache Invalidate PCINV + 0 + 0 + read-write + + + Const_00 + 0 Write No effect normal instruction cache operation. Read Normal operation instruction cache available + 0 + + + Const_11 + 1 Write Initiate invalidation of entire instruction cache. Read Instruction cache invalidation in progress. Instruction cache unavailable. + 1 + + + + + PBINV + Program Buffer Invalidate PBINV. Write Operation This field returns 0 when read. + 1 + 1 + read-write + + + Const_00 + 0 Write No effect. Normal program line buffer operation. + 0 + + + Const_11 + 1 Write Invalidate the program line buffer. + 1 + + + + + + + PCON2 + CPUx Program Control 2 + resetvalue={Application Reset:0x0} + 37384 + 32 + 0 + 0 + + + PCACHE_SZE + Program Cache Size ICACHE in KBytes PCACHE SZE. In KBytes + 0 + 15 + read-only + + + PSCRATCH_SZE + Program Scratch Size in KBytes PSCRATCH SZE. In KBytes + 16 + 31 + read-only + + + + + PCON0 + CPUx Program Control 0 + resetvalue={Application Reset:0x2} + 37388 + 32 + 2 + 4294967295 + + + PCBYP + Program Cache Bypass PCBYP + 1 + 1 + read-write + + + Const_00 + 0 Cache enabled + 0 + + + Const_11 + 1 Cache bypass disabled + 1 + + + + + + + + + CPU1 + 100 + CPU + CPU0 + 0 + + 0 + 65472 + registers + + + + 18 + 8 + DPR[%s] + DPR + 49152 + + DPRy_L + CPUx Data Protection Range 0 Lower Bound Register + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + LOWBND + DPRy Lower Boundary Address LOWBND + 3 + 31 + read-write + + + + + DPRy_U + CPUx Data Protection Range 0 Upper Bound Register + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + UPPBND + DPRy Upper Boundary Address UPPBND + 3 + 31 + read-write + + + + + + 10 + 8 + CPR[%s] + CPR + 53248 + + CPRy_L + CPUx Code Protection Range 0 Lower Bound Register + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + LOWBND + CPRy Lower Boundary Address LOWBND + 5 + 31 + read-write + + + + + CPRy_U + CPUx Code Protection Range 0 Upper Bound Register + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + UPPBND + CPR0 m Upper Boundary Address UPPBND + 5 + 31 + read-write + + + + + + TPS + TPS + 58368 + + CON + CPUx Temporal Protection System Control Register + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + TEXP0 + Timer0 Expired Flag TEXP0. Set when the corresponding timer expires. Cleared on any write to the TIMER0 register. + 0 + 0 + read-only + + + TEXP1 + Timer1 Expired Flag TEXP1. Set when the corresponding timer expires. Cleared on any write to the TIMER1 register. + 1 + 1 + read-only + + + TEXP2 + Timer1 Expired Flag TEXP2. Set when the corresponding timer expires. Cleared on any write to the TIMER1 register. + 2 + 2 + read-only + + + TTRAP + Temporal Protection Trap TTRAP. If set indicates that a TAE trap has been requested. Any subsequent TAE traps are disabled. A write clears the flag and re enables TAE traps. + 16 + 16 + read-only + + + + + 3 + 4 + TIMER[%s] + CPUx Temporal Protection System Timer Register 0 + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + Timer + Temporal Protection Timer Timer. Writing zero de activates the Timer. Writing a non zero value starts the Timer. Any write clears the corresponding TPS CON.TEXP flag. Read returns the current Timer value. + 0 + 31 + read-write + + + + + + TPS_EXTIM + TPS EXTIM + 58432 + + ENTRY_LVAL + CPUx Exception Entry Timer Load Value + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + ENTRY_LVAL + Exception Entry Timer Load value ENTRY LVAL. Value loaded into the exception entry timer on detection of an enabled exception. Bits 3 0 are constrained to be 0 + 4 + 11 + read-write + + + + + ENTRY_CVAL + CPUx Exception Entry Timer Current Value + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + ENTRY_CVAL + Exception Entry Timer Current Value ENTRY CVAL. Current value of the exception entry timer. + 0 + 11 + read-only + + + + + EXIT_LVAL + CPUx Exception Exit Timer Load Value + resetvalue={Application Reset:0x0} + 8 + 32 + 0 + 4294967295 + + + EXIT_LVAL + Exception Exit Timer Load value EXIT LVAL. Value loaded into the exception exit timer on detection of an enabled exception. Bits 3 0 are constrained to be 0 + 4 + 23 + read-write + + + + + EXIT_CVAL + CPUx Exception Exit Timer Current Value + resetvalue={Application Reset:0x0} + 12 + 32 + 0 + 4294967295 + + + EXIT_CVAL + Exception Exit Timer Current Value EXIT CVAL. Current value of the exception exit timer. + 0 + 23 + read-only + + + + + CLASS_EN + CPUx Exception Timer Class Enable Register + resetvalue={Application Reset:0x0} + 16 + 32 + 0 + 4294967295 + + + EXTIM_CLASS_EN + Exception Timer Class Enables EXTIM CLASS EN. Trap Class enables for exception timer. + 0 + 7 + read-write + + + + + STAT + CPUx Exception Timer Status Register + resetvalue={Application Reset:0x0} + 20 + 32 + 0 + 4294967295 + + + EXIT_TIN + Exception Exit Timer TIN EXIT TIN. Exception Exit Timer TIN of triggering trap. + 0 + 7 + read-write + + + EXIT_CLASS + Exception Exit Timer Class EXIT CLASS. Exception exit Timer Class of triggering trap. + 8 + 10 + read-write + + + EXIT_AT + Exception Exit Timer Alarm Triggered EXIT AT. Exception Exit Timer Alarm triggered sticky bit. Alarm triggered since last cleared. + 15 + 15 + read-only + + + ENTRY_TIN + Exception Entry Timer TIN ENTRY TIN. Exception Entry Timer TIN of triggering trap. + 16 + 23 + read-write + + + ENTRY_CLASS + Exception Entry Timer Class ENTRY CLASS. Exception Entry Timer Class of triggering trap. + 24 + 26 + read-write + + + ENTRY_AT + Exception Entry Timer Alarm Triggered ENTRY AT. Exception Entry Timer Alarm triggered sticky bit. Alarm triggered since last cleared. + 31 + 31 + read-only + + + + + FCX + CPUx Exception Timer FCX Register + resetvalue={Application Reset:0x0} + 24 + 32 + 0 + 4294967295 + + + EXIT_FCX + Exception Exit Timer FCX EXIT FCX. Exception Exit Timer FCX of triggering trap. + 0 + 19 + read-only + + + + + + FPU_TRAP + FPU TRAP + 40960 + + CON + CPUx Trap Control Register + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + TST + Trap Status TST + 0 + 0 + read-only + + + Const_00 + 0 No instruction captured. The next enabled exception will cause the exceptional instruction to be captured. + 0 + + + Const_11 + 1 Instruction captured. No further enabled exceptions will be captured until TST is cleared. + 1 + + + + + TCL + Trap Clear TCL. Read always reads as 0. + 1 + 1 + write-only + + + Const_00 + 0 No effect. + 0 + + + Const_11 + 1 Clears the trapped instruction TST will be negated . + 1 + + + + + RM + Captured Rounding Mode RM. The rounding mode of the captured instruction. Only valid when TST is asserted. Note that this is the rounding mode supplied to the FPU for the exceptional instruction. UPDFL instructions may cause a trap and change the rounding mode. In this case the RM bits capture the input rounding mode + 8 + 9 + read-only + + + FXE + FX Trap Enable FXE. When set an instruction generating an FX exception will trigger a trap. + 18 + 18 + read-write + + + FUE + FU Trap Enable FUE. When set an instruction generating an FU exception will trigger a trap. + 19 + 19 + read-write + + + FZE + FZ Trap Enable FZE. When set an instruction generating an FZ exception will trigger a trap. + 20 + 20 + read-write + + + FVE + FV Trap Enable FVE. When set an instruction generating an FV exception will trigger a trap. + 21 + 21 + read-write + + + FIE + FI Trap Enable FIE. When set an instruction generating an FI exception will trigger a trap. + 22 + 22 + read-write + + + FX + Captured FX FX. Asserted if the captured instruction asserted FX. Only valid when TST is asserted. + 26 + 26 + read-only + + + FU + Captured FU FU. Asserted if the captured instruction asserted FU. Only valid when TST is asserted. + 27 + 27 + read-only + + + FZ + Captured FZ FZ. Asserted if the captured instruction asserted FZ. Only valid when TST is asserted + 28 + 28 + read-only + + + FV + Captured FV FV. Asserted if the captured instruction asserted FV. Only valid when TST is asserted + 29 + 29 + read-only + + + FI + Captured FI FI. Asserted if the captured instruction asserted FI. Only valid when TST is asserted + 30 + 30 + read-only + + + + + PC + CPUx Trapping Instruction Program Counter Register + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + PC + Captured Program Counter PC. The program counter virtual address of the captured instruction. Only valid when FPU TRAP CON.TST is asserted. + 0 + 31 + read-only + + + + + OPC + CPUx Trapping Instruction Opcode Register + resetvalue={Application Reset:0x0} + 8 + 32 + 0 + 4294967295 + + + OPC + Captured Opcode OPC. The secondary opcode of the captured instruction. When FPU TRAP OPC.FMT 0 only bits 3 0 are defined. OPC is valid only when FPU TRAP CON.TST is asserted. + 0 + 7 + read-only + + + FMT + Captured Instruction Format FMT. The format of the captured instruction s opcode. Only valid when FPU TRAP CON.TST is asserted. + 8 + 8 + read-only + + + Const_00 + 0 RRR + 0 + + + Const_11 + 1 RR + 1 + + + + + DREG + Captured Destination Register DREG. The destination register of the captured instruction. ... Only valid when FPU TRAP CON.TST is asserted. + 16 + 19 + read-only + + + Const_00 + 0 Data general purpose register 0. + 0 + + + Const_1515 + F Data general purpose register 15. + 15 + + + + + + + SRC1 + CPUx Trapping Instruction Operand Register + resetvalue={Application Reset:0x0} + 16 + 32 + 0 + 4294967295 + + + SRC1 + Captured SRC1 Operand SRC1. The SRC1 operand of the captured instruction. Only valid when FPU TRAP CON.TST is asserted. + 0 + 31 + read-only + + + + + SRC2 + CPUx Trapping Instruction Operand Register + resetvalue={Application Reset:0x0} + 20 + 32 + 0 + 4294967295 + + + SRC2 + Captured SRC2 Operand SRC2. The SRC2 operand of the captured instruction. Only valid when FPU TRAP CON.TST is asserted. + 0 + 31 + read-only + + + + + SRC3 + CPUx Trapping Instruction Operand Register + resetvalue={Application Reset:0x0} + 24 + 32 + 0 + 4294967295 + + + SRC3 + Captured SRC3 Operand SRC3. The SRC3 operand of the captured instruction. Only valid when FPU TRAP CON.TST is asserted. + 0 + 31 + read-only + + + + + + 8 + 8 + TR[%s] + Trigger + 61440 + + TRiEVT + CPUx Trigger Event 0 + resetvalue={Debug Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + EVTA + Event Associated EVTA. Specifies the Debug Action associated with the Debug Event + 0 + 2 + read-write + + + Const_00 + 000 BOD 0 Disabled. BOD 1 Disabled. + 0 + + + Const_11 + 001 BOD 0 Pulse BRKOUT Signal. BOD 1 None. + 1 + + + Const_22 + 010 BOD 0 Halt and pulse BRKOUT Signal. BOD 1 Halt. + 2 + + + Const_33 + 011 BOD 0 Breakpoint trap and pulse BRKOUT Signal. BOD 1 Breakpoint trap. + 3 + + + Const_44 + 100 BOD 0 Breakpoint interrupt 0 and pulse BRKOUT Signal. BOD 1 Breakpoint interrupt 0. + 4 + + + Const_55 + 101 BOD 0 If implemented breakpoint interrupt 1 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 1. If not implemented None. + 5 + + + Const_66 + 110 BOD 0 If implemented breakpoint interrupt 2 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 2. If not implemented None. + 6 + + + Const_77 + 111 BOD 0 If implemented breakpoint interrupt 3 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 3. If not implemented None. + 7 + + + + + BBM + Break Before Make BBM or Break After Make BAM Selection BBM. Code triggers BBM or BAM selection. Data access and data code combination access triggers can only create BAM Debug Events. When these triggers occur TRnEVT.BBM is ignored. + 3 + 3 + read-write + + + Const_00 + 0 Code only triggers Break After Make BAM . + 0 + + + Const_11 + 1 Code only triggers Break Before Make BBM . + 1 + + + + + BOD + Breakout Disable BOD + 4 + 4 + read-write + + + Const_00 + 0 BRKOUT signal asserted according to the action specified in the EVTA field. + 0 + + + Const_11 + 1 BRKOUT signal not asserted. This takes priority over any assertion generated by the EVTA field. + 1 + + + + + SUSP + CDC Suspend Out Signal State SUSP. Value to be assigned to the CDC suspend out signal when the Debug Event is raised. + 5 + 5 + read-write + + + CNT + Counter CNT. When this event occurs adjust the control of the performance counters in task mode as follows + 6 + 7 + read-write + + + Const_00 + 00 No change. + 0 + + + Const_11 + 01 Start the performance counters. + 1 + + + Const_22 + 10 Stop the performance counters. + 2 + + + Const_33 + 11 Toggle the performance counter control i.e. start it if it is currently stopped stop it if it is currently running . + 3 + + + + + TYP + Input Selection TYP + 12 + 12 + read-write + + + Const_00 + 0 Address + 0 + + + Const_11 + 1 PC + 1 + + + + + RNG + Compare Type RNG. Once an even numbered comparator has been set to range the EVTR settings of its associated upper neighbour will be ignored. + 13 + 13 + read-write + + + Const_11 + 1 Range + 1 + + + Const_00 + 0 Equality + 0 + + + + + ASI_EN + Enable ASI Comparison ASI EN + 15 + 15 + read-write + + + Const_00 + 0 No ASI comparison performed. Debug Trigger is valid for all processes. + 0 + + + Const_11 + 1 Enable ASI comparison. Debug Events are only triggered when the current process ASI matches TRnEVT.ASI. + 1 + + + + + ASI + Address Space Identifier ASI. The ASI of the Debug Trigger process. + 16 + 20 + read-write + + + AST + Address Store AST. Used in conjunction with TYP 0 + 27 + 27 + read-write + + + ALD + Address Load ALD. Used in conjunction with TYP 0 + 28 + 28 + read-write + + + + + TRiADR + CPUx Trigger Address 0 + resetvalue={Debug Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + ADDR + Comparison Address ADDR. For PC comparison bit 0 is always zero. + 0 + 31 + read-write + + + + + + SMACON + CPUx SIST Mode Access Control Register + resetvalue={Application Reset:0x0} + 36876 + 32 + 0 + 4294967295 + + + IODT + In Order Data Transactions IODT + 24 + 24 + read-write + + + Const_00 + 0 Normal operation Non dependent loads bypass stores. + 0 + + + Const_11 + 1 In order operation Loads always flush preceding stores processor store buffer disabled. + 1 + + + + + + + DIEAR + CPUx Data Integrity Error Address Register + resetvalue={Application Reset:0x0} + 36896 + 32 + 0 + 4294967295 + + + TA + Transaction Address TA. Physical address being accessed by operation that encountered data integrity error. + 0 + 31 + read-only + + + + + DIETR + CPUx Data Integrity Error Trap Register + resetvalue={Application Reset:0x0} + 36900 + 32 + 0 + 4294967295 + + + IED + Integrity Error Detected IED + 0 + 0 + read-write + + + Const_00 + 0 Write Clear IED bit re enable DIETR and DIEAR update. Read No data integrity error condition occurred + 0 + + + Const_11 + 1 Write No Effect. Read Data integrity error condition detected. DIETR and DIEAR contents valid further DIETR and DIEAR updates disabled.. + 1 + + + + + IE_T + Integrity Error Tag Memory IE T + 1 + 1 + read-only + + + IE_C + Integrity Error Cache Memory IE C + 2 + 2 + read-only + + + IE_S + Integrity Error Scratchpad Memory IE S + 3 + 3 + read-only + + + IE_BI + Integrity Error Bus Interface IE BI + 4 + 4 + read-only + + + E_INFO + Error Information E INFO. If IE BS 1 Bus Master Tag ID of requesting masterIf IE C 1 Cache way. + 5 + 10 + read-only + + + IE_UNC + Dual Bit Error Detected IE UNC + 11 + 11 + read-only + + + IE_SP + Safety Protection Error Detected IE SP + 12 + 12 + read-only + + + IE_BS + Bus Slave Access Indicator IE BS + 13 + 13 + read-only + + + IE_DLMU + Integrity Error DLMU IE DLMU + 14 + 14 + read-only + + + IE_LPB + Integrity Error Local Pflash Bank IE LPB + 15 + 15 + read-only + + + IE_MTMV + Memory Test Mode Violation detected IE MTMV + 16 + 16 + read-only + + + + + PIEAR + CPUx Program Integrity Error Address Register + resetvalue={Application Reset:0x0} + 37392 + 32 + 0 + 4294967295 + + + TA + Transaction Address TA. Physical address being accessed by operation that encountered program integrity error. + 0 + 31 + read-only + + + + + PIETR + CPUx Program Integrity Error Trap Register + resetvalue={Application Reset:0x0} + 37396 + 32 + 0 + 4294967295 + + + IED + Integrity Error Detected IED + 0 + 0 + read-write + + + Const_00 + 0 Write Clear IED bit re enable PIETR and PIEAR update. Read No data integrity error condition occurred + 0 + + + Const_11 + 1 Write No Effect. Read Data integrity error condition detected. PIETR and PIEAR contents valid further PIETR and PIEAR updates disabled.. + 1 + + + + + IE_T + Integrity Error TAG Memory IE T + 1 + 1 + read-only + + + IE_C + Integrity Error Cache Memory IE C + 2 + 2 + read-only + + + IE_S + Integrity Error Scratchpad Memory IE S + 3 + 3 + read-only + + + IE_BI + Integrity Error Bus Interface IE BI + 4 + 4 + read-only + + + E_INFO + Error Information E INFO. If IE BS 1 Bus Master Tag ID of requesting masterIf IE C 1 Cache way. + 5 + 10 + read-only + + + IE_UNC + Integrity Error Uncorrectable Error Detected IE UNC + 11 + 11 + read-only + + + IE_SP + Safety Protection Error Detected IE SP + 12 + 12 + read-only + + + IE_BS + Bus Slave Access Indicator IE BS + 13 + 13 + read-only + + + IE_ADDR + Address Phase error detected at SRI slave interface IE ADDR + 14 + 14 + read-only + + + IE_LPB + Integrity Error Local Pflash bank IE LPB + 15 + 15 + read-only + + + IE_MTMV + Memory Test Mode Violation detected IE MTMV + 16 + 16 + read-only + + + + + TASK_ASI + CPUx Task Address Space Identifier Register + resetvalue={Application Reset:0x1F} + 32772 + 32 + 31 + 4294967295 + + + ASI + Address Space Identifier ASI. The ASI register contains the Address Space Identifier of the current process. + 0 + 4 + read-write + + + + + PMA0 + CPUx Data Access CacheabilityRegister + resetvalue={Application Reset:0x300} + 33024 + 32 + 768 + 4294967295 + + + DAC + Data Access Cacheability Segments FHto 0H DAC. Note segments F H E H D H and A H are constrained to be non cacheable + 0 + 15 + read-write + + + + + PMA1 + CPUx Code Access CacheabilityRegister + resetvalue={Application Reset:0x300} + 33028 + 32 + 768 + 4294967295 + + + CAC + Code Access Cacheability Segments FH 0H CAC. Note Segments F H E H C H A H are constrained to be non cacheable + 0 + 15 + read-write + + + + + PMA2 + CPUx Peripheral Space Identifier register + resetvalue={Application Reset:0x0C000} + 33032 + 32 + 49152 + 4294967295 + + + PSI + Peripheral Space Identifier Segments FH 0H PSI + 0 + 15 + read-only + + + + + COMPAT + CPUx Compatibility Control Register + resetvalue={Application Reset:0x0FFFFFFFF} + 37888 + 32 + 4294967295 + 4294967295 + + + RM + Rounding Mode Compatibility RM + 3 + 3 + read-write + + + Const_00 + 0 PSW.RM not restored by RET. + 0 + + + Const_11 + 1 PSW.RM restored by RET TC1.3 behavior . + 1 + + + + + SP + SYSCON Safety Protection Mode Compatibility SP + 4 + 4 + read-write + + + Const_00 + 0 SYSCON 31 1 safety endinit protected. + 0 + + + Const_11 + 1 SYSCON 31 1 not safety endinit protected TC1.3 behavior . + 1 + + + + + + + PCXI + CPUx Previous Context Information Register + resetvalue={Application Reset:0x0} + 65024 + 32 + 0 + 4294967295 + + + PCXO + Previous Context Pointer Offset Field PCXO. The PCXO and PCXS fields form the pointer PCX which points to the CSA of the previous context. + 0 + 15 + read-write + + + PCXS + Previous Context Pointer Segment Address PCXS. Contains the segment address portion of the PCX. This field is used in conjunction with the PCXO field. + 16 + 19 + read-write + + + UL + Upper or Lower Context Tag UL. Identifies the type of context saved. If the type does not match the type expected when a context restore operation is performed a trap is generated. + 20 + 20 + read-write + + + Const_00 + 0 Lower Context + 0 + + + Const_11 + 1 Upper Context + 1 + + + + + PIE + Previous Interrupt Enable PIE. Indicates the state of the interrupt enable bit ICR.IE for the interrupted task. + 21 + 21 + read-write + + + PCPN + Previous CPU Priority Number PCPN. Contains the priority level number of the interrupted task. + 22 + 29 + read-write + + + + + PSW + CPUx Program Status Word + resetvalue={Application Reset:0x0B80} + 65028 + 32 + 2944 + 4294967295 + + + CDC + Call Depth Counter CDC. Consists of two variable width subfields. The first subfield consists of a string of zero or more initial 1 bits terminated by the first 0 bit. The remaining bits form the second subfield CDC.COUNT which constitutes the Call Depth Count value. The count value is incremented on each Call and is decremented on a Return. 0cccccc B 6 bit counter trap on overflow. 10ccccc B 5 bit counter trap on overflow. 110cccc B 4 bit counter trap on overflow. 1110ccc B 3 bit counter trap on overflow. 11110cc B 2 bit counter trap on overflow. 111110c B 1 bit counter trap on overflow. 1111110 B Trap every call Call Trace mode . 1111111 B Disable Call Depth Counting. When the call depth count CDC.COUNT overflows a trap CDO is generated. Setting the CDC to 1111110 B allows no bits for the counter and causes every call to be trapped. This is used for Call Depth Tracing. Setting the CDC to 1111111 B disables Call Depth Counting. + 0 + 6 + read-write + + + CDE + Call Depth Count Enable CDE. Enables call depth counting provided that the PSW.CDC mask field is not all set to 1. If PSW.CDC 1111111 B call depth counting is disabled regardless of the setting on the PSW.CDE bit. + 7 + 7 + read-write + + + Const_00 + 0 Call depth counting is temporarily disabled. It is automatically re enabled after execution of the next Call instruction. + 0 + + + Const_11 + 1 Call depth counting is enabled. + 1 + + + + + IS + Interrupt Stack Control IS. Determines if the current execution thread is using the shared global interrupt stack or a user stack. + 9 + 9 + read-write + + + Const_00 + 0 User Stack. If an interrupt is taken when the IS bit is 0 then the stack pointer register is loaded from the ISP register before execution starts at the first instruction of the Interrupt Service Routine ISR . + 0 + + + Const_11 + 1 Shared Global Stack. If an interrupt is taken when the PSW.IS bit is 1 then the current value of the stack pointer is used by the Interrupt Service Routine ISR . + 1 + + + + + IO + Access Privilege Level Control I O Privilege IO. Determines the access level to special function registers and peripheral devices. + 10 + 11 + read-write + + + Const_00 + 00 User 0 Mode No peripheral access. Access to memory regions with the peripheral space attribute are prohibited and results in a PSE or MPP trap. This access level is given to tasks that need not directly access peripheral devices. Tasks at this level do not have permission to enable or disable interrupts. + 0 + + + Const_11 + 01 User 1 Mode Regular peripheral access. Enables access to common peripheral devices that are not specially protected including read write access to serial I O ports read access to timers and access to most I O status registers. Tasks at this level may disable interrupts. + 1 + + + Const_22 + 10 Supervisor Mode Enables access to all peripheral devices. It enables read write access to core registers and protected peripheral devices. Tasks at this level may disable interrupts. + 2 + + + + + S + Safe Task Identifier S + 14 + 14 + read-write + + + USB + User Status Bits USB. The eight most significant bits of the PSW are designated as User Status Bits. These bits may be set or cleared as side effects of instruction execution. Refer to the TriCore Architecture manual for details. + 24 + 31 + read-write + + + + + PC + CPUx Program Counter + resetvalue={Application Reset:0x0} + 65032 + 32 + 0 + 0 + + + PC + Program Counter PC + 1 + 31 + read-write + + + + + SYSCON + CPUx System Configuration Register + resetvalue={Application Reset:0x0,Application Reset:0x0} + 65044 + 32 + 0 + 0 + + + FCDSF + Free Context List Depleted Sticky Flag FCDSF. This sticky bit indicates that a FCD Free Context List Depleted trap occurred since the bit was last cleared by software. + 0 + 0 + read-write + + + Const_00 + 0 No FCD trap occurred since the last clear. + 0 + + + Const_11 + 1 An FCD trap occurred since the last clear. + 1 + + + + + PROTEN + Memory Protection Enable PROTEN. Enables the memory protection system. Memory protection is controlled through the memory protection register sets. Note Initialize the protection register sets prior to setting PROTEN to one. + 1 + 1 + read-write + + + Const_00 + 0 Memory Protection is disabled. + 0 + + + Const_11 + 1 Memory Protection is enabled. + 1 + + + + + TPROTEN + Temporal Protection Enable TPROTEN. Enable the Temporal Protection system. + 2 + 2 + read-write + + + Const_00 + 0 Temporal Protection is disabled. + 0 + + + Const_11 + 1 Temporal Protection is enabled. + 1 + + + + + IS + Initial State Interrupt IS. of PSW.S bit in interrupt handle + 3 + 3 + read-write + + + TS + Initial State Trap TS. of PSW.S bit in trap handle + 4 + 4 + read-write + + + ESDIS + Emulator Space Disable. Disable the Emulator Space system + 8 + 8 + read-write + + + U1_IED + User 1 Instruction execution disable U1 IED. Disable the execution of User 1 mode instructions in User 1 IO mode. Disables User 1 ability to enable and disable interrupts. + 16 + 16 + read-write + + + U1_IOS + User 1 Peripheral access as supervisor U1 IOS. Allow User 1 mode tasks to access peripherals as if in Supervisor mode. Enables User 1 access to all peripheral registers. + 17 + 17 + read-write + + + BHALT + Boot Halt BHALT + 24 + 24 + read-write + + + Const_00 + 0 Core is not in boot halt. + 0 + + + Const_11 + 1 Core is in boot halt write to 0 will exit + 1 + + + + + + + CPU_ID + CPUx Identification Register TC1.6.2P + resetvalue={Application Reset:0x0C0C021} + 65048 + 32 + 12632097 + 4294967295 + + + MOD_REV + Revision Number MOD REV + 0 + 7 + read-only + + + Const_3232 + 20 Reset value + 32 + + + + + MOD_32B + 32 Bit Module Enable MOD 32B + 8 + 15 + read-only + + + Const_192192 + C0 A value of C0 H in this field indicates a 32 bit module with a 32 bit module ID register. + 192 + + + + + MOD + Module Identification Number MOD + 16 + 31 + read-only + + + Const_192192 + 00C0 For module identification. + 192 + + + + + + + CORE_ID + CPUx Core Identification Register + resetvalue={Application Reset:0x0} + 65052 + 32 + 0 + 4294967288 + + + CORE_ID + Core Identification Number CORE ID. The identification number of the core. + 0 + 2 + read-only + + + + + BIV + CPUx Base Interrupt Vector Table Pointer + resetvalue={Application Reset:0x0} + 65056 + 32 + 0 + 4294967295 + + + VSS + Vector Spacing Select VSS. 0 32 byte vector spacing. 1 8 Byte vector spacing. + 0 + 0 + read-write + + + BIV + Base Address of Interrupt Vector Table BIV. The address in the BIV register must be aligned to an even byte address halfword address . Because of the simple ORing of the left shifted priority number and the contents of the BIV register the alignment of the base address of the vector table must be to a power of two boundary dependent on the number of interrupt entries used. For the full range of 256 interrupt entries an alignment to an 8 KByte boundary is required. If fewer sources are used the alignment requirements are correspondingly relaxed. + 1 + 31 + read-write + + + + + BTV + CPUx Base Trap Vector Table Pointer + resetvalue={Application Reset:0x0A0000100} + 65060 + 32 + 2684354816 + 4294967295 + + + BTV + Base Address of Trap Vector Table BTV. The address in the BTV register must be aligned to an even byte address halfword address . Also due to the simple ORing of the left shifted trap identification number and the contents of the BTV register the alignment of the base address of the vector table must be to a power of two boundary. There are eight different trap classes resulting in Trap Classes from 0 to 7. The contents of BTV should therefore be set to at least a 256 byte boundary 8 Trap Classes 8 word spacing . + 1 + 31 + read-write + + + + + ISP + CPUx Interrupt Stack Pointer + resetvalue={Application Reset:0x100} + 65064 + 32 + 256 + 4294967295 + + + ISP + Interrupt Stack Pointer ISP + 0 + 31 + read-write + + + + + ICR + CPUx Interrupt Control Register + resetvalue={Application Reset:0x0} + 65068 + 32 + 0 + 4294967295 + + + CCPN + Current CPU Priority Number CCPN. The Current CPU Priority Number CCPN bit field indicates the current priority level of the CPU. It is automatically updated by hardware on entry or exit of Interrupt Service Routines ISRs and through the execution of a BISR instruction. CCPN can also be updated through an MTCR instruction. + 0 + 7 + read-write + + + IE + Global Interrupt Enable Bit IE. The interrupt enable bit globally enables the CPU service request system. Whether a service request is delivered to the CPU depends on the individual Service Request Enable Bits SRE in the SRNs and the current state of the CPU. ICR.IE is automatically updated by hardware on entry and exit of an Interrupt Service Routine ISR . ICR.IE is cleared to 0 when an interrupt is taken and is restored to the previous value when the ISR executes an RFE instruction to terminate itself. ICR.IE can also be updated through the execution of the ENABLE DISABLE MTCR and BISR instructions. + 15 + 15 + read-write + + + Const_00 + 0 Interrupt system is globally disabled + 0 + + + Const_11 + 1 Interrupt system is globally enabled + 1 + + + + + PIPN + Pending Interrupt Priority Number PIPN. A read only bit field that is updated by the ICU at the end of each interrupt arbitration process. It indicates the priority number of the pending service request. ICR.PIPN is set to 0 when no request is pending and at the beginning of each new arbitration process. ... + 16 + 23 + read-only + + + Const_00 + 00 No valid pending request. + 0 + + + Const_11 + 01 Request pending lowest priority. + 1 + + + Const_255255 + FF Request pending highest priority. + 255 + + + + + + + FCX + CPUx Free CSA List Head Pointer + resetvalue={Application Reset:0x0} + 65080 + 32 + 0 + 4294967295 + + + FCXO + FCX Offset Address Field FCXO. The FCXO and FCXS fields together form the FCX pointer which points to the next available CSA. + 0 + 15 + read-write + + + FCXS + FCX Segment Address Field FCXS. Used in conjunction with the FCXO field. + 16 + 19 + read-write + + + + + LCX + CPUx Free CSA List Limit Pointer + resetvalue={Application Reset:0x0} + 65084 + 32 + 0 + 4294967295 + + + LCXO + LCX Offset Field LCXO. The LCXO and LCXS fields form the pointer LCX which points to the last available CSA. + 0 + 15 + read-write + + + LCXS + LCX Segment Address LCXS. This field is used in conjunction with the LCXO field. + 16 + 19 + read-write + + + + + CUS_ID + CPUx Customer ID register + resetvalue={Application Reset:0x0} + 65104 + 32 + 0 + 4294967288 + + + CID + Customer ID CID. See CROSSREFERENCE for the relation between CUS ID and CORE ID for each derivative + 0 + 2 + read-only + + + + + 16 + 4 + Dy[%s] + CPUx Data General Purpose Register 0 + resetvalue={Application Reset:0x0} + 65280 + 32 + 0 + 0 + + + DATA + Data Register DATA. General purpose registers + 0 + 31 + read-write + + + + + 16 + 4 + Ay[%s] + CPUx Address General Purpose Register 0 + resetvalue={Application Reset:0x0} + 65408 + 32 + 0 + 0 + + + ADDR + Address Register ADDR. General purpose registers + 0 + 31 + read-write + + + + + CPXE_0 + CPUx Code Protection Execute Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57344 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + CPXE_1 + CPUx Code Protection Execute Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57348 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + CPXE_2 + CPUx Code Protection Execute Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57352 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + CPXE_3 + CPUx Code Protection Execute Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57356 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + DPRE_0 + CPUx Data Protection Read Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57360 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPRE_1 + CPUx Data Protection Read Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57364 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPRE_2 + CPUx Data Protection Read Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57368 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPRE_3 + CPUx Data Protection Read Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57372 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPWE_0 + CPUx Data Protection Write Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57376 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + DPWE_1 + CPUx Data Protection Write Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57380 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + DPWE_2 + CPUx Data Protection Write Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57384 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + DPWE_3 + CPUx Data Protection Write Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57388 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + CPXE_4 + CPUx Code Protection Execute Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57408 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + CPXE_5 + CPUx Code Protection Execute Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57412 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + DPRE_4 + CPUx Data Protection Read Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57424 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPRE_5 + CPUx Data Protection Read Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57428 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPWE_4 + CPUx Data Protection Write Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57440 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + DPWE_5 + CPUx Data Protection Write Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57444 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + CCTRL + CPUx Counter Control + resetvalue={Debug Reset:0x0} + 64512 + 32 + 0 + 4294967295 + + + CM + Counter Mode CM + 0 + 0 + read-write + + + Const_00 + 0 Normal Mode. + 0 + + + Const_11 + 1 Task Mode. + 1 + + + + + CE + Count Enable CE + 1 + 1 + read-write + + + Const_00 + 0 Disable the counters CCNT ICNT M1CNT M2CNT M3CNT. + 0 + + + Const_11 + 1 Enable the counters CCNT ICNT M1CNT M2CNT M3CNT. + 1 + + + + + M1 + M1CNT Configuration M1 + 2 + 4 + read-write + + + M2 + M2CNT Configuration M2 + 5 + 7 + read-write + + + M3 + M3CNT Configuration M3 + 8 + 10 + read-write + + + + + CCNT + CPUx CPU Clock Cycle Count + resetvalue={Debug Reset:0x0} + 64516 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Current Count of the CPU Clock Cycles. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + ICNT + CPUx Instruction Count + resetvalue={Debug Reset:0x0} + 64520 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Count of the Instructions Executed. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + M1CNT + CPUx Multi Count Register 1 + resetvalue={Debug Reset:0x0} + 64524 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Count of the Selected Event. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + M2CNT + CPUx Multi Count Register 2 + resetvalue={Debug Reset:0x0} + 64528 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Count of the Selected Event. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + M3CNT + CPUx Multi Count Register 3 + resetvalue={Debug Reset:0x0} + 64532 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Count of the Selected Event. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + DBGSR + CPUx Debug Status Register + resetvalue={Debug Reset:0x0} + 64768 + 32 + 0 + 4294967295 + + + DE + Debug Enable DE. Determines whether the CDC is enabled or not. + 0 + 0 + read-only + + + Const_00 + 0 The CDC is disabled. + 0 + + + Const_11 + 1 The CDC is enabled. + 1 + + + + + HALT + CPU Halt Request Status Field HALT. HALT can be set or cleared by software. HALT 0 is the actual Halt bit. HALT 1 is a mask bit to specify whether or not HALT 0 is to be updated on a software write. HALT 1 is always read as 0. HALT 1 must be set to 1 in order to update HALT 0 by software R read W write . + 1 + 2 + read-write + + + Const_00 + 00 R CPU running. W HALT 0 unchanged. + 0 + + + Const_11 + 01 R CPU halted. W HALT 0 unchanged. + 1 + + + Const_22 + 10 R Not Applicable. W reset HALT 0 . + 2 + + + Const_33 + 11 R Not Applicable. W If DBGSR.DE 1 The CDC is enabled set HALT 0 . If DBGSR.DE 0 The CDC is not enabled HALT 0 is left unchanged. + 3 + + + + + SIH + Suspend in Halt SIH. State of the Suspend In signal. + 3 + 3 + read-only + + + Const_00 + 0 The Suspend In signal is negated. The CPU is not in Halt Mode except when the Halt mechanism is set following a Debug Event or a write to DBGSR.HALT . + 0 + + + Const_11 + 1 The Suspend In signal is asserted. The CPU is in Halt Mode. + 1 + + + + + SUSP + Current State of the Core Suspend Out Signal SUSP + 4 + 4 + read-write + + + Const_00 + 0 Core suspend out inactive. + 0 + + + Const_11 + 1 Core suspend out active. + 1 + + + + + PREVSUSP + Previous State of Core Suspend Out Signal PREVSUSP. Updated when a Debug Event causes a hardware update of DBGSR.SUSP. This field is not updated for writes to DBGSR.SUSP. + 6 + 6 + read-only + + + Const_00 + 0 Previous core suspend out inactive. + 0 + + + Const_11 + 1 Previous core suspend out active. + 1 + + + + + PEVT + Posted Event PEVT + 7 + 7 + read-write + + + Const_00 + 0 No posted event. + 0 + + + Const_11 + 1 Posted event. + 1 + + + + + + + EXEVT + CPUx External Event Register + resetvalue={Debug Reset:0x0} + 64776 + 32 + 0 + 4294967295 + + + EVTA + Event Associated EVTA. Specifies the Debug Action associated with the Debug Event + 0 + 2 + read-write + + + Const_00 + 000 BOD 0 Disabled. BOD 1 Disabled. + 0 + + + Const_11 + 001 BOD 0 Pulse BRKOUT Signal. BOD 1 None. + 1 + + + Const_22 + 010 BOD 0 Halt and pulse BRKOUT Signal. BOD 1 Halt. + 2 + + + Const_33 + 011 BOD 0 Breakpoint trap and pulse. BRKOUT Signal. BOD 1 Breakpoint trap. + 3 + + + Const_44 + 100 BOD 0 Breakpoint interrupt 0 and pulse BRKOUT Signal. BOD 1 Breakpoint interrupt 0. + 4 + + + Const_55 + 101 BOD 0 If implemented breakpoint interrupt 1 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 1. If not implemented None. + 5 + + + Const_66 + 110 BOD 0 If implemented breakpoint interrupt 2 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 2. If not implemented None. + 6 + + + Const_77 + 111 BOD 0 If implemented breakpoint interrupt 3 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 3. If not implemented None. + 7 + + + + + BBM + Break Before Make BBM or Break After Make BAM Selection BBM + 3 + 3 + read-write + + + Const_00 + 0 Break after make BAM . + 0 + + + Const_11 + 1 Break before make BBM . + 1 + + + + + BOD + Breakout Disable BOD + 4 + 4 + read-write + + + Const_00 + 0 BRKOUT signal asserted according to the Debug Action specified in the EVTA field. + 0 + + + Const_11 + 1 BRKOUT signal not asserted. This takes priority over any assertion generated by the EVTA field. + 1 + + + + + SUSP + CDC Suspend Out Signal State SUSP. Value to be assigned to the CDC suspend out signal when the Debug Event is raised. + 5 + 5 + read-write + + + CNT + Counter CNT. When this event occurs adjust the control of the performance counters in task mode as follows + 6 + 7 + read-write + + + Const_00 + 00 No change. + 0 + + + Const_11 + 01 Start the performance counters. + 1 + + + Const_22 + 10 Stop the performance counters. + 2 + + + Const_33 + 11 Toggle the performance counter control i.e. start it if it is currently stopped stop it if it is currently running . + 3 + + + + + + + CREVT + CPUx Core Register Access Event + resetvalue={Debug Reset:0x0} + 64780 + 32 + 0 + 4294967295 + + + EVTA + Event Associated EVTA. Debug Action associated with the Debug Event + 0 + 2 + read-write + + + Const_00 + 000 BOD 0 Disabled. BOD 1 Disabled. + 0 + + + Const_11 + 001 BOD 0 Pulse BRKOUT Signal. BOD 1 None. + 1 + + + Const_22 + 010 BOD 0 Halt and pulse BRKOUT Signal. BOD 1 Halt. + 2 + + + Const_33 + 011 BOD 0 Breakpoint trap and pulse BRKOUT Signal. BOD 1 Breakpoint trap. + 3 + + + Const_44 + 100 BOD 0 Breakpoint interrupt 0 and pulse BRKOUT Signal. BOD 1 Breakpoint interrupt 0. + 4 + + + Const_55 + 101 BOD 0 If implemented breakpoint interrupt 1 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 1. If not implemented None. + 5 + + + Const_66 + 110 BOD 0 If implemented breakpoint interrupt 2 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 2. If not implemented None. + 6 + + + Const_77 + 111 BOD 0 If implemented breakpoint interrupt 3 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 3. If not implemented None. + 7 + + + + + BBM + Break Before Make BBM or Break After Make BAM Selection BBM + 3 + 3 + read-write + + + Const_00 + 0 Break after make BAM . + 0 + + + Const_11 + 1 Break before make BBM . + 1 + + + + + BOD + Breakout Disable BOD + 4 + 4 + read-write + + + Const_00 + 0 BRKOUT signal asserted according to the action specified in the EVTA field. + 0 + + + Const_11 + 1 BRKOUT signal not asserted. This takes priority over any assertion generated by the EVTA field. + 1 + + + + + SUSP + CDC Suspend Out Signal State SUSP. Value to be assigned to the CDC suspend out signal when the Debug Event is raised. + 5 + 5 + read-write + + + CNT + Counter CNT. When this event occurs adjust the control of the performance counters in task mode as follows + 6 + 7 + read-write + + + Const_00 + 00 No change. + 0 + + + Const_11 + 01 Start the performance counters. + 1 + + + Const_22 + 10 Stop the performance counters. + 2 + + + Const_33 + 11 Toggle the performance counter control i.e. start it if it is currently stopped stop it if it is currently running . + 3 + + + + + + + SWEVT + CPUx Software Debug Event + resetvalue={Debug Reset:0x0} + 64784 + 32 + 0 + 4294967295 + + + EVTA + Event Associated EVTA. Debug Action associated with the Debug Event + 0 + 2 + read-write + + + Const_00 + 000 BOD 0 Disabled. BOD 1 Disabled. + 0 + + + Const_11 + 001 BOD 0 Pulse BRKOUT Signal. BOD 1 None. + 1 + + + Const_22 + 010 BOD 0 Halt and pulse BRKOUT Signal. BOD 1 Halt. + 2 + + + Const_33 + 011 BOD 0 Breakpoint trap and pulse BRKOUT Signal. BOD 1 Breakpoint trap. + 3 + + + Const_44 + 100 BOD 0 Breakpoint interrupt 0 and pulse BRKOUT Signal. BOD 1 Breakpoint interrupt 0. + 4 + + + Const_55 + 101 BOD 0 If implemented breakpoint interrupt 1 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 1. If not implemented None. + 5 + + + Const_66 + 110 BOD 0 If implemented breakpoint interrupt 2 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 2. If not implemented None. + 6 + + + Const_77 + 111 BOD 0 If implemented breakpoint interrupt 3 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 3. If not implemented None. + 7 + + + + + BBM + Break Before Make BBM or Break After Make BAM Selection BBM + 3 + 3 + read-write + + + Const_00 + 0 Break after make BAM . + 0 + + + Const_11 + 1 Break before make BBM . + 1 + + + + + BOD + Breakout Disable BOD + 4 + 4 + read-write + + + Const_00 + 0 BRKOUT signal asserted according to the action specified in the EVTA field. + 0 + + + Const_11 + 1 BRKOUT signal not asserted. This takes priority over any assertion generated by the EVTA field. + 1 + + + + + SUSP + CDC Suspend Out Signal State SUSP. Value to be assigned to the CDC suspend out signal when the event is raised. + 5 + 5 + read-write + + + CNT + Counter CNT. When this event occurs adjust the control of the performance counters in task mode as follows + 6 + 7 + read-write + + + Const_00 + 00 No change. + 0 + + + Const_11 + 01 Start the performance counters. + 1 + + + Const_22 + 10 Stop the performance counters. + 2 + + + Const_33 + 11 Toggle the performance counter control i.e. start it if it is currently stopped stop it if it is currently running . + 3 + + + + + + + TRIG_ACC + CPUx TriggerAddressx + resetvalue={Debug Reset:0x0} + 64816 + 32 + 0 + 4294967295 + + + T0 + Trigger 0 T0. active since last cleared + 0 + 0 + read-only + + + T1 + Trigger 1 T1. active since last cleared + 1 + 1 + read-only + + + T2 + Trigger 2 T2. active since last cleared + 2 + 2 + read-only + + + T3 + Trigger 3 T3. active since last cleared + 3 + 3 + read-only + + + T4 + Trigger 4 T4. active since last cleared + 4 + 4 + read-only + + + T5 + Trigger 5 T5. active since last cleared + 5 + 5 + read-only + + + T6 + Trigger 6 T6. active since last cleared + 6 + 6 + read-only + + + T7 + Trigger 7 T7. active since last cleared + 7 + 7 + read-only + + + + + DMS + CPUx Debug Monitor Start Address + resetvalue={Application Reset:0x0} + 64832 + 32 + 0 + 0 + + + DMSValue + Debug Monitor Start Address DMSValue. The address at which monitor code execution begins when a breakpoint trap is taken. + 1 + 31 + read-write + + + + + DCX + CPUx Debug Context Save Area Pointer + resetvalue={Application Reset:0x0} + 64836 + 32 + 0 + 0 + + + DCXValue + Debug Context Save Area Pointer DCXValue. Address where the debug context is stored following a breakpoint trap. + 6 + 31 + read-write + + + + + DBGTCR + CPUx Debug Trap Control Register + resetvalue={Application Reset:0x1} + 64840 + 32 + 1 + 4294967295 + + + DTA + Debug Trap Active Bit DTA. A breakpoint trap may only be taken in the condition DTA 0. Taking a breakpoint trap sets the DTA bit to one. Further breakpoint traps are therefore disabled until such time as the breakpoint trap handler clears the DTA bit or until the breakpoint trap handler terminates with a RFM. + 0 + 0 + read-write + + + Const_00 + 0 No breakpoint trap is active. + 0 + + + Const_11 + 1 A breakpoint Trap is active + 1 + + + + + + + SEGEN + CPUx SRI Error Generation Register + resetvalue={Application Reset:0x0} + 4144 + 32 + 0 + 4294967295 + + + ADFLIP + Address ECC Bit Flip ADFLIP. SRI address ECC Bits to be flipped on the next read or write transaction from the DMI when enabled by AE. + 0 + 7 + read-write + + + Const_00 + 0 No Flip + 0 + + + Const_11 + 1 Flip + 1 + + + + + ADTYPE + Type of error ADTYPE + 8 + 9 + read-write + + + Const_00 + 00 Data Master Address Phase + 0 + + + Const_11 + 01 Data Master Write Data + 1 + + + Const_22 + 10 Data Slave Read Data + 2 + + + + + AE + Activate Error Enable AE. Enabled the selective inverting of SRI ECC packet bits defined by ADFLIP. This bit will be cleared by hardware after the next SRI read or write transaction from the DMI. + 31 + 31 + read-write + + + Const_00 + 0 Not Enabled + 0 + + + Const_11 + 1 Enabled + 1 + + + + + + + DCON2 + CPUx Data Control Register 2 + resetvalue={Application Reset:0x0} + 36864 + 32 + 0 + 0 + + + DCACHE_SZE + Data Cache Size DCACHE SZE. In KBytes + 0 + 15 + read-only + + + DSCRATCH_SZE + Data Scratch Size DSCRATCH SZE. In KBytes + 16 + 31 + read-only + + + + + DSTR + CPUx Data Synchronous Trap Register + resetvalue={Application Reset:0x0} + 36880 + 32 + 0 + 4294967295 + + + SRE + Scratch Range Error SRE. A scratch Range Error occurs whenever an access to the data scratch is outside the range of the SRAM. + 0 + 0 + read-write + + + GAE + Global Address Error GAE. Load or store to local code scratch address outside of the lower 1MByte. + 1 + 1 + read-write + + + LBE + Load Bus Error LBE. A Load Bus Error will be set whenever the SRI flags an error due a load from external memory. + 2 + 2 + read-write + + + DRE + Local DLMU Range Error DRE. A DLMU Range Error occurs whenever an access to the local DLMU region is outside the physically implemented memory. + 3 + 3 + read-write + + + CRE + Cache Refill Error CRE. A Cache Refill Error will be set whenever the SRI flags an error due a cache refill from external memory. + 6 + 6 + read-write + + + DTME + DTAG MSIST Error DTME. Access to memory mapped DTAG range outside of physically implemented memory. + 14 + 14 + read-write + + + LOE + Load Overlay Error LOE. Load to invalid overlay address. + 15 + 15 + read-write + + + SDE + Segment Difference Error SDE. Load or store access where base address is in different segment to access address. + 16 + 16 + read-write + + + SCE + Segment Crossing Error SCE. Load or store access across segment boundary. + 17 + 17 + read-write + + + CAC + CSFR Access Error CAC. Load or store to local CSFR space. + 18 + 18 + read-write + + + MPE + Memory Protection Error MPE. Data access violating memory protection. + 19 + 19 + read-write + + + CLE + Context Location Error CLE. Context operation to invalid location. + 20 + 20 + read-write + + + ALN + Alignment Error ALN. Data access causing alignment error. + 24 + 24 + read-write + + + + + DATR + CPUx Data Asynchronous Trap Register + resetvalue={Application Reset:0x0} + 36888 + 32 + 0 + 4294967295 + + + SBE + Store Bus Error SBE + 3 + 3 + read-write + + + CWE + Cache Writeback Error CWE + 9 + 9 + read-write + + + CFE + Cache Flush Error CFE + 10 + 10 + read-write + + + SOE + Store Overlay Error SOE + 14 + 14 + read-write + + + + + DEADD + CPUx Data Error Address Register + resetvalue={Application Reset:0x0} + 36892 + 32 + 0 + 4294967295 + + + ERROR_ADDRESS + Error Address ERROR ADDRESS + 0 + 31 + read-only + + + + + DCON0 + CPUx Data Memory Control Register + resetvalue={Application Reset:0x2} + 36928 + 32 + 2 + 4294967295 + + + DCBYP + Data Cache Bypass DCBYP + 1 + 1 + read-write + + + Const_00 + 0 DCache DRB enabled + 0 + + + Const_11 + 1 DCache DRB Bypass disabled + 1 + + + + + + + PSTR + CPUx Program Synchronous Trap Register + resetvalue={Application Reset:0x0} + 37376 + 32 + 0 + 4294967295 + + + FRE + Fetch Range Error FRE. A Fetch Range Error occurs whenever an access to the Program Scratch is outside the range of the SRAM. + 0 + 0 + read-write + + + FBE + Fetch Bus Error FBE. A Fetch bus error will be set whenever the SRI flags an error due a fetch from external memory. This will be set for both direct fetches from the bus and for cache refills. + 2 + 2 + read-write + + + FPE + Fetch Peripheral Error FPE. A Fetch peripheral error will be flagged whenever a fetch is attempted to peripheral space. + 12 + 12 + read-write + + + FME + Fetch MSIST Error FME. During SIST mode a fetch from the PTAG will cause a PSE trap to occur. + 14 + 14 + read-write + + + + + PCON1 + CPUx Program Control 1 + resetvalue={Application Reset:0x0} + 37380 + 32 + 0 + 4294967295 + + + PCINV + Program Cache Invalidate PCINV + 0 + 0 + read-write + + + Const_00 + 0 Write No effect normal instruction cache operation. Read Normal operation instruction cache available + 0 + + + Const_11 + 1 Write Initiate invalidation of entire instruction cache. Read Instruction cache invalidation in progress. Instruction cache unavailable. + 1 + + + + + PBINV + Program Buffer Invalidate PBINV. Write Operation This field returns 0 when read. + 1 + 1 + read-write + + + Const_00 + 0 Write No effect. Normal program line buffer operation. + 0 + + + Const_11 + 1 Write Invalidate the program line buffer. + 1 + + + + + + + PCON2 + CPUx Program Control 2 + resetvalue={Application Reset:0x0} + 37384 + 32 + 0 + 0 + + + PCACHE_SZE + Program Cache Size ICACHE in KBytes PCACHE SZE. In KBytes + 0 + 15 + read-only + + + PSCRATCH_SZE + Program Scratch Size in KBytes PSCRATCH SZE. In KBytes + 16 + 31 + read-only + + + + + PCON0 + CPUx Program Control 0 + resetvalue={Application Reset:0x2} + 37388 + 32 + 2 + 4294967295 + + + PCBYP + Program Cache Bypass PCBYP + 1 + 1 + read-write + + + Const_00 + 0 Cache enabled + 0 + + + Const_11 + 1 Cache bypass disabled + 1 + + + + + + + + + CPU2 + 100 + CPU + CPU0 + 0 + + 0 + 65472 + registers + + + + 18 + 8 + DPR[%s] + DPR + 49152 + + DPRy_L + CPUx Data Protection Range 0 Lower Bound Register + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + LOWBND + DPRy Lower Boundary Address LOWBND + 3 + 31 + read-write + + + + + DPRy_U + CPUx Data Protection Range 0 Upper Bound Register + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + UPPBND + DPRy Upper Boundary Address UPPBND + 3 + 31 + read-write + + + + + + 10 + 8 + CPR[%s] + CPR + 53248 + + CPRy_L + CPUx Code Protection Range 0 Lower Bound Register + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + LOWBND + CPRy Lower Boundary Address LOWBND + 5 + 31 + read-write + + + + + CPRy_U + CPUx Code Protection Range 0 Upper Bound Register + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + UPPBND + CPR0 m Upper Boundary Address UPPBND + 5 + 31 + read-write + + + + + + TPS + TPS + 58368 + + CON + CPUx Temporal Protection System Control Register + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + TEXP0 + Timer0 Expired Flag TEXP0. Set when the corresponding timer expires. Cleared on any write to the TIMER0 register. + 0 + 0 + read-only + + + TEXP1 + Timer1 Expired Flag TEXP1. Set when the corresponding timer expires. Cleared on any write to the TIMER1 register. + 1 + 1 + read-only + + + TEXP2 + Timer1 Expired Flag TEXP2. Set when the corresponding timer expires. Cleared on any write to the TIMER1 register. + 2 + 2 + read-only + + + TTRAP + Temporal Protection Trap TTRAP. If set indicates that a TAE trap has been requested. Any subsequent TAE traps are disabled. A write clears the flag and re enables TAE traps. + 16 + 16 + read-only + + + + + 3 + 4 + TIMER[%s] + CPUx Temporal Protection System Timer Register 0 + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + Timer + Temporal Protection Timer Timer. Writing zero de activates the Timer. Writing a non zero value starts the Timer. Any write clears the corresponding TPS CON.TEXP flag. Read returns the current Timer value. + 0 + 31 + read-write + + + + + + TPS_EXTIM + TPS EXTIM + 58432 + + ENTRY_LVAL + CPUx Exception Entry Timer Load Value + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + ENTRY_LVAL + Exception Entry Timer Load value ENTRY LVAL. Value loaded into the exception entry timer on detection of an enabled exception. Bits 3 0 are constrained to be 0 + 4 + 11 + read-write + + + + + ENTRY_CVAL + CPUx Exception Entry Timer Current Value + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + ENTRY_CVAL + Exception Entry Timer Current Value ENTRY CVAL. Current value of the exception entry timer. + 0 + 11 + read-only + + + + + EXIT_LVAL + CPUx Exception Exit Timer Load Value + resetvalue={Application Reset:0x0} + 8 + 32 + 0 + 4294967295 + + + EXIT_LVAL + Exception Exit Timer Load value EXIT LVAL. Value loaded into the exception exit timer on detection of an enabled exception. Bits 3 0 are constrained to be 0 + 4 + 23 + read-write + + + + + EXIT_CVAL + CPUx Exception Exit Timer Current Value + resetvalue={Application Reset:0x0} + 12 + 32 + 0 + 4294967295 + + + EXIT_CVAL + Exception Exit Timer Current Value EXIT CVAL. Current value of the exception exit timer. + 0 + 23 + read-only + + + + + CLASS_EN + CPUx Exception Timer Class Enable Register + resetvalue={Application Reset:0x0} + 16 + 32 + 0 + 4294967295 + + + EXTIM_CLASS_EN + Exception Timer Class Enables EXTIM CLASS EN. Trap Class enables for exception timer. + 0 + 7 + read-write + + + + + STAT + CPUx Exception Timer Status Register + resetvalue={Application Reset:0x0} + 20 + 32 + 0 + 4294967295 + + + EXIT_TIN + Exception Exit Timer TIN EXIT TIN. Exception Exit Timer TIN of triggering trap. + 0 + 7 + read-write + + + EXIT_CLASS + Exception Exit Timer Class EXIT CLASS. Exception exit Timer Class of triggering trap. + 8 + 10 + read-write + + + EXIT_AT + Exception Exit Timer Alarm Triggered EXIT AT. Exception Exit Timer Alarm triggered sticky bit. Alarm triggered since last cleared. + 15 + 15 + read-only + + + ENTRY_TIN + Exception Entry Timer TIN ENTRY TIN. Exception Entry Timer TIN of triggering trap. + 16 + 23 + read-write + + + ENTRY_CLASS + Exception Entry Timer Class ENTRY CLASS. Exception Entry Timer Class of triggering trap. + 24 + 26 + read-write + + + ENTRY_AT + Exception Entry Timer Alarm Triggered ENTRY AT. Exception Entry Timer Alarm triggered sticky bit. Alarm triggered since last cleared. + 31 + 31 + read-only + + + + + FCX + CPUx Exception Timer FCX Register + resetvalue={Application Reset:0x0} + 24 + 32 + 0 + 4294967295 + + + EXIT_FCX + Exception Exit Timer FCX EXIT FCX. Exception Exit Timer FCX of triggering trap. + 0 + 19 + read-only + + + + + + FPU_TRAP + FPU TRAP + 40960 + + CON + CPUx Trap Control Register + resetvalue={Application Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + TST + Trap Status TST + 0 + 0 + read-only + + + Const_00 + 0 No instruction captured. The next enabled exception will cause the exceptional instruction to be captured. + 0 + + + Const_11 + 1 Instruction captured. No further enabled exceptions will be captured until TST is cleared. + 1 + + + + + TCL + Trap Clear TCL. Read always reads as 0. + 1 + 1 + write-only + + + Const_00 + 0 No effect. + 0 + + + Const_11 + 1 Clears the trapped instruction TST will be negated . + 1 + + + + + RM + Captured Rounding Mode RM. The rounding mode of the captured instruction. Only valid when TST is asserted. Note that this is the rounding mode supplied to the FPU for the exceptional instruction. UPDFL instructions may cause a trap and change the rounding mode. In this case the RM bits capture the input rounding mode + 8 + 9 + read-only + + + FXE + FX Trap Enable FXE. When set an instruction generating an FX exception will trigger a trap. + 18 + 18 + read-write + + + FUE + FU Trap Enable FUE. When set an instruction generating an FU exception will trigger a trap. + 19 + 19 + read-write + + + FZE + FZ Trap Enable FZE. When set an instruction generating an FZ exception will trigger a trap. + 20 + 20 + read-write + + + FVE + FV Trap Enable FVE. When set an instruction generating an FV exception will trigger a trap. + 21 + 21 + read-write + + + FIE + FI Trap Enable FIE. When set an instruction generating an FI exception will trigger a trap. + 22 + 22 + read-write + + + FX + Captured FX FX. Asserted if the captured instruction asserted FX. Only valid when TST is asserted. + 26 + 26 + read-only + + + FU + Captured FU FU. Asserted if the captured instruction asserted FU. Only valid when TST is asserted. + 27 + 27 + read-only + + + FZ + Captured FZ FZ. Asserted if the captured instruction asserted FZ. Only valid when TST is asserted + 28 + 28 + read-only + + + FV + Captured FV FV. Asserted if the captured instruction asserted FV. Only valid when TST is asserted + 29 + 29 + read-only + + + FI + Captured FI FI. Asserted if the captured instruction asserted FI. Only valid when TST is asserted + 30 + 30 + read-only + + + + + PC + CPUx Trapping Instruction Program Counter Register + resetvalue={Application Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + PC + Captured Program Counter PC. The program counter virtual address of the captured instruction. Only valid when FPU TRAP CON.TST is asserted. + 0 + 31 + read-only + + + + + OPC + CPUx Trapping Instruction Opcode Register + resetvalue={Application Reset:0x0} + 8 + 32 + 0 + 4294967295 + + + OPC + Captured Opcode OPC. The secondary opcode of the captured instruction. When FPU TRAP OPC.FMT 0 only bits 3 0 are defined. OPC is valid only when FPU TRAP CON.TST is asserted. + 0 + 7 + read-only + + + FMT + Captured Instruction Format FMT. The format of the captured instruction s opcode. Only valid when FPU TRAP CON.TST is asserted. + 8 + 8 + read-only + + + Const_00 + 0 RRR + 0 + + + Const_11 + 1 RR + 1 + + + + + DREG + Captured Destination Register DREG. The destination register of the captured instruction. ... Only valid when FPU TRAP CON.TST is asserted. + 16 + 19 + read-only + + + Const_00 + 0 Data general purpose register 0. + 0 + + + Const_1515 + F Data general purpose register 15. + 15 + + + + + + + SRC1 + CPUx Trapping Instruction Operand Register + resetvalue={Application Reset:0x0} + 16 + 32 + 0 + 4294967295 + + + SRC1 + Captured SRC1 Operand SRC1. The SRC1 operand of the captured instruction. Only valid when FPU TRAP CON.TST is asserted. + 0 + 31 + read-only + + + + + SRC2 + CPUx Trapping Instruction Operand Register + resetvalue={Application Reset:0x0} + 20 + 32 + 0 + 4294967295 + + + SRC2 + Captured SRC2 Operand SRC2. The SRC2 operand of the captured instruction. Only valid when FPU TRAP CON.TST is asserted. + 0 + 31 + read-only + + + + + SRC3 + CPUx Trapping Instruction Operand Register + resetvalue={Application Reset:0x0} + 24 + 32 + 0 + 4294967295 + + + SRC3 + Captured SRC3 Operand SRC3. The SRC3 operand of the captured instruction. Only valid when FPU TRAP CON.TST is asserted. + 0 + 31 + read-only + + + + + + 8 + 8 + TR[%s] + Trigger + 61440 + + TRiEVT + CPUx Trigger Event 0 + resetvalue={Debug Reset:0x0} + 0 + 32 + 0 + 4294967295 + + + EVTA + Event Associated EVTA. Specifies the Debug Action associated with the Debug Event + 0 + 2 + read-write + + + Const_00 + 000 BOD 0 Disabled. BOD 1 Disabled. + 0 + + + Const_11 + 001 BOD 0 Pulse BRKOUT Signal. BOD 1 None. + 1 + + + Const_22 + 010 BOD 0 Halt and pulse BRKOUT Signal. BOD 1 Halt. + 2 + + + Const_33 + 011 BOD 0 Breakpoint trap and pulse BRKOUT Signal. BOD 1 Breakpoint trap. + 3 + + + Const_44 + 100 BOD 0 Breakpoint interrupt 0 and pulse BRKOUT Signal. BOD 1 Breakpoint interrupt 0. + 4 + + + Const_55 + 101 BOD 0 If implemented breakpoint interrupt 1 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 1. If not implemented None. + 5 + + + Const_66 + 110 BOD 0 If implemented breakpoint interrupt 2 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 2. If not implemented None. + 6 + + + Const_77 + 111 BOD 0 If implemented breakpoint interrupt 3 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 3. If not implemented None. + 7 + + + + + BBM + Break Before Make BBM or Break After Make BAM Selection BBM. Code triggers BBM or BAM selection. Data access and data code combination access triggers can only create BAM Debug Events. When these triggers occur TRnEVT.BBM is ignored. + 3 + 3 + read-write + + + Const_00 + 0 Code only triggers Break After Make BAM . + 0 + + + Const_11 + 1 Code only triggers Break Before Make BBM . + 1 + + + + + BOD + Breakout Disable BOD + 4 + 4 + read-write + + + Const_00 + 0 BRKOUT signal asserted according to the action specified in the EVTA field. + 0 + + + Const_11 + 1 BRKOUT signal not asserted. This takes priority over any assertion generated by the EVTA field. + 1 + + + + + SUSP + CDC Suspend Out Signal State SUSP. Value to be assigned to the CDC suspend out signal when the Debug Event is raised. + 5 + 5 + read-write + + + CNT + Counter CNT. When this event occurs adjust the control of the performance counters in task mode as follows + 6 + 7 + read-write + + + Const_00 + 00 No change. + 0 + + + Const_11 + 01 Start the performance counters. + 1 + + + Const_22 + 10 Stop the performance counters. + 2 + + + Const_33 + 11 Toggle the performance counter control i.e. start it if it is currently stopped stop it if it is currently running . + 3 + + + + + TYP + Input Selection TYP + 12 + 12 + read-write + + + Const_00 + 0 Address + 0 + + + Const_11 + 1 PC + 1 + + + + + RNG + Compare Type RNG. Once an even numbered comparator has been set to range the EVTR settings of its associated upper neighbour will be ignored. + 13 + 13 + read-write + + + Const_11 + 1 Range + 1 + + + Const_00 + 0 Equality + 0 + + + + + ASI_EN + Enable ASI Comparison ASI EN + 15 + 15 + read-write + + + Const_00 + 0 No ASI comparison performed. Debug Trigger is valid for all processes. + 0 + + + Const_11 + 1 Enable ASI comparison. Debug Events are only triggered when the current process ASI matches TRnEVT.ASI. + 1 + + + + + ASI + Address Space Identifier ASI. The ASI of the Debug Trigger process. + 16 + 20 + read-write + + + AST + Address Store AST. Used in conjunction with TYP 0 + 27 + 27 + read-write + + + ALD + Address Load ALD. Used in conjunction with TYP 0 + 28 + 28 + read-write + + + + + TRiADR + CPUx Trigger Address 0 + resetvalue={Debug Reset:0x0} + 4 + 32 + 0 + 4294967295 + + + ADDR + Comparison Address ADDR. For PC comparison bit 0 is always zero. + 0 + 31 + read-write + + + + + + SMACON + CPUx SIST Mode Access Control Register + resetvalue={Application Reset:0x0} + 36876 + 32 + 0 + 4294967295 + + + IODT + In Order Data Transactions IODT + 24 + 24 + read-write + + + Const_00 + 0 Normal operation Non dependent loads bypass stores. + 0 + + + Const_11 + 1 In order operation Loads always flush preceding stores processor store buffer disabled. + 1 + + + + + + + DIEAR + CPUx Data Integrity Error Address Register + resetvalue={Application Reset:0x0} + 36896 + 32 + 0 + 4294967295 + + + TA + Transaction Address TA. Physical address being accessed by operation that encountered data integrity error. + 0 + 31 + read-only + + + + + DIETR + CPUx Data Integrity Error Trap Register + resetvalue={Application Reset:0x0} + 36900 + 32 + 0 + 4294967295 + + + IED + Integrity Error Detected IED + 0 + 0 + read-write + + + Const_00 + 0 Write Clear IED bit re enable DIETR and DIEAR update. Read No data integrity error condition occurred + 0 + + + Const_11 + 1 Write No Effect. Read Data integrity error condition detected. DIETR and DIEAR contents valid further DIETR and DIEAR updates disabled.. + 1 + + + + + IE_T + Integrity Error Tag Memory IE T + 1 + 1 + read-only + + + IE_C + Integrity Error Cache Memory IE C + 2 + 2 + read-only + + + IE_S + Integrity Error Scratchpad Memory IE S + 3 + 3 + read-only + + + IE_BI + Integrity Error Bus Interface IE BI + 4 + 4 + read-only + + + E_INFO + Error Information E INFO. If IE BS 1 Bus Master Tag ID of requesting masterIf IE C 1 Cache way. + 5 + 10 + read-only + + + IE_UNC + Dual Bit Error Detected IE UNC + 11 + 11 + read-only + + + IE_SP + Safety Protection Error Detected IE SP + 12 + 12 + read-only + + + IE_BS + Bus Slave Access Indicator IE BS + 13 + 13 + read-only + + + IE_DLMU + Integrity Error DLMU IE DLMU + 14 + 14 + read-only + + + IE_LPB + Integrity Error Local Pflash Bank IE LPB + 15 + 15 + read-only + + + IE_MTMV + Memory Test Mode Violation detected IE MTMV + 16 + 16 + read-only + + + + + PIEAR + CPUx Program Integrity Error Address Register + resetvalue={Application Reset:0x0} + 37392 + 32 + 0 + 4294967295 + + + TA + Transaction Address TA. Physical address being accessed by operation that encountered program integrity error. + 0 + 31 + read-only + + + + + PIETR + CPUx Program Integrity Error Trap Register + resetvalue={Application Reset:0x0} + 37396 + 32 + 0 + 4294967295 + + + IED + Integrity Error Detected IED + 0 + 0 + read-write + + + Const_00 + 0 Write Clear IED bit re enable PIETR and PIEAR update. Read No data integrity error condition occurred + 0 + + + Const_11 + 1 Write No Effect. Read Data integrity error condition detected. PIETR and PIEAR contents valid further PIETR and PIEAR updates disabled.. + 1 + + + + + IE_T + Integrity Error TAG Memory IE T + 1 + 1 + read-only + + + IE_C + Integrity Error Cache Memory IE C + 2 + 2 + read-only + + + IE_S + Integrity Error Scratchpad Memory IE S + 3 + 3 + read-only + + + IE_BI + Integrity Error Bus Interface IE BI + 4 + 4 + read-only + + + E_INFO + Error Information E INFO. If IE BS 1 Bus Master Tag ID of requesting masterIf IE C 1 Cache way. + 5 + 10 + read-only + + + IE_UNC + Integrity Error Uncorrectable Error Detected IE UNC + 11 + 11 + read-only + + + IE_SP + Safety Protection Error Detected IE SP + 12 + 12 + read-only + + + IE_BS + Bus Slave Access Indicator IE BS + 13 + 13 + read-only + + + IE_ADDR + Address Phase error detected at SRI slave interface IE ADDR + 14 + 14 + read-only + + + IE_LPB + Integrity Error Local Pflash bank IE LPB + 15 + 15 + read-only + + + IE_MTMV + Memory Test Mode Violation detected IE MTMV + 16 + 16 + read-only + + + + + TASK_ASI + CPUx Task Address Space Identifier Register + resetvalue={Application Reset:0x1F} + 32772 + 32 + 31 + 4294967295 + + + ASI + Address Space Identifier ASI. The ASI register contains the Address Space Identifier of the current process. + 0 + 4 + read-write + + + + + PMA0 + CPUx Data Access CacheabilityRegister + resetvalue={Application Reset:0x300} + 33024 + 32 + 768 + 4294967295 + + + DAC + Data Access Cacheability Segments FHto 0H DAC. Note segments F H E H D H and A H are constrained to be non cacheable + 0 + 15 + read-write + + + + + PMA1 + CPUx Code Access CacheabilityRegister + resetvalue={Application Reset:0x300} + 33028 + 32 + 768 + 4294967295 + + + CAC + Code Access Cacheability Segments FH 0H CAC. Note Segments F H E H C H A H are constrained to be non cacheable + 0 + 15 + read-write + + + + + PMA2 + CPUx Peripheral Space Identifier register + resetvalue={Application Reset:0x0C000} + 33032 + 32 + 49152 + 4294967295 + + + PSI + Peripheral Space Identifier Segments FH 0H PSI + 0 + 15 + read-only + + + + + COMPAT + CPUx Compatibility Control Register + resetvalue={Application Reset:0x0FFFFFFFF} + 37888 + 32 + 4294967295 + 4294967295 + + + RM + Rounding Mode Compatibility RM + 3 + 3 + read-write + + + Const_00 + 0 PSW.RM not restored by RET. + 0 + + + Const_11 + 1 PSW.RM restored by RET TC1.3 behavior . + 1 + + + + + SP + SYSCON Safety Protection Mode Compatibility SP + 4 + 4 + read-write + + + Const_00 + 0 SYSCON 31 1 safety endinit protected. + 0 + + + Const_11 + 1 SYSCON 31 1 not safety endinit protected TC1.3 behavior . + 1 + + + + + + + PCXI + CPUx Previous Context Information Register + resetvalue={Application Reset:0x0} + 65024 + 32 + 0 + 4294967295 + + + PCXO + Previous Context Pointer Offset Field PCXO. The PCXO and PCXS fields form the pointer PCX which points to the CSA of the previous context. + 0 + 15 + read-write + + + PCXS + Previous Context Pointer Segment Address PCXS. Contains the segment address portion of the PCX. This field is used in conjunction with the PCXO field. + 16 + 19 + read-write + + + UL + Upper or Lower Context Tag UL. Identifies the type of context saved. If the type does not match the type expected when a context restore operation is performed a trap is generated. + 20 + 20 + read-write + + + Const_00 + 0 Lower Context + 0 + + + Const_11 + 1 Upper Context + 1 + + + + + PIE + Previous Interrupt Enable PIE. Indicates the state of the interrupt enable bit ICR.IE for the interrupted task. + 21 + 21 + read-write + + + PCPN + Previous CPU Priority Number PCPN. Contains the priority level number of the interrupted task. + 22 + 29 + read-write + + + + + PSW + CPUx Program Status Word + resetvalue={Application Reset:0x0B80} + 65028 + 32 + 2944 + 4294967295 + + + CDC + Call Depth Counter CDC. Consists of two variable width subfields. The first subfield consists of a string of zero or more initial 1 bits terminated by the first 0 bit. The remaining bits form the second subfield CDC.COUNT which constitutes the Call Depth Count value. The count value is incremented on each Call and is decremented on a Return. 0cccccc B 6 bit counter trap on overflow. 10ccccc B 5 bit counter trap on overflow. 110cccc B 4 bit counter trap on overflow. 1110ccc B 3 bit counter trap on overflow. 11110cc B 2 bit counter trap on overflow. 111110c B 1 bit counter trap on overflow. 1111110 B Trap every call Call Trace mode . 1111111 B Disable Call Depth Counting. When the call depth count CDC.COUNT overflows a trap CDO is generated. Setting the CDC to 1111110 B allows no bits for the counter and causes every call to be trapped. This is used for Call Depth Tracing. Setting the CDC to 1111111 B disables Call Depth Counting. + 0 + 6 + read-write + + + CDE + Call Depth Count Enable CDE. Enables call depth counting provided that the PSW.CDC mask field is not all set to 1. If PSW.CDC 1111111 B call depth counting is disabled regardless of the setting on the PSW.CDE bit. + 7 + 7 + read-write + + + Const_00 + 0 Call depth counting is temporarily disabled. It is automatically re enabled after execution of the next Call instruction. + 0 + + + Const_11 + 1 Call depth counting is enabled. + 1 + + + + + IS + Interrupt Stack Control IS. Determines if the current execution thread is using the shared global interrupt stack or a user stack. + 9 + 9 + read-write + + + Const_00 + 0 User Stack. If an interrupt is taken when the IS bit is 0 then the stack pointer register is loaded from the ISP register before execution starts at the first instruction of the Interrupt Service Routine ISR . + 0 + + + Const_11 + 1 Shared Global Stack. If an interrupt is taken when the PSW.IS bit is 1 then the current value of the stack pointer is used by the Interrupt Service Routine ISR . + 1 + + + + + IO + Access Privilege Level Control I O Privilege IO. Determines the access level to special function registers and peripheral devices. + 10 + 11 + read-write + + + Const_00 + 00 User 0 Mode No peripheral access. Access to memory regions with the peripheral space attribute are prohibited and results in a PSE or MPP trap. This access level is given to tasks that need not directly access peripheral devices. Tasks at this level do not have permission to enable or disable interrupts. + 0 + + + Const_11 + 01 User 1 Mode Regular peripheral access. Enables access to common peripheral devices that are not specially protected including read write access to serial I O ports read access to timers and access to most I O status registers. Tasks at this level may disable interrupts. + 1 + + + Const_22 + 10 Supervisor Mode Enables access to all peripheral devices. It enables read write access to core registers and protected peripheral devices. Tasks at this level may disable interrupts. + 2 + + + + + S + Safe Task Identifier S + 14 + 14 + read-write + + + USB + User Status Bits USB. The eight most significant bits of the PSW are designated as User Status Bits. These bits may be set or cleared as side effects of instruction execution. Refer to the TriCore Architecture manual for details. + 24 + 31 + read-write + + + + + PC + CPUx Program Counter + resetvalue={Application Reset:0x0} + 65032 + 32 + 0 + 0 + + + PC + Program Counter PC + 1 + 31 + read-write + + + + + SYSCON + CPUx System Configuration Register + resetvalue={Application Reset:0x0,Application Reset:0x0} + 65044 + 32 + 0 + 0 + + + FCDSF + Free Context List Depleted Sticky Flag FCDSF. This sticky bit indicates that a FCD Free Context List Depleted trap occurred since the bit was last cleared by software. + 0 + 0 + read-write + + + Const_00 + 0 No FCD trap occurred since the last clear. + 0 + + + Const_11 + 1 An FCD trap occurred since the last clear. + 1 + + + + + PROTEN + Memory Protection Enable PROTEN. Enables the memory protection system. Memory protection is controlled through the memory protection register sets. Note Initialize the protection register sets prior to setting PROTEN to one. + 1 + 1 + read-write + + + Const_00 + 0 Memory Protection is disabled. + 0 + + + Const_11 + 1 Memory Protection is enabled. + 1 + + + + + TPROTEN + Temporal Protection Enable TPROTEN. Enable the Temporal Protection system. + 2 + 2 + read-write + + + Const_00 + 0 Temporal Protection is disabled. + 0 + + + Const_11 + 1 Temporal Protection is enabled. + 1 + + + + + IS + Initial State Interrupt IS. of PSW.S bit in interrupt handle + 3 + 3 + read-write + + + TS + Initial State Trap TS. of PSW.S bit in trap handle + 4 + 4 + read-write + + + ESDIS + Emulator Space Disable. Disable the Emulator Space system + 8 + 8 + read-write + + + U1_IED + User 1 Instruction execution disable U1 IED. Disable the execution of User 1 mode instructions in User 1 IO mode. Disables User 1 ability to enable and disable interrupts. + 16 + 16 + read-write + + + U1_IOS + User 1 Peripheral access as supervisor U1 IOS. Allow User 1 mode tasks to access peripherals as if in Supervisor mode. Enables User 1 access to all peripheral registers. + 17 + 17 + read-write + + + BHALT + Boot Halt BHALT + 24 + 24 + read-write + + + Const_00 + 0 Core is not in boot halt. + 0 + + + Const_11 + 1 Core is in boot halt write to 0 will exit + 1 + + + + + + + CPU_ID + CPUx Identification Register TC1.6.2P + resetvalue={Application Reset:0x0C0C021} + 65048 + 32 + 12632097 + 4294967295 + + + MOD_REV + Revision Number MOD REV + 0 + 7 + read-only + + + Const_3232 + 20 Reset value + 32 + + + + + MOD_32B + 32 Bit Module Enable MOD 32B + 8 + 15 + read-only + + + Const_192192 + C0 A value of C0 H in this field indicates a 32 bit module with a 32 bit module ID register. + 192 + + + + + MOD + Module Identification Number MOD + 16 + 31 + read-only + + + Const_192192 + 00C0 For module identification. + 192 + + + + + + + CORE_ID + CPUx Core Identification Register + resetvalue={Application Reset:0x0} + 65052 + 32 + 0 + 4294967288 + + + CORE_ID + Core Identification Number CORE ID. The identification number of the core. + 0 + 2 + read-only + + + + + BIV + CPUx Base Interrupt Vector Table Pointer + resetvalue={Application Reset:0x0} + 65056 + 32 + 0 + 4294967295 + + + VSS + Vector Spacing Select VSS. 0 32 byte vector spacing. 1 8 Byte vector spacing. + 0 + 0 + read-write + + + BIV + Base Address of Interrupt Vector Table BIV. The address in the BIV register must be aligned to an even byte address halfword address . Because of the simple ORing of the left shifted priority number and the contents of the BIV register the alignment of the base address of the vector table must be to a power of two boundary dependent on the number of interrupt entries used. For the full range of 256 interrupt entries an alignment to an 8 KByte boundary is required. If fewer sources are used the alignment requirements are correspondingly relaxed. + 1 + 31 + read-write + + + + + BTV + CPUx Base Trap Vector Table Pointer + resetvalue={Application Reset:0x0A0000100} + 65060 + 32 + 2684354816 + 4294967295 + + + BTV + Base Address of Trap Vector Table BTV. The address in the BTV register must be aligned to an even byte address halfword address . Also due to the simple ORing of the left shifted trap identification number and the contents of the BTV register the alignment of the base address of the vector table must be to a power of two boundary. There are eight different trap classes resulting in Trap Classes from 0 to 7. The contents of BTV should therefore be set to at least a 256 byte boundary 8 Trap Classes 8 word spacing . + 1 + 31 + read-write + + + + + ISP + CPUx Interrupt Stack Pointer + resetvalue={Application Reset:0x100} + 65064 + 32 + 256 + 4294967295 + + + ISP + Interrupt Stack Pointer ISP + 0 + 31 + read-write + + + + + ICR + CPUx Interrupt Control Register + resetvalue={Application Reset:0x0} + 65068 + 32 + 0 + 4294967295 + + + CCPN + Current CPU Priority Number CCPN. The Current CPU Priority Number CCPN bit field indicates the current priority level of the CPU. It is automatically updated by hardware on entry or exit of Interrupt Service Routines ISRs and through the execution of a BISR instruction. CCPN can also be updated through an MTCR instruction. + 0 + 7 + read-write + + + IE + Global Interrupt Enable Bit IE. The interrupt enable bit globally enables the CPU service request system. Whether a service request is delivered to the CPU depends on the individual Service Request Enable Bits SRE in the SRNs and the current state of the CPU. ICR.IE is automatically updated by hardware on entry and exit of an Interrupt Service Routine ISR . ICR.IE is cleared to 0 when an interrupt is taken and is restored to the previous value when the ISR executes an RFE instruction to terminate itself. ICR.IE can also be updated through the execution of the ENABLE DISABLE MTCR and BISR instructions. + 15 + 15 + read-write + + + Const_00 + 0 Interrupt system is globally disabled + 0 + + + Const_11 + 1 Interrupt system is globally enabled + 1 + + + + + PIPN + Pending Interrupt Priority Number PIPN. A read only bit field that is updated by the ICU at the end of each interrupt arbitration process. It indicates the priority number of the pending service request. ICR.PIPN is set to 0 when no request is pending and at the beginning of each new arbitration process. ... + 16 + 23 + read-only + + + Const_00 + 00 No valid pending request. + 0 + + + Const_11 + 01 Request pending lowest priority. + 1 + + + Const_255255 + FF Request pending highest priority. + 255 + + + + + + + FCX + CPUx Free CSA List Head Pointer + resetvalue={Application Reset:0x0} + 65080 + 32 + 0 + 4294967295 + + + FCXO + FCX Offset Address Field FCXO. The FCXO and FCXS fields together form the FCX pointer which points to the next available CSA. + 0 + 15 + read-write + + + FCXS + FCX Segment Address Field FCXS. Used in conjunction with the FCXO field. + 16 + 19 + read-write + + + + + LCX + CPUx Free CSA List Limit Pointer + resetvalue={Application Reset:0x0} + 65084 + 32 + 0 + 4294967295 + + + LCXO + LCX Offset Field LCXO. The LCXO and LCXS fields form the pointer LCX which points to the last available CSA. + 0 + 15 + read-write + + + LCXS + LCX Segment Address LCXS. This field is used in conjunction with the LCXO field. + 16 + 19 + read-write + + + + + CUS_ID + CPUx Customer ID register + resetvalue={Application Reset:0x0} + 65104 + 32 + 0 + 4294967288 + + + CID + Customer ID CID. See CROSSREFERENCE for the relation between CUS ID and CORE ID for each derivative + 0 + 2 + read-only + + + + + 16 + 4 + Dy[%s] + CPUx Data General Purpose Register 0 + resetvalue={Application Reset:0x0} + 65280 + 32 + 0 + 0 + + + DATA + Data Register DATA. General purpose registers + 0 + 31 + read-write + + + + + 16 + 4 + Ay[%s] + CPUx Address General Purpose Register 0 + resetvalue={Application Reset:0x0} + 65408 + 32 + 0 + 0 + + + ADDR + Address Register ADDR. General purpose registers + 0 + 31 + read-write + + + + + CPXE_0 + CPUx Code Protection Execute Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57344 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + CPXE_1 + CPUx Code Protection Execute Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57348 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + CPXE_2 + CPUx Code Protection Execute Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57352 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + CPXE_3 + CPUx Code Protection Execute Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57356 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + DPRE_0 + CPUx Data Protection Read Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57360 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPRE_1 + CPUx Data Protection Read Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57364 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPRE_2 + CPUx Data Protection Read Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57368 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPRE_3 + CPUx Data Protection Read Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57372 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPWE_0 + CPUx Data Protection Write Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57376 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + DPWE_1 + CPUx Data Protection Write Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57380 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + DPWE_2 + CPUx Data Protection Write Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57384 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + DPWE_3 + CPUx Data Protection Write Enable Register Set 3 + resetvalue={Application Reset:0x0} + 57388 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + CPXE_4 + CPUx Code Protection Execute Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57408 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + CPXE_5 + CPUx Code Protection Execute Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57412 + 32 + 0 + 4294967295 + + + XE_n + Execute Enable Range select XE n + 0 + 9 + read-write + + + Const_00 + 0 Code Protection Range n not enabled for execution + 0 + + + Const_11 + 1 Code Protection Range n enabled for execution + 1 + + + + + + + DPRE_4 + CPUx Data Protection Read Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57424 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPRE_5 + CPUx Data Protection Read Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57428 + 32 + 0 + 4294967295 + + + RE_n + Read Enable Range Select RE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data read + 0 + + + Const_11 + 1 Data Protection Range n enabled for data read + 1 + + + + + + + DPWE_4 + CPUx Data Protection Write Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57440 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + DPWE_5 + CPUx Data Protection Write Enable Register Set 5 + resetvalue={Application Reset:0x0} + 57444 + 32 + 0 + 4294967295 + + + WE_n + Write Enable Range Select WE n + 0 + 17 + read-write + + + Const_00 + 0 Data Protection Range n not enabled for data write + 0 + + + Const_11 + 1 Data Protection Range n enabled for data write + 1 + + + + + + + CCTRL + CPUx Counter Control + resetvalue={Debug Reset:0x0} + 64512 + 32 + 0 + 4294967295 + + + CM + Counter Mode CM + 0 + 0 + read-write + + + Const_00 + 0 Normal Mode. + 0 + + + Const_11 + 1 Task Mode. + 1 + + + + + CE + Count Enable CE + 1 + 1 + read-write + + + Const_00 + 0 Disable the counters CCNT ICNT M1CNT M2CNT M3CNT. + 0 + + + Const_11 + 1 Enable the counters CCNT ICNT M1CNT M2CNT M3CNT. + 1 + + + + + M1 + M1CNT Configuration M1 + 2 + 4 + read-write + + + M2 + M2CNT Configuration M2 + 5 + 7 + read-write + + + M3 + M3CNT Configuration M3 + 8 + 10 + read-write + + + + + CCNT + CPUx CPU Clock Cycle Count + resetvalue={Debug Reset:0x0} + 64516 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Current Count of the CPU Clock Cycles. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + ICNT + CPUx Instruction Count + resetvalue={Debug Reset:0x0} + 64520 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Count of the Instructions Executed. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + M1CNT + CPUx Multi Count Register 1 + resetvalue={Debug Reset:0x0} + 64524 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Count of the Selected Event. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + M2CNT + CPUx Multi Count Register 2 + resetvalue={Debug Reset:0x0} + 64528 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Count of the Selected Event. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + M3CNT + CPUx Multi Count Register 3 + resetvalue={Debug Reset:0x0} + 64532 + 32 + 0 + 4294967295 + + + CountValue + Count Value CountValue. Count of the Selected Event. + 0 + 30 + read-write + + + SOvf + Sticky Overflow Bit SOvf. This bit is set by hardware when count value 30 0 31 h7FFF FFFF. It can only be cleared by software. + 31 + 31 + read-write + + + + + DBGSR + CPUx Debug Status Register + resetvalue={Debug Reset:0x0} + 64768 + 32 + 0 + 4294967295 + + + DE + Debug Enable DE. Determines whether the CDC is enabled or not. + 0 + 0 + read-only + + + Const_00 + 0 The CDC is disabled. + 0 + + + Const_11 + 1 The CDC is enabled. + 1 + + + + + HALT + CPU Halt Request Status Field HALT. HALT can be set or cleared by software. HALT 0 is the actual Halt bit. HALT 1 is a mask bit to specify whether or not HALT 0 is to be updated on a software write. HALT 1 is always read as 0. HALT 1 must be set to 1 in order to update HALT 0 by software R read W write . + 1 + 2 + read-write + + + Const_00 + 00 R CPU running. W HALT 0 unchanged. + 0 + + + Const_11 + 01 R CPU halted. W HALT 0 unchanged. + 1 + + + Const_22 + 10 R Not Applicable. W reset HALT 0 . + 2 + + + Const_33 + 11 R Not Applicable. W If DBGSR.DE 1 The CDC is enabled set HALT 0 . If DBGSR.DE 0 The CDC is not enabled HALT 0 is left unchanged. + 3 + + + + + SIH + Suspend in Halt SIH. State of the Suspend In signal. + 3 + 3 + read-only + + + Const_00 + 0 The Suspend In signal is negated. The CPU is not in Halt Mode except when the Halt mechanism is set following a Debug Event or a write to DBGSR.HALT . + 0 + + + Const_11 + 1 The Suspend In signal is asserted. The CPU is in Halt Mode. + 1 + + + + + SUSP + Current State of the Core Suspend Out Signal SUSP + 4 + 4 + read-write + + + Const_00 + 0 Core suspend out inactive. + 0 + + + Const_11 + 1 Core suspend out active. + 1 + + + + + PREVSUSP + Previous State of Core Suspend Out Signal PREVSUSP. Updated when a Debug Event causes a hardware update of DBGSR.SUSP. This field is not updated for writes to DBGSR.SUSP. + 6 + 6 + read-only + + + Const_00 + 0 Previous core suspend out inactive. + 0 + + + Const_11 + 1 Previous core suspend out active. + 1 + + + + + PEVT + Posted Event PEVT + 7 + 7 + read-write + + + Const_00 + 0 No posted event. + 0 + + + Const_11 + 1 Posted event. + 1 + + + + + + + EXEVT + CPUx External Event Register + resetvalue={Debug Reset:0x0} + 64776 + 32 + 0 + 4294967295 + + + EVTA + Event Associated EVTA. Specifies the Debug Action associated with the Debug Event + 0 + 2 + read-write + + + Const_00 + 000 BOD 0 Disabled. BOD 1 Disabled. + 0 + + + Const_11 + 001 BOD 0 Pulse BRKOUT Signal. BOD 1 None. + 1 + + + Const_22 + 010 BOD 0 Halt and pulse BRKOUT Signal. BOD 1 Halt. + 2 + + + Const_33 + 011 BOD 0 Breakpoint trap and pulse. BRKOUT Signal. BOD 1 Breakpoint trap. + 3 + + + Const_44 + 100 BOD 0 Breakpoint interrupt 0 and pulse BRKOUT Signal. BOD 1 Breakpoint interrupt 0. + 4 + + + Const_55 + 101 BOD 0 If implemented breakpoint interrupt 1 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 1. If not implemented None. + 5 + + + Const_66 + 110 BOD 0 If implemented breakpoint interrupt 2 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 2. If not implemented None. + 6 + + + Const_77 + 111 BOD 0 If implemented breakpoint interrupt 3 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 3. If not implemented None. + 7 + + + + + BBM + Break Before Make BBM or Break After Make BAM Selection BBM + 3 + 3 + read-write + + + Const_00 + 0 Break after make BAM . + 0 + + + Const_11 + 1 Break before make BBM . + 1 + + + + + BOD + Breakout Disable BOD + 4 + 4 + read-write + + + Const_00 + 0 BRKOUT signal asserted according to the Debug Action specified in the EVTA field. + 0 + + + Const_11 + 1 BRKOUT signal not asserted. This takes priority over any assertion generated by the EVTA field. + 1 + + + + + SUSP + CDC Suspend Out Signal State SUSP. Value to be assigned to the CDC suspend out signal when the Debug Event is raised. + 5 + 5 + read-write + + + CNT + Counter CNT. When this event occurs adjust the control of the performance counters in task mode as follows + 6 + 7 + read-write + + + Const_00 + 00 No change. + 0 + + + Const_11 + 01 Start the performance counters. + 1 + + + Const_22 + 10 Stop the performance counters. + 2 + + + Const_33 + 11 Toggle the performance counter control i.e. start it if it is currently stopped stop it if it is currently running . + 3 + + + + + + + CREVT + CPUx Core Register Access Event + resetvalue={Debug Reset:0x0} + 64780 + 32 + 0 + 4294967295 + + + EVTA + Event Associated EVTA. Debug Action associated with the Debug Event + 0 + 2 + read-write + + + Const_00 + 000 BOD 0 Disabled. BOD 1 Disabled. + 0 + + + Const_11 + 001 BOD 0 Pulse BRKOUT Signal. BOD 1 None. + 1 + + + Const_22 + 010 BOD 0 Halt and pulse BRKOUT Signal. BOD 1 Halt. + 2 + + + Const_33 + 011 BOD 0 Breakpoint trap and pulse BRKOUT Signal. BOD 1 Breakpoint trap. + 3 + + + Const_44 + 100 BOD 0 Breakpoint interrupt 0 and pulse BRKOUT Signal. BOD 1 Breakpoint interrupt 0. + 4 + + + Const_55 + 101 BOD 0 If implemented breakpoint interrupt 1 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 1. If not implemented None. + 5 + + + Const_66 + 110 BOD 0 If implemented breakpoint interrupt 2 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 2. If not implemented None. + 6 + + + Const_77 + 111 BOD 0 If implemented breakpoint interrupt 3 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 3. If not implemented None. + 7 + + + + + BBM + Break Before Make BBM or Break After Make BAM Selection BBM + 3 + 3 + read-write + + + Const_00 + 0 Break after make BAM . + 0 + + + Const_11 + 1 Break before make BBM . + 1 + + + + + BOD + Breakout Disable BOD + 4 + 4 + read-write + + + Const_00 + 0 BRKOUT signal asserted according to the action specified in the EVTA field. + 0 + + + Const_11 + 1 BRKOUT signal not asserted. This takes priority over any assertion generated by the EVTA field. + 1 + + + + + SUSP + CDC Suspend Out Signal State SUSP. Value to be assigned to the CDC suspend out signal when the Debug Event is raised. + 5 + 5 + read-write + + + CNT + Counter CNT. When this event occurs adjust the control of the performance counters in task mode as follows + 6 + 7 + read-write + + + Const_00 + 00 No change. + 0 + + + Const_11 + 01 Start the performance counters. + 1 + + + Const_22 + 10 Stop the performance counters. + 2 + + + Const_33 + 11 Toggle the performance counter control i.e. start it if it is currently stopped stop it if it is currently running . + 3 + + + + + + + SWEVT + CPUx Software Debug Event + resetvalue={Debug Reset:0x0} + 64784 + 32 + 0 + 4294967295 + + + EVTA + Event Associated EVTA. Debug Action associated with the Debug Event + 0 + 2 + read-write + + + Const_00 + 000 BOD 0 Disabled. BOD 1 Disabled. + 0 + + + Const_11 + 001 BOD 0 Pulse BRKOUT Signal. BOD 1 None. + 1 + + + Const_22 + 010 BOD 0 Halt and pulse BRKOUT Signal. BOD 1 Halt. + 2 + + + Const_33 + 011 BOD 0 Breakpoint trap and pulse BRKOUT Signal. BOD 1 Breakpoint trap. + 3 + + + Const_44 + 100 BOD 0 Breakpoint interrupt 0 and pulse BRKOUT Signal. BOD 1 Breakpoint interrupt 0. + 4 + + + Const_55 + 101 BOD 0 If implemented breakpoint interrupt 1 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 1. If not implemented None. + 5 + + + Const_66 + 110 BOD 0 If implemented breakpoint interrupt 2 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 2. If not implemented None. + 6 + + + Const_77 + 111 BOD 0 If implemented breakpoint interrupt 3 and pulse BRKOUT Signal. BOD 1 If implemented breakpoint interrupt 3. If not implemented None. + 7 + + + + + BBM + Break Before Make BBM or Break After Make BAM Selection BBM + 3 + 3 + read-write + + + Const_00 + 0 Break after make BAM . + 0 + + + Const_11 + 1 Break before make BBM . + 1 + + + + + BOD + Breakout Disable BOD + 4 + 4 + read-write + + + Const_00 + 0 BRKOUT signal asserted according to the action specified in the EVTA field. + 0 + + + Const_11 + 1 BRKOUT signal not asserted. This takes priority over any assertion generated by the EVTA field. + 1 + + + + + SUSP + CDC Suspend Out Signal State SUSP. Value to be assigned to the CDC suspend out signal when the event is raised. + 5 + 5 + read-write + + + CNT + Counter CNT. When this event occurs adjust the control of the performance counters in task mode as follows + 6 + 7 + read-write + + + Const_00 + 00 No change. + 0 + + + Const_11 + 01 Start the performance counters. + 1 + + + Const_22 + 10 Stop the performance counters. + 2 + + + Const_33 + 11 Toggle the performance counter control i.e. start it if it is currently stopped stop it if it is currently running . + 3 + + + + + + + TRIG_ACC + CPUx TriggerAddressx + resetvalue={Debug Reset:0x0} + 64816 + 32 + 0 + 4294967295 + + + T0 + Trigger 0 T0. active since last cleared + 0 + 0 + read-only + + + T1 + Trigger 1 T1. active since last cleared + 1 + 1 + read-only + + + T2 + Trigger 2 T2. active since last cleared + 2 + 2 + read-only + + + T3 + Trigger 3 T3. active since last cleared + 3 + 3 + read-only + + + T4 + Trigger 4 T4. active since last cleared + 4 + 4 + read-only + + + T5 + Trigger 5 T5. active since last cleared + 5 + 5 + read-only + + + T6 + Trigger 6 T6. active since last cleared + 6 + 6 + read-only + + + T7 + Trigger 7 T7. active since last cleared + 7 + 7 + read-only + + + + + DMS + CPUx Debug Monitor Start Address + resetvalue={Application Reset:0x0} + 64832 + 32 + 0 + 0 + + + DMSValue + Debug Monitor Start Address DMSValue. The address at which monitor code execution begins when a breakpoint trap is taken. + 1 + 31 + read-write + + + + + DCX + CPUx Debug Context Save Area Pointer + resetvalue={Application Reset:0x0} + 64836 + 32 + 0 + 0 + + + DCXValue + Debug Context Save Area Pointer DCXValue. Address where the debug context is stored following a breakpoint trap. + 6 + 31 + read-write + + + + + DBGTCR + CPUx Debug Trap Control Register + resetvalue={Application Reset:0x1} + 64840 + 32 + 1 + 4294967295 + + + DTA + Debug Trap Active Bit DTA. A breakpoint trap may only be taken in the condition DTA 0. Taking a breakpoint trap sets the DTA bit to one. Further breakpoint traps are therefore disabled until such time as the breakpoint trap handler clears the DTA bit or until the breakpoint trap handler terminates with a RFM. + 0 + 0 + read-write + + + Const_00 + 0 No breakpoint trap is active. + 0 + + + Const_11 + 1 A breakpoint Trap is active + 1 + + + + + + + SEGEN + CPUx SRI Error Generation Register + resetvalue={Application Reset:0x0} + 4144 + 32 + 0 + 4294967295 + + + ADFLIP + Address ECC Bit Flip ADFLIP. SRI address ECC Bits to be flipped on the next read or write transaction from the DMI when enabled by AE. + 0 + 7 + read-write + + + Const_00 + 0 No Flip + 0 + + + Const_11 + 1 Flip + 1 + + + + + ADTYPE + Type of error ADTYPE + 8 + 9 + read-write + + + Const_00 + 00 Data Master Address Phase + 0 + + + Const_11 + 01 Data Master Write Data + 1 + + + Const_22 + 10 Data Slave Read Data + 2 + + + + + AE + Activate Error Enable AE. Enabled the selective inverting of SRI ECC packet bits defined by ADFLIP. This bit will be cleared by hardware after the next SRI read or write transaction from the DMI. + 31 + 31 + read-write + + + Const_00 + 0 Not Enabled + 0 + + + Const_11 + 1 Enabled + 1 + + + + + + + DCON2 + CPUx Data Control Register 2 + resetvalue={Application Reset:0x0} + 36864 + 32 + 0 + 0 + + + DCACHE_SZE + Data Cache Size DCACHE SZE. In KBytes + 0 + 15 + read-only + + + DSCRATCH_SZE + Data Scratch Size DSCRATCH SZE. In KBytes + 16 + 31 + read-only + + + + + DSTR + CPUx Data Synchronous Trap Register + resetvalue={Application Reset:0x0} + 36880 + 32 + 0 + 4294967295 + + + SRE + Scratch Range Error SRE. A scratch Range Error occurs whenever an access to the data scratch is outside the range of the SRAM. + 0 + 0 + read-write + + + GAE + Global Address Error GAE. Load or store to local code scratch address outside of the lower 1MByte. + 1 + 1 + read-write + + + LBE + Load Bus Error LBE. A Load Bus Error will be set whenever the SRI flags an error due a load from external memory. + 2 + 2 + read-write + + + DRE + Local DLMU Range Error DRE. A DLMU Range Error occurs whenever an access to the local DLMU region is outside the physically implemented memory. + 3 + 3 + read-write + + + CRE + Cache Refill Error CRE. A Cache Refill Error will be set whenever the SRI flags an error due a cache refill from external memory. + 6 + 6 + read-write + + + DTME + DTAG MSIST Error DTME. Access to memory mapped DTAG range outside of physically implemented memory. + 14 + 14 + read-write + + + LOE + Load Overlay Error LOE. Load to invalid overlay address. + 15 + 15 + read-write + + + SDE + Segment Difference Error SDE. Load or store access where base address is in different segment to access address. + 16 + 16 + read-write + + + SCE + Segment Crossing Error SCE. Load or store access across segment boundary. + 17 + 17 + read-write + + + CAC + CSFR Access Error CAC. Load or store to local CSFR space. + 18 + 18 + read-write + + + MPE + Memory Protection Error MPE. Data access violating memory protection. + 19 + 19 + read-write + + + CLE + Context Location Error CLE. Context operation to invalid location. + 20 + 20 + read-write + + + ALN + Alignment Error ALN. Data access causing alignment error. + 24 + 24 + read-write + + + + + DATR + CPUx Data Asynchronous Trap Register + resetvalue={Application Reset:0x0} + 36888 + 32 + 0 + 4294967295 + + + SBE + Store Bus Error SBE + 3 + 3 + read-write + + + CWE + Cache Writeback Error CWE + 9 + 9 + read-write + + + CFE + Cache Flush Error CFE + 10 + 10 + read-write + + + SOE + Store Overlay Error SOE + 14 + 14 + read-write + + + + + DEADD + CPUx Data Error Address Register + resetvalue={Application Reset:0x0} + 36892 + 32 + 0 + 4294967295 + + + ERROR_ADDRESS + Error Address ERROR ADDRESS + 0 + 31 + read-only + + + + + DCON0 + CPUx Data Memory Control Register + resetvalue={Application Reset:0x2} + 36928 + 32 + 2 + 4294967295 + + + DCBYP + Data Cache Bypass DCBYP + 1 + 1 + read-write + + + Const_00 + 0 DCache DRB enabled + 0 + + + Const_11 + 1 DCache DRB Bypass disabled + 1 + + + + + + + PSTR + CPUx Program Synchronous Trap Register + resetvalue={Application Reset:0x0} + 37376 + 32 + 0 + 4294967295 + + + FRE + Fetch Range Error FRE. A Fetch Range Error occurs whenever an access to the Program Scratch is outside the range of the SRAM. + 0 + 0 + read-write + + + FBE + Fetch Bus Error FBE. A Fetch bus error will be set whenever the SRI flags an error due a fetch from external memory. This will be set for both direct fetches from the bus and for cache refills. + 2 + 2 + read-write + + + FPE + Fetch Peripheral Error FPE. A Fetch peripheral error will be flagged whenever a fetch is attempted to peripheral space. + 12 + 12 + read-write + + + FME + Fetch MSIST Error FME. During SIST mode a fetch from the PTAG will cause a PSE trap to occur. + 14 + 14 + read-write + + + + + PCON1 + CPUx Program Control 1 + resetvalue={Application Reset:0x0} + 37380 + 32 + 0 + 4294967295 + + + PCINV + Program Cache Invalidate PCINV + 0 + 0 + read-write + + + Const_00 + 0 Write No effect normal instruction cache operation. Read Normal operation instruction cache available + 0 + + + Const_11 + 1 Write Initiate invalidation of entire instruction cache. Read Instruction cache invalidation in progress. Instruction cache unavailable. + 1 + + + + + PBINV + Program Buffer Invalidate PBINV. Write Operation This field returns 0 when read. + 1 + 1 + read-write + + + Const_00 + 0 Write No effect. Normal program line buffer operation. + 0 + + + Const_11 + 1 Write Invalidate the program line buffer. + 1 + + + + + + + PCON2 + CPUx Program Control 2 + resetvalue={Application Reset:0x0} + 37384 + 32 + 0 + 0 + + + PCACHE_SZE + Program Cache Size ICACHE in KBytes PCACHE SZE. In KBytes + 0 + 15 + read-only + + + PSCRATCH_SZE + Program Scratch Size in KBytes PSCRATCH SZE. In KBytes + 16 + 31 + read-only + + + + + PCON0 + CPUx Program Control 0 + resetvalue={Application Reset:0x2} + 37388 + 32 + 2 + 4294967295 + + + PCBYP + Program Cache Bypass PCBYP + 1 + 1 + read-write + + + Const_00 + 0 Cache enabled + 0 + + + Const_11 + 1 Cache bypass disabled + 1 + + + + + + + + + + \ No newline at end of file diff --git a/test_svd/svd.xsd b/test_svd/svd.xsd new file mode 100644 index 0000000..94f9b6e --- /dev/null +++ b/test_svd/svd.xsd @@ -0,0 +1,645 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..a8e7b6b --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,74 @@ +use std::fs; +use std::path::Path; +use std::process::Command; + +#[allow(dead_code)] +pub fn assert_files_eq, Q: AsRef>(ref_file: T, gen_file: Q) { + let ref_file = fs::read_to_string(ref_file).expect("Unable to read source file"); + let gen_file = fs::read_to_string(gen_file).expect("Unable to read generated file"); + let result = similar::TextDiff::from_lines(&ref_file, &gen_file); + let diff = format!( + "{}", + result + .unified_diff() + .context_radius(10) + .header("ref_file", "new_file") + ); + assert!( + !result + .ops() + .iter() + .any(|ops| !matches!(*ops, similar::DiffOp::Equal { .. })), + "{}", + diff + ); +} + +/// execute cargo build and check that build is successfull +pub fn assert_cargo_build(package_folder: tempfile::TempDir) { + // Run cargo to build + let mut command = Command::new("cargo"); + command.arg("build"); + command.current_dir(package_folder.path()); + + let exec_result = command.output(); + + if exec_result.is_err() { + // This to preserve the project for further debugging + let _ = package_folder.into_path(); + panic!("Failed to execute"); + } + let output_result = exec_result.unwrap(); + if !output_result.status.success() { + let stdout_msg = std::str::from_utf8(&output_result.stdout) + .expect("Failed to parse stdout returned from cargo build"); + let stderr_msg = std::str::from_utf8(&output_result.stderr) + .expect("Failed to parse stderr returned from cargo build"); + eprintln!("Failed compilation of test project stdout: {}", stdout_msg); + eprintln!("Failed compilation of test project stderr: {}", stderr_msg); + // This to preserve the project for further debugging + let _ = package_folder.into_path(); + panic!("Failed compilation of test project"); + } +} + +#[allow(dead_code)] +pub fn assert_cargo_test(package_folder: tempfile::TempDir) { + // Run cargo to build + let mut command = Command::new("cargo"); + command.arg("test"); + command.current_dir(package_folder.path()); + + let exec_result = command.output(); + + if exec_result.is_err() { + // This to preserve the project for further debugging + let _ = package_folder.into_path(); + panic!("Failed to execute tests"); + } + if !exec_result.unwrap().status.success() { + // This to preserve the project for further debugging + let _ = package_folder.into_path(); + panic!("Failed running tests of test project"); + } +} diff --git a/tests/reference_gen_code/simple.txt b/tests/reference_gen_code/simple.txt new file mode 100644 index 0000000..8c2c9a2 --- /dev/null +++ b/tests/reference_gen_code/simple.txt @@ -0,0 +1,101 @@ +#![no_std] +#![doc = "Peripheral access API (generated using chiptool v0.1.0 (150ce4a 2023-03-22))"] + +mod common { + use core::marker::PhantomData; + + #[derive(Copy, Clone, PartialEq, Eq)] + pub struct RW; + #[derive(Copy, Clone, PartialEq, Eq)] + pub struct R; + #[derive(Copy, Clone, PartialEq, Eq)] + pub struct W; + + mod sealed { + use super::*; + pub trait Access {} + impl Access for R {} + impl Access for W {} + impl Access for RW {} + } + + pub trait Access: sealed::Access + Copy {} + impl Access for R {} + impl Access for W {} + impl Access for RW {} + + pub trait Read: Access {} + impl Read for RW {} + impl Read for R {} + + pub trait Write: Access {} + impl Write for RW {} + impl Write for W {} + + #[derive(Copy, Clone, PartialEq, Eq)] + pub struct Reg { + ptr: *mut u8, + phantom: PhantomData<*mut (T, A)>, + } + unsafe impl Send for Reg {} + unsafe impl Sync for Reg {} + + impl Reg { + #[inline(always)] + pub fn from_ptr(ptr: *mut u8) -> Self { + Self { + ptr, + phantom: PhantomData, + } + } + + #[inline(always)] + pub fn ptr(&self) -> *mut T { + self.ptr as _ + } + } + + impl Reg { + #[inline(always)] + pub unsafe fn read(&self) -> T { + (self.ptr as *mut T).read_volatile() + } + } + + impl Reg { + #[inline(always)] + pub unsafe fn write_value(&self, val: T) { + (self.ptr as *mut T).write_volatile(val) + } + } + + impl Reg { + #[inline(always)] + pub unsafe fn write(&self, f: impl FnOnce(&mut T) -> R) -> R { + let mut val = Default::default(); + let res = f(&mut val); + self.write_value(val); + res + } + } + + impl Reg { + #[inline(always)] + pub unsafe fn modify(&self, f: impl FnOnce(&mut T) -> R) -> R { + let mut val = self.read(); + let res = f(&mut val); + self.write_value(val); + res + } + } +} + + +mod TIMER0 + + +mod TIMER1 + + +mod TIMER2 + diff --git a/tests/resources/LICENSE.txt b/tests/resources/LICENSE.txt new file mode 100644 index 0000000..61fe2e3 --- /dev/null +++ b/tests/resources/LICENSE.txt @@ -0,0 +1,3 @@ +This is demo license. +Multiple lines /* with some nested comments*/ + diff --git a/tests/resources/project_files_aurix/.cargo/config.toml b/tests/resources/project_files_aurix/.cargo/config.toml new file mode 100644 index 0000000..870a705 --- /dev/null +++ b/tests/resources/project_files_aurix/.cargo/config.toml @@ -0,0 +1,16 @@ +[target.tc162-htc-none] +rustflags = ["-C", "link-args=-Llinker-scripts -Ttc39xB_memory.ld -Map memory.map"] +linker = "rust-lld.exe" +runner = "tsim16p_e -tc162p -config_file_path tsim-semihosting/tsim-config -disable-watchdog -s -U -x 100000 -e -H -o" + +[build] +target = "tc162-htc-none" + +[env] +CC_tc162_htc_none = "clang" +CFLAGS_tc162_htc_none = "-march=tc162" +AR_tc162_htc_none = "llvm-ar" +ARFLAGS_tc162_htc_none = "r" + +[unstable] +sparse-registry = true diff --git a/tests/resources/project_files_aurix/linker-scripts/tc39xB_memory.ld b/tests/resources/project_files_aurix/linker-scripts/tc39xB_memory.ld new file mode 100644 index 0000000..0f166b9 --- /dev/null +++ b/tests/resources/project_files_aurix/linker-scripts/tc39xB_memory.ld @@ -0,0 +1,110 @@ +/************************************************************************************************** + * FILE: tc39xB_memory.ld + * + * UC ARCHITECTURE: + * + * TC3xx + * + * UC FAMILY: + * + * TC39xB + * + * DESCRIPTION: + * + * uC family memory region definition file. + * Not all available memory regions are defined, only those used in BSP example. + * It includes the application linker files locating sections to memory regions at the end. + * + * FILE HISTORY: + * + * V1 05.2020 RO + * - Base reference example + * + ************************************************************************************************** + * Copyright (C) 2015-2020 HighTec EDV-Systeme GmbH. All rights reserved. + * This is proprietary software. Any use of the software requires a written + * license agreement with HighTec EDV-Systeme GmbH. Please contact for + * detailed license information: info@hightec-rt.com. + *************************************************************************************************/ + +OUTPUT_FORMAT("elf32-tricore") +OUTPUT_ARCH(tricore) +ENTRY(_crt0_reset) + + +/* ================================================================================================ + * TC39XB MEMORY REGIONS + * ==============================================================================================*/ + +MEMORY +{ + /* User configuration block - BMHD headers only */ + ucb_bmhd_orig (rx): org = 0xaf400000, len = 2K + ucb_bmhd_copy (rx): org = 0xaf401000, len = 2K + + /* Program Flash memory - cached region */ + int_flash0 (rx): org = 0x80000000, len = 3M + int_flash1 (rx): org = 0x80300000, len = 3M + int_flash2 (rx): org = 0x80600000, len = 3M + int_flash3 (rx): org = 0x80900000, len = 3M + int_flash4 (rx): org = 0x80C00000, len = 3M + int_flash5 (rx): org = 0x80F00000, len = 1M + + /* Program scratchpad memories */ + pspr_cpu0 (rx): org = 0x70100000, len = 64K + pspr_cpu1 (rx): org = 0x60100000, len = 64K + pspr_cpu2 (rx): org = 0x50100000, len = 64K + pspr_cpu3 (rx): org = 0x40100000, len = 64K + pspr_cpu4 (rx): org = 0x30100000, len = 64K + pspr_cpu5 (rx): org = 0x10100000, len = 64K + + /* Data scratchpad memories */ + dspr_cpu0 (w!x): org = 0x70000000, len = 240K + dspr_cpu1 (w!x): org = 0x60000000, len = 240K + dspr_cpu2 (w!x): org = 0x50000000, len = 96K + dspr_cpu3 (w!x): org = 0x40000000, len = 96K + dspr_cpu4 (w!x): org = 0x30000000, len = 96K + dspr_cpu5 (w!x): org = 0x10000000, len = 96K + + /* Distributed LMU RAM - Non-Cached regions selected + * Local core access is always non-cached */ + dlmu_cpu0 (wx): org = 0xB0000000, len = 64K + dlmu_cpu1 (wx): org = 0xB0010000, len = 64K + dlmu_cpu2 (wx): org = 0xB0020000, len = 64K + dlmu_cpu3 (wx): org = 0xB0030000, len = 64K + dlmu_cpu4 (wx): org = 0xB0100000, len = 64K + dlmu_cpu5 (wx): org = 0xB0110000, len = 64K + + /* Global LMU - Local memory Unit */ + lmu0_cached (wx): org = 0x90040000, len = 256K + lmu1_cached (wx): org = 0x90080000, len = 256K + lmu2_cached (wx): org = 0x900C0000, len = 256K + lmu0_noncached (wx): org = 0xB0040000, len = 256K + lmu1_noncached (wx): org = 0xB0080000, len = 256K + lmu2_noncached (wx): org = 0xB00C0000, len = 256K + + /* Periphery memory space region */ + periphery_base : org = 0xF0000000, len = 0 + periphery_end : org = 0xFFFF0000, len = 0 +} + +/* memory mirrors describe same physical memory accessible by different addresses */ +/* "REGION_MIRROR" keyword is not supported by LLVM linker! +REGION_MIRROR("lmu0_cached", "lmu0_noncached") +REGION_MIRROR("lmu1_cached", "lmu1_noncached") +REGION_MIRROR("lmu2_cached", "lmu2_noncached") +*/ + +/* ================================================================================================ + * MEMORY REGION SYMBOLS + * ==============================================================================================*/ + +/* Internal Flash memory */ +INT_FLASH_MEMORY_BASE = ORIGIN(int_flash0); +INT_FLASH_MEMORY_SIZE = 16M; + +/* ================================================================================================ + * INCLUDE OF APPLICATION LINKER FILE + * ==============================================================================================*/ + +INCLUDE tc39x_bsp_example_llvm.ld diff --git a/tests/resources/project_files_aurix/linker-scripts/tc39x_bsp_example_llvm.ld b/tests/resources/project_files_aurix/linker-scripts/tc39x_bsp_example_llvm.ld new file mode 100644 index 0000000..dceaef4 --- /dev/null +++ b/tests/resources/project_files_aurix/linker-scripts/tc39x_bsp_example_llvm.ld @@ -0,0 +1,671 @@ +/************************************************************************************************** + * FILE: tc39x_bsp_example.ld + * + * UC ARCHITECTURE: + * + * TC3xx + * + * UC FAMILY: + * + * TC39x + * + * DESCRIPTION: + * + * Application linker file describing only elements used in BSP example + * to keep the file as simple as possible. + * It locates object sections to memory regions defined in _memory + * linker file via predefined ALIASES. + * + * FILE HISTORY: + * + * V1 05.2020 RO + * - Base reference example + * + ************************************************************************************************** + * Copyright (C) 2015-2020 HighTec EDV-Systeme GmbH. All rights reserved. + * This is proprietary software. Any use of the software requires a written + * license agreement with HighTec EDV-Systeme GmbH. Please contact for + * detailed license information: info@hightec-rt.com. + *************************************************************************************************/ + + +/* ================================================================================================ + * PREDEFINED OUTPUT SECTIONS TO MEMORY REGION ALIASES + * Aliases allow a quick change in memory placement + * ==============================================================================================*/ + +/* BMHD sections */ +REGION_ALIAS("BMHD_ORIG", ucb_bmhd_orig) +REGION_ALIAS("BMHD_COPY", ucb_bmhd_copy) + +/* CRT0 Boot Code Start */ +REGION_ALIAS("BOOT", int_flash0) + +/* BSP Interrupt handler table in RAM */ +REGION_ALIAS("BSP_ISR_HANDLERS_CPU0_", pspr_cpu0) +REGION_ALIAS("BSP_ISR_HANDLERS_CPU1_", pspr_cpu1) +REGION_ALIAS("BSP_ISR_HANDLERS_CPU2_", pspr_cpu2) +REGION_ALIAS("BSP_ISR_HANDLERS_CPU3_", pspr_cpu3) +REGION_ALIAS("BSP_ISR_HANDLERS_CPU4_", pspr_cpu4) +REGION_ALIAS("BSP_ISR_HANDLERS_CPU5_", pspr_cpu5) + +/* Core0: Output sections to memory region mapping */ +REGION_ALIAS("CODE_CPU0_", int_flash0) +REGION_ALIAS("RODATA_CPU0_", int_flash0) +REGION_ALIAS("RAMCODE_CPU0_", pspr_cpu0) +REGION_ALIAS("DATA_DSPR_CPU0_", dspr_cpu0) +REGION_ALIAS("DATA_DLMU_CPU0_", dlmu_cpu0) + +/* Core1: Output sections to memory region mapping */ +REGION_ALIAS("CODE_CPU1_", int_flash1) +REGION_ALIAS("RODATA_CPU1_", int_flash1) +REGION_ALIAS("RAMCODE_CPU1_", pspr_cpu1) +REGION_ALIAS("DATA_DSPR_CPU1_", dspr_cpu1) +REGION_ALIAS("DATA_DLMU_CPU1_", dlmu_cpu1) + +/* Core2: Output sections to memory region mapping */ +REGION_ALIAS("CODE_CPU2_", int_flash2) +REGION_ALIAS("RODATA_CPU2_", int_flash2) +REGION_ALIAS("RAMCODE_CPU2_", pspr_cpu2) +REGION_ALIAS("DATA_DSPR_CPU2_", dspr_cpu2) +REGION_ALIAS("DATA_DLMU_CPU2_", dlmu_cpu2) + +/* Core3: Output sections to memory region mapping */ +REGION_ALIAS("CODE_CPU3_", int_flash3) +REGION_ALIAS("RODATA_CPU3_", int_flash3) +REGION_ALIAS("RAMCODE_CPU3_", pspr_cpu3) +REGION_ALIAS("DATA_DSPR_CPU3_", dspr_cpu3) +REGION_ALIAS("DATA_DLMU_CPU3_", dlmu_cpu3) + +/* Core4: Output sections to memory region mapping */ +REGION_ALIAS("CODE_CPU4_", int_flash4) +REGION_ALIAS("RODATA_CPU4_", int_flash4) +REGION_ALIAS("RAMCODE_CPU4_", pspr_cpu4) +REGION_ALIAS("DATA_DSPR_CPU4_", dspr_cpu4) +REGION_ALIAS("DATA_DLMU_CPU4_", dlmu_cpu4) + +/* Core5: Output sections to memory region mapping */ +REGION_ALIAS("CODE_CPU5_", int_flash5) +REGION_ALIAS("RODATA_CPU5_", int_flash5) +REGION_ALIAS("RAMCODE_CPU5_", pspr_cpu5) +REGION_ALIAS("DATA_DSPR_CPU5_", dspr_cpu5) +REGION_ALIAS("DATA_DLMU_CPU5_", dlmu_cpu5) + +/* Common code and data */ +REGION_ALIAS("CODE", int_flash0) +REGION_ALIAS("RODATA", int_flash0) +REGION_ALIAS("DATA", lmu0_noncached) +REGION_ALIAS("RAM_CODE", lmu0_noncached) + + +/* ================================================================================================ + * PREDEFINED CONSTANTS + * ==============================================================================================*/ + +/* Shared Global Stack as defined by AURIX architecture (PSW.IS = 1) + * the User stack is left on eventual User or RTOS control (PSW.IS = 0) + */ +SHARED_STACK_SIZE = 4K; + +/* CSA dedicated memory region size defined as + * (Number of CSA regions x CSA entry size) where 256 entries is Maximum + */ +CSA_REGIONS = 256; +CSA_SIZE = CSA_REGIONS * 64; + +/* General HEAP is case one uses certain stdlib functions */ +__HEAP_SIZE = DEFINED (__HEAP_SIZE) ? __HEAP_SIZE : 4K; + + +/* ================================================================================================ + * SECTIONS: BMHD headers + * ==============================================================================================*/ + +SECTIONS +{ + /* Boot Mode Header - original values */ + .bmhd_0_orig 0xaf400000 : { KEEP (*(.bmhd_0_orig)) } > BMHD_ORIG + .bmhd_1_orig 0xaf400200 : { KEEP (*(.bmhd_1_orig)) } > BMHD_ORIG + .bmhd_2_orig 0xaf400400 : { KEEP (*(.bmhd_2_orig)) } > BMHD_ORIG + .bmhd_3_orig 0xaf400600 : { KEEP (*(.bmhd_3_orig)) } > BMHD_ORIG + + /* Boot Mode Header - copy values */ + .bmhd_0_copy 0xaf401000 : { KEEP (*(.bmhd_0_copy)) } > BMHD_COPY + .bmhd_1_copy 0xaf401200 : { KEEP (*(.bmhd_1_copy)) } > BMHD_COPY + .bmhd_2_copy 0xaf401400 : { KEEP (*(.bmhd_2_copy)) } > BMHD_COPY + .bmhd_3_copy 0xaf401600 : { KEEP (*(.bmhd_3_copy)) } > BMHD_COPY +} + + +/* ================================================================================================ + * SECTIONS: Application BOOT code + * Address pointed by BMHD start address value + * ==============================================================================================*/ + +SECTIONS +{ + .crt0_boot : { KEEP (*(.crt0_boot.code)) } > BOOT +} + + +/* ================================================================================================ + * SECTIONS: Reset Default TRAP handlers provided by BSP + * the TRAP table is shared across cores + * BTV register value after reset is 0xA0000100 (0x80000100) + * ==============================================================================================*/ + +SECTIONS +{ + .bsp_trap_reset 0x80000100 : + { + KEEP (*(.bsp_trap_vector_table)) + KEEP (*(.bsp_trap_handlers)) + } > CODE_CPU0_ +} + + +/* ================================================================================================ + * SECTIONS: BSP Interrupt tables + * BSP provided Interrupt vector table and ISR Handler tables for each core + * BSP code set BIV register to core corresponding Base address + * ==============================================================================================*/ + +SECTIONS +{ + .CPU0.bsp_isr_vector_table : { KEEP (*(.bsp_isr_vector_table_cpu0)) } > CODE_CPU0_ + .CPU1.bsp_isr_vector_table : { KEEP (*(.bsp_isr_vector_table_cpu1)) } > CODE_CPU1_ + .CPU2.bsp_isr_vector_table : { KEEP (*(.bsp_isr_vector_table_cpu2)) } > CODE_CPU2_ + .CPU3.bsp_isr_vector_table : { KEEP (*(.bsp_isr_vector_table_cpu3)) } > CODE_CPU3_ + .CPU4.bsp_isr_vector_table : { KEEP (*(.bsp_isr_vector_table_cpu4)) } > CODE_CPU4_ + .CPU5.bsp_isr_vector_table : { KEEP (*(.bsp_isr_vector_table_cpu5)) } > CODE_CPU5_ +} + +SECTIONS +{ + .CPU0.bsp_isr_ram_table (NOLOAD) : { *(.BspIsrRamTable_Cpu0) } > BSP_ISR_HANDLERS_CPU0_ + .CPU1.bsp_isr_ram_table (NOLOAD) : { *(.BspIsrRamTable_Cpu1) } > BSP_ISR_HANDLERS_CPU1_ + .CPU2.bsp_isr_ram_table (NOLOAD) : { *(.BspIsrRamTable_Cpu2) } > BSP_ISR_HANDLERS_CPU2_ + .CPU3.bsp_isr_ram_table (NOLOAD) : { *(.BspIsrRamTable_Cpu3) } > BSP_ISR_HANDLERS_CPU3_ + .CPU4.bsp_isr_ram_table (NOLOAD) : { *(.BspIsrRamTable_Cpu4) } > BSP_ISR_HANDLERS_CPU4_ + .CPU5.bsp_isr_ram_table (NOLOAD) : { *(.BspIsrRamTable_Cpu5) } > BSP_ISR_HANDLERS_CPU5_ +} + + +/* ================================================================================================ + * SECTIONS: Cores' CSA regions + * Each core has its own CSA region list + * ==============================================================================================*/ + +SECTIONS +{ + .CPU0.csa (NOLOAD) : { . = ALIGN(64); __CSA_BASE_CPU0_ = .; . += CSA_SIZE; } > DATA_DSPR_CPU0_ + .CPU1.csa (NOLOAD) : { . = ALIGN(64); __CSA_BASE_CPU1_ = .; . += CSA_SIZE; } > DATA_DSPR_CPU1_ + .CPU2.csa (NOLOAD) : { . = ALIGN(64); __CSA_BASE_CPU2_ = .; . += CSA_SIZE; } > DATA_DSPR_CPU2_ + .CPU3.csa (NOLOAD) : { . = ALIGN(64); __CSA_BASE_CPU3_ = .; . += CSA_SIZE; } > DATA_DSPR_CPU3_ + .CPU4.csa (NOLOAD) : { . = ALIGN(64); __CSA_BASE_CPU4_ = .; . += CSA_SIZE; } > DATA_DSPR_CPU4_ + .CPU5.csa (NOLOAD) : { . = ALIGN(64); __CSA_BASE_CPU5_ = .; . += CSA_SIZE; } > DATA_DSPR_CPU5_ +} + + +/* ================================================================================================ + * SECTIONS: Cores' Shared Stacks + * Each core has its own Shared stack area (PSW.IS = 1) + * ==============================================================================================*/ + +SECTIONS +{ + .CPU0.stack (NOLOAD) : { . = ALIGN(8); __STACK_BASE_CPU0_ = .; . += SHARED_STACK_SIZE; } > DATA_DSPR_CPU0_ + .CPU1.stack (NOLOAD) : { . = ALIGN(8); __STACK_BASE_CPU1_ = .; . += SHARED_STACK_SIZE; } > DATA_DSPR_CPU1_ + .CPU2.stack (NOLOAD) : { . = ALIGN(8); __STACK_BASE_CPU2_ = .; . += SHARED_STACK_SIZE; } > DATA_DSPR_CPU2_ + .CPU3.stack (NOLOAD) : { . = ALIGN(8); __STACK_BASE_CPU3_ = .; . += SHARED_STACK_SIZE; } > DATA_DSPR_CPU3_ + .CPU4.stack (NOLOAD) : { . = ALIGN(8); __STACK_BASE_CPU4_ = .; . += SHARED_STACK_SIZE; } > DATA_DSPR_CPU4_ + .CPU5.stack (NOLOAD) : { . = ALIGN(8); __STACK_BASE_CPU5_ = .; . += SHARED_STACK_SIZE; } > DATA_DSPR_CPU5_ +} + + +/* ================================================================================================ + * SECTIONS: CORE 0 dedicated sections + * In the example they are Empty, but user might used them to play + * with core specific placement + * ==============================================================================================*/ + +SECTIONS +{ + .CPU0.code : { } > CODE_CPU0_ + .CPU0.ramcode : { } > RAMCODE_CPU0_ AT > RODATA_CPU0_ + .CPU0.rodata : { } > RODATA_CPU0_ + .CPU0.data : { } > DATA_DSPR_CPU0_ AT > RODATA_CPU0_ + .CPU0.bss (NOLOAD): { } > DATA_DSPR_CPU0_ +} + + +/* ================================================================================================ + * SECTIONS: CORE 1 dedicated sections + * In the example they are Empty, but user might used them to play + * with core specific placement + * ==============================================================================================*/ + +SECTIONS +{ + .CPU1.code : { } > CODE_CPU1_ + .CPU1.ramcode : { } > RAMCODE_CPU1_ AT > RODATA_CPU1_ + .CPU1.rodata : { } > RODATA_CPU1_ + .CPU1.data : { } > DATA_DSPR_CPU1_ AT > RODATA_CPU1_ + .CPU1.bss (NOLOAD): { } > DATA_DSPR_CPU1_ +} + + +/* ================================================================================================ + * SECTIONS: CORE 2 dedicated sections + * In the example they are Empty, but user might used them to play + * with core specific placement + * ==============================================================================================*/ + +SECTIONS +{ + .CPU2.code : { } > CODE_CPU2_ + .CPU2.ramcode : { } > RAMCODE_CPU2_ AT > RODATA_CPU2_ + .CPU2.rodata : { } > RODATA_CPU2_ + .CPU2.data : { } > DATA_DSPR_CPU2_ AT > RODATA_CPU2_ + .CPU2.bss (NOLOAD): { } > DATA_DSPR_CPU2_ +} + + +/* ================================================================================================ + * SECTIONS: CORE 3 dedicated sections + * In the example they are Empty, but user might used them to play + * with core specific placement + * ==============================================================================================*/ + +SECTIONS +{ + .CPU3.code : { } > CODE_CPU3_ + .CPU3.ramcode : { } > RAMCODE_CPU3_ AT > RODATA_CPU3_ + .CPU3.rodata : { } > RODATA_CPU3_ + .CPU3.data : { } > DATA_DSPR_CPU3_ AT > RODATA_CPU3_ + .CPU3.bss (NOLOAD) : { } > DATA_DSPR_CPU3_ +} + + +/* ================================================================================================ + * SECTIONS: CORE 4 dedicated sections + * In the example they are Empty, but user might used them to play + * with core specific placement + * ==============================================================================================*/ + +SECTIONS +{ + .CPU4.code : { } > CODE_CPU4_ + .CPU4.ramcode : { } > RAMCODE_CPU4_ AT > RODATA_CPU4_ + .CPU4.rodata : { } > RODATA_CPU4_ + .CPU4.data : { } > DATA_DSPR_CPU4_ AT > RODATA_CPU4_ + .CPU4.bss (NOLOAD) : { } > DATA_DSPR_CPU4_ +} + + +/* ================================================================================================ + * SECTIONS: CORE 5 dedicated sections + * In the example they are Empty, but user might used them to play + * with core specific placement + * ==============================================================================================*/ + +SECTIONS +{ + .CPU5.code : { } > CODE_CPU5_ + .CPU5.ramcode : { } > RAMCODE_CPU5_ AT > RODATA_CPU5_ + .CPU5.rodata : { } > RODATA_CPU5_ + .CPU5.data : { } > DATA_DSPR_CPU5_ AT > RODATA_CPU5_ + .CPU5.bss (NOLOAD) : { } > DATA_DSPR_CPU5_ +} + + +/* ================================================================================================ + * SECTIONS: COMMON (shared) sections + * by default, all example sections are located here + * ==============================================================================================*/ + +SECTIONS +{ + /* Code sections */ + .code : + { + *(.text*) + } > CODE + + /* code to execute from RAM */ + .ramcode : + { + *(.ramcode*) + } > RAM_CODE AT > RODATA + + /* read-only data, constants */ + .rodata : + { + *(.rodata*) + } > RODATA + + /* C++ constructors */ + .ctors : ALIGN(4) + { + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + KEEP (*(.ctors)); + LONG(0); + __CTOR_END__ = .; + } > RODATA + + /* Short-addressable read-only data */ + .sdata2 : + { + *(.sdata2*) + } > RODATA + + /* Short-addresable read-write data - initialized */ + .sdata : + { + *(.sdata*) + } > DATA AT > RODATA + + /* Short-addresable read-write data - non-initialized (zeroed) */ + .sbss (NOLOAD): + { + *(.sbss*) + } > DATA + + /* read-write data - initialized */ + .data : + { + *(.data*) + } > DATA AT > RODATA + + /* read-write data - non-initialized */ + .bss : + { + *(.bss*); + *(COMMON); + } > DATA + + /* HEAP area for stdlib functions */ + .heap : ALIGN(8) + { + . += __HEAP_SIZE; + } > DATA +} + + +/* ================================================================================================ + * SECTIONS: CLEAR & COPY TABLES with END delimiter to support crt0 init + * clear_table: + * data memory ranges to clear to zero + * copy_table: + * data memory ranges that needs to be value initialized + * (init values are stored in FLASH and copied to RAM) + * Each core has its own table to process during its init to allow multicore execution. + * Shared resources are inserted to Core[0] tables (the RESET core) + * ==============================================================================================*/ +SECTIONS +{ + /*-------------------------------------------------------------------------------------------*/ + + .CPU0.clear_sec : ALIGN(4) + { + LONG(ADDR(.CPU0.bss)); LONG(SIZEOF(.CPU0.bss)); + LONG(ADDR(.sbss)); LONG(SIZEOF(.sbss)); + LONG(ADDR(.bss)); LONG(SIZEOF(.bss)); + LONG(ADDR(.heap)); LONG(SIZEOF(.heap)); + LONG(-1); LONG(-1); + } > RODATA_CPU0_ + + .CPU0.copy_sec : ALIGN(4) + { + LONG(LOADADDR(.CPU0.ramcode)); LONG(ADDR(.CPU0.ramcode)); LONG(SIZEOF(.CPU0.ramcode)); + LONG(LOADADDR(.CPU0.data)); LONG(ADDR(.CPU0.data)); LONG(SIZEOF(.CPU0.data)); + LONG(LOADADDR(.ramcode)); LONG(ADDR(.ramcode)); LONG(SIZEOF(.ramcode)); + LONG(LOADADDR(.sdata)); LONG(ADDR(.sdata)); LONG(SIZEOF(.sdata)); + LONG(LOADADDR(.data)); LONG(ADDR(.data)); LONG(SIZEOF(.data)); + LONG(-1); LONG(-1); LONG(-1); + } > RODATA_CPU0_ + + /*-------------------------------------------------------------------------------------------*/ + + .CPU1.clear_sec : ALIGN(4) + { + LONG(ADDR(.CPU1.bss)); LONG(SIZEOF(.CPU1.bss)); + LONG(-1); LONG(-1); + } > RODATA_CPU1_ + + .CPU1.copy_sec : ALIGN(4) + { + LONG(LOADADDR(.CPU1.ramcode)); LONG(0 + ADDR(.CPU1.ramcode)); LONG(SIZEOF(.CPU1.ramcode)); + LONG(LOADADDR(.CPU1.data)); LONG(ADDR(.CPU1.data)); LONG(SIZEOF(.CPU1.data)); + LONG(-1); LONG(-1); LONG(-1); + } > RODATA_CPU1_ + + /*-------------------------------------------------------------------------------------------*/ + + .CPU2.clear_sec : ALIGN(4) + { + LONG(ADDR(.CPU2.bss)); LONG(SIZEOF(.CPU2.bss)); + LONG(-1); LONG(-1); + } > RODATA_CPU2_ + + .CPU2.copy_sec : ALIGN(4) + { + LONG(LOADADDR(.CPU2.ramcode)); LONG(0 + ADDR(.CPU2.ramcode)); LONG(SIZEOF(.CPU2.ramcode)); + LONG(LOADADDR(.CPU2.data)); LONG(0 + ADDR(.CPU2.data)); LONG(SIZEOF(.CPU2.data)); + LONG(-1); LONG(-1); LONG(-1); + } > RODATA_CPU2_ + + /*-------------------------------------------------------------------------------------------*/ + + .CPU3.clear_sec : ALIGN(4) + { + LONG(ADDR(.CPU3.bss)); LONG(SIZEOF(.CPU3.bss)); + LONG(-1); LONG(-1); + } > RODATA_CPU3_ + + .CPU3.copy_sec : ALIGN(4) + { + LONG(LOADADDR(.CPU3.ramcode)); LONG(0 + ADDR(.CPU3.ramcode)); LONG(SIZEOF(.CPU3.ramcode)); + LONG(LOADADDR(.CPU3.data)); LONG(0 + ADDR(.CPU3.data)); LONG(SIZEOF(.CPU3.data)); + LONG(-1); LONG(-1); LONG(-1); + } > RODATA_CPU3_ + + /*-------------------------------------------------------------------------------------------*/ + + .CPU4.clear_sec : ALIGN(4) + { + LONG(ADDR(.CPU4.bss)); LONG(SIZEOF(.CPU4.bss)); + LONG(-1); LONG(-1); + } > RODATA_CPU4_ + + .CPU4.copy_sec : ALIGN(4) + { + LONG(LOADADDR(.CPU4.ramcode)); LONG(0 + ADDR(.CPU4.ramcode)); LONG(SIZEOF(.CPU4.ramcode)); + LONG(LOADADDR(.CPU4.data)); LONG(0 + ADDR(.CPU4.data)); LONG(SIZEOF(.CPU4.data)); + LONG(-1); LONG(-1); LONG(-1); + } > RODATA_CPU4_ + + /*-------------------------------------------------------------------------------------------*/ + + .CPU5.clear_sec : ALIGN(4) + { + LONG(ADDR(.CPU5.bss)); LONG(SIZEOF(.CPU5.bss)); + LONG(-1); LONG(-1); + } > RODATA_CPU5_ + + .CPU5.copy_sec : ALIGN(4) + { + LONG(LOADADDR(.CPU5.ramcode)); LONG(0 + ADDR(.CPU5.ramcode)); LONG(SIZEOF(.CPU5.ramcode)); + LONG(LOADADDR(.CPU5.data)); LONG(0 + ADDR(.CPU5.data)); LONG(SIZEOF(.CPU5.data)); + LONG(-1); LONG(-1); LONG(-1); + } > RODATA_CPU5_ +} + + +/* ================================================================================================ + * Linker Symbols + * ==============================================================================================*/ + +/* Read only small address pointer */ +_SMALL_DATA2_ = ADDR(.sdata2) + 0x8000; + +/* Volatile data short address pointer (.sdata before .sbss) */ +_SMALL_DATA_ = ADDR(.sdata) + 0x8000; + +/* Expected HEAP SYMBOLS */ +__HEAP = ADDR(.heap); +__HEAP_END = SIZEOF(.heap); + + +/* ================================================================================================ + * CRT0 CONFIG STRUCTURE + * Initialization structure for uC Cores used in crt0 startup code + * Each core has itw one table entry. + * ==============================================================================================*/ + +SECTIONS +{ + .crt0_config : ALIGN(4) + { + PROVIDE(__crt0_config = .); /* base of the crt0 config table */ + + /* Core[0] */ + LONG(ADDR(.CPU0.stack)); /* STACK address */ + LONG(SIZEOF(.CPU0.stack)); /* STACK size */ + LONG(ADDR(.CPU0.csa)); /* CSA address */ + LONG(SIZEOF(.CPU0.csa)); /* CSA size */ + LONG(_SMALL_DATA_); /* SDATA address */ + LONG(_SMALL_DATA2_); /* SDATA2 address */ + LONG(0); /* SDATA3 address */ + LONG(0); /* SDATA4 address */ + LONG(ADDR(.CPU0.clear_sec)); /* CLEAR table */ + LONG(ADDR(.CPU0.copy_sec)); /* COPY table */ + LONG(__CTOR_LIST__); /* CTOR table */ + + /* Core[1] */ + LONG(ADDR(.CPU1.stack)); /* STACK address */ + LONG(SIZEOF(.CPU1.stack)); /* STACK size */ + LONG(ADDR(.CPU1.csa)); /* CSA address */ + LONG(SIZEOF(.CPU1.csa)); /* CSA size */ + LONG(_SMALL_DATA_); /* SDATA address */ + LONG(_SMALL_DATA2_); /* SDATA2 address */ + LONG(0); /* SDATA3 address */ + LONG(0); /* SDATA4 address */ + LONG(ADDR(.CPU1.clear_sec) ); /* CLEAR table */ + LONG(ADDR(.CPU1.copy_sec)); /* COPY table */ + LONG(0); /* CTOR table */ + + /* Core[2] */ + LONG(ADDR(.CPU2.stack)); /* STACK address */ + LONG(SIZEOF(.CPU2.stack)); /* STACK size */ + LONG(ADDR(.CPU2.csa)); /* CSA address */ + LONG(SIZEOF(.CPU2.csa)); /* CSA size */ + LONG(_SMALL_DATA_); /* SDATA address */ + LONG(_SMALL_DATA2_); /* SDATA2 address */ + LONG(0); /* SDATA3 address */ + LONG(0); /* SDATA4 address */ + LONG(ADDR(.CPU2.clear_sec)); /* CLEAR table */ + LONG(ADDR(.CPU2.copy_sec)); /* COPY table */ + LONG(0); /* CTOR table */ + + /* Core[3] */ + LONG(ADDR(.CPU3.stack)); /* STACK address */ + LONG(SIZEOF(.CPU3.stack)); /* STACK size */ + LONG(ADDR(.CPU3.csa)); /* CSA address */ + LONG(SIZEOF(.CPU3.csa)); /* CSA size */ + LONG(_SMALL_DATA_); /* SDATA address */ + LONG(_SMALL_DATA2_); /* SDATA3 address */ + LONG(0); /* SDATA3 address */ + LONG(0); /* SDATA4 address */ + LONG(ADDR(.CPU3.clear_sec)); /* CLEAR table */ + LONG(ADDR(.CPU3.copy_sec)); /* COPY table */ + LONG(0); /* CTOR table */ + + /* Core[4] */ + LONG(ADDR(.CPU4.stack)); /* STACK address */ + LONG(SIZEOF(.CPU4.stack)); /* STACK size */ + LONG(ADDR(.CPU4.csa)); /* CSA address */ + LONG(SIZEOF(.CPU4.csa)); /* CSA size */ + LONG(_SMALL_DATA_); /* SDATA address */ + LONG(_SMALL_DATA2_); /* SDATA3 address */ + LONG(0); /* SDATA3 address */ + LONG(0); /* SDATA4 address */ + LONG(ADDR(.CPU4.clear_sec)); /* CLEAR table */ + LONG(ADDR(.CPU4.copy_sec)); /* COPY table */ + LONG(0); /* CTOR table */ + + /* Dummy entry due to CoreId index gap in TC39x */ + LONG(0); /* STACK address */ + LONG(0); /* STACK size */ + LONG(0); /* CSA address */ + LONG(0); /* CSA size */ + LONG(0); /* SDATA address */ + LONG(0); /* SDATA3 address */ + LONG(0); /* SDATA3 address */ + LONG(0); /* SDATA4 address */ + LONG(0); /* CLEAR table */ + LONG(0); /* COPY table */ + LONG(0); /* CTOR table */ + + /* Core[5] */ + LONG(ADDR(.CPU5.stack)); /* STACK address */ + LONG(SIZEOF(.CPU5.stack)); /* STACK size */ + LONG(ADDR(.CPU5.csa)); /* CSA address */ + LONG(SIZEOF(.CPU5.csa)); /* CSA size */ + LONG(_SMALL_DATA_); /* SDATA address */ + LONG(_SMALL_DATA2_); /* SDATA3 address */ + LONG(0); /* SDATA3 address */ + LONG(0); /* SDATA4 address */ + LONG(ADDR(.CPU5.clear_sec)); /* CLEAR table */ + LONG(ADDR(.CPU5.copy_sec)); /* COPY table */ + LONG(0); /* CTOR table */ + + } > RODATA +} + + +/* ================================================================================================ + * DWARF debug sections and others + * Symbols in the DWARF debugging sections are relative to the + * beginning of the section, so we begin them at 0. + * ==============================================================================================*/ + +SECTIONS +{ + /* DWARF 1 */ + .comment 0 : { *(.comment) } + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_ranges 0 : { *(.debug_ranges) } + + /* DWARF 2 control flow extension */ + .debug_control_flow 0 : { *(.debug_control_flow) } + + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + .version_info 0 : { *(.version_info) } + + .eh_frame 0 : { *(.eh_frame) } > CODE +} diff --git a/tests/resources/project_files_aurix/rust-toolchain.toml b/tests/resources/project_files_aurix/rust-toolchain.toml new file mode 100644 index 0000000..e9c1e54 --- /dev/null +++ b/tests/resources/project_files_aurix/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "tricore-htc-none-v0.2.0" + diff --git a/tests/resources/project_files_aurix/src/bin/main.rs b/tests/resources/project_files_aurix/src/bin/main.rs new file mode 100644 index 0000000..74aef9f --- /dev/null +++ b/tests/resources/project_files_aurix/src/bin/main.rs @@ -0,0 +1,97 @@ +#![no_std] +#![no_main] + +use arm_example::{timer::bitfield_reg, *}; +use tc162_rt::entry; +entry!(main); +fn main() -> ! { + unsafe { + //Verbose read modify + let register = TIMER.bitfield_reg(); + let register_value = register.read(); + let _bitfield_value = register_value.bitfieldr().get(); + // Modify value of register using fluent api + let new_register_value = register_value.bitfieldrw().set(23).bitfieldw().set(23); + register.write(new_register_value); + + // Register without bitfield + let register_value = TIMER.nobitfield_reg().read(); + let _numeric_value = register_value.get(); + let _modified_register_value = register_value.set(23); + + // Modify + TIMER.bitfield_reg().modify(|f| { + f.bitfieldenumerated() + .set(bitfield_reg::BitfieldEnumerated::GPIOA_0) + .bitfieldw() + .set(3) + }); + + // init + TIMER.bitfield_reg().init(|f| { + f.bitfieldenumerated() + .set(bitfield_reg::BitfieldEnumerated::GPIOA_0) + .bitfieldw() + .set(3) + }); + + // Modify atomic only 32bit registers + TIMER.bitfield_reg().modify_atomic(|f| { + f.bitfieldenumerated() + .set(bitfield_reg::BitfieldEnumerated::GPIOA_0) + .bitfieldw() + .set(25) + }); + + // Array of register bitfields + let mut a = TIMER.bitfield_reg().read(); + for x in 0..2 { + a = a.fieldarray(x).set(bitfield_reg::FieldArray::FALLING); + } + TIMER.bitfield_reg().write(a); + + // Array of registers + let r = TIMER.arrayreg(); + for r in r.iter().take(2) { + let reg_val = r.read(); + let old_val = reg_val.get(); + r.write(reg_val.set(old_val + 1)); + } + + TIMER.arrayreg()[2].modify_atomic(|f| f.set(24)); + + // Array of peripherals + for peri in UART { + peri.reg16bitenum().modify(|f| { + f.bitfield9bitsenum() + .set(uart::reg16bitenum::Bitfield9BitsEnum::VAL_0) + }); + } + + //Raw bitfield write. How to write an enumerated bitifield with a value listed in the enumeration + TIMER.bitfield_reg().modify(|f| { + f.bitfieldenumerated() + .set(bitfield_reg::BitfieldEnumerated::new(3)) + .bitfieldw() + .set(3) + }); + + //Tests related to csfr registers + let register = CSFR_CPU.biv(); + let register_value = register.read(); + let _biv_value = register_value.biv().get(); + + // Modify value of register using fluent api + let new_register_value = register_value.biv().set(23).vss().set(true); + register.write(new_register_value); + + // Modify + CSFR_CPU.biv().modify(|f| { + f.vss() + .set(true) + .biv() + .set(3) + }); + } + loop {} +} diff --git a/tests/resources/project_files_aurix/tc162-rt/.cargo/config b/tests/resources/project_files_aurix/tc162-rt/.cargo/config new file mode 100644 index 0000000..681e3a8 --- /dev/null +++ b/tests/resources/project_files_aurix/tc162-rt/.cargo/config @@ -0,0 +1,12 @@ +[target.tc162-htc-none] +rustflags = ["-C", "link-args=-Tlink.x -Map map"] +linker = "rust-lld.exe" + +[build] +target = "tc162-htc-none" + +[env] +CC_tc162_htc_none = "clang" +CFLAGS_tc162_htc_none = "-target tricore -march=tc162" +AR_tc162_htc_none = "llvm-ar" +ARFLAGS_tc162_htc_none = "r" \ No newline at end of file diff --git a/tests/resources/project_files_aurix/tc162-rt/.gitignore b/tests/resources/project_files_aurix/tc162-rt/.gitignore new file mode 100644 index 0000000..4fffb2f --- /dev/null +++ b/tests/resources/project_files_aurix/tc162-rt/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/tests/resources/project_files_aurix/tc162-rt/Cargo.toml b/tests/resources/project_files_aurix/tc162-rt/Cargo.toml new file mode 100644 index 0000000..a6d296a --- /dev/null +++ b/tests/resources/project_files_aurix/tc162-rt/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "tc162-rt" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/tests/resources/project_files_aurix/tc162-rt/README.md b/tests/resources/project_files_aurix/tc162-rt/README.md new file mode 100644 index 0000000..321b185 --- /dev/null +++ b/tests/resources/project_files_aurix/tc162-rt/README.md @@ -0,0 +1,15 @@ +# `tc162-rt` + +> Startup code and minimal runtime for TC162 TriCore(TM) microcontroller architecture + +This project is developed and maintained by the HighTec EVD. + +# Minimum Supported Rust Version (MSRV) + +This crate is guaranteed to compile on stable Rust 1.65.0 and up. It *might* +compile with older versions but that may change in any new patch release. + +# License + +The source code is under the Apache License v2.0 with LLVM Exceptions. +See ([LICENSE-APACHE](LICENSE-APACHE) or https://llvm.org/LICENSE.txt) for license information. \ No newline at end of file diff --git a/tests/resources/project_files_aurix/tc162-rt/src/lib.rs b/tests/resources/project_files_aurix/tc162-rt/src/lib.rs new file mode 100644 index 0000000..0d7e7b0 --- /dev/null +++ b/tests/resources/project_files_aurix/tc162-rt/src/lib.rs @@ -0,0 +1,588 @@ +//! Startup code and minimal runtime for TriCore(TM) TC162 microcontrollers +//! +//! This crate contains all the required parts to build a `no_std` application (binary crate) that +//! targets a TC3xx AURIX(TM) microcontroller family. +//! +//! ARCHITECTURE: TC162 +//! +//! UC FAMILY: TC3xx +//! +//! # Features +//! +//! This crate takes care of: +//! +//! - C/C++/RUST runtime environment startup file. +//! +//! - To initialize ABI registers +//! - To initialize CSA context area +//! - To initialize Stack area needed for 'C' code +//! - To initialize ECC in RAM memories (not done for AURIX) +//! - To clear BSS (not-initialized) data +//! - To initialize DATA (initialized) data +//! - To initialize C++ global object instances +//! - To provide startup hooks for user defined code +//! +//! ## Multicore Startup +//! +//! Crt0 startup on multicore systems is driven by a configuration provided by a corresponding +//! linker file. Configuration table contains one entry for each Core present in uC +//! +//! ## Startup Hooks +//! +//! Crt0 provides two startup hooks the user can use to implement system dependent early HW +//! initialization. +//! +//! ### 'Crt0PreInit()' hook called +//! - after STACK area and CSA list on given core is initialized +//! - before Clear and Copy table operation is executed +//! ! HW initialization code cannot rely on global data (BSS or DATA) +//! +//! ### 'Crt0PostInit()' hook called +//! - when all startup initialization is finished (data can be used) +//! - before calling shared_main() application entry point +//! +//! ## C++ support +//! The crt0 startup code provides a default global object initialization based on ctor table +//! registered per core. +//! The format of 'ctor' table expected: +//! ctor_setion +//! { +//! __CTOR_LIST__ = .; +//! LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) +//! KEEP (*(.ctors)); +//! LONG(0); +//! __CTOR_END__ = .; +//! } +//! By default, the linker gathers all C++ module ctor entries into one common ctor table. In case +//! of multicore object initialization, the user must provide their system of CTOR initialization. +//! +//! ## Application specific crt0 Routines Implementation] +//! Startup routines are implemented as WEAK functions to allow application-specific replacement +//! in case of need. +//! - Crt0BssInit +//! - Crt0DataInit +//! - Crt0CtorInit +//! - Crt0PreInit +//! - Crt0PostInit +//! +//! # FILE HISTORY: +//! +//! V1 01.2023 MF +//! - Base reference example +//! +// ************************************************************************************************* +// Copyright (C) 2015-2023 HighTec EDV-Systeme GmbH. All rights reserved. +// This is proprietary software. Any use of the software requires a written +// license agreement with HighTec EDV-Systeme GmbH. Please contact for +// detailed license information: info@hightec-rt.com. +// ************************************************************************************************* +#![no_std] + +use core::arch::global_asm; +use core::panic::PanicInfo; + +extern "C" { + pub fn _exit(status: u32) -> !; +} + + +#[panic_handler] +fn panic(_panic: &PanicInfo<'_>) -> ! { + loop { + unsafe { _exit(0xff); } + } +} + +#[macro_export] +macro_rules! entry { + ($path:path) => { + #[export_name = "main"] + pub unsafe fn __main() -> ! { + // type check the given path + let f: fn() -> ! = $path; + + f() + } + } +} + +#[no_mangle] +pub unsafe fn abort() -> ! { + _exit (0xff); +} + +/// Parse cfg attributes inside a global_asm call. +macro_rules! cfg_global_asm { + {@inner, [$($x:tt)*], } => { + global_asm!{$($x)*} + }; + (@inner, [$($x:tt)*], #[cfg($meta:meta)] $asm:literal, $($rest:tt)*) => { + #[cfg($meta)] + cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*} + #[cfg(not($meta))] + cfg_global_asm!{@inner, [$($x)*], $($rest)*} + }; + {@inner, [$($x:tt)*], $asm:literal, $($rest:tt)*} => { + cfg_global_asm!{@inner, [$($x)* $asm,], $($rest)*} + }; + {$($asms:tt)*} => { + cfg_global_asm!{@inner, [], $($asms)*} + }; +} + +cfg_global_asm!{ + // SYMBOLS & DEFINES & MACROS + // crt0_config : Entry offsets + // Must correspond to __crt0_config structure defined in the Linker file + ".equ STACK, 0x00 + .equ STACK_SIZE, 0x04 + .equ CSA, 0x08 + .equ CSA_SIZE, 0x0C + .equ SDATA, 0x10 + .equ SDATA2, 0x14 + .equ SDATA3, 0x18 + .equ SDATA4, 0x1C + .equ CLEAR_TABLE, 0x20 + .equ COPY_TABLE, 0x24 + .equ CTOR_TABLE, 0x28 + .equ CPUINIT_SIZE, 0x2C", + + // CSA_ENTRY supportive symbols + // CSA_ENTRY_SIZE : in bytes, given by TC3xx architecture + // LW_OFFSET_SHIFT : Link Word, low part shift offset + ".equ CSA_ENTRY_SIZE, 64 + .equ LW_OFFSET_SHIFT, -6", + + // CLEAR_TABLE structure offsets + // Offsets must correspond to the Linker __clear_table structure + // Offsets are in bytes + // Structure + // 1. LONG : DST - Destaination base address + // 2. LONG : SIZE - number of data to clear (write 0) in bytes + ".equ CLEAR_TABLE_DST, 0x00 + .equ CLEAR_TABLE_SIZE, 0x04 + .equ CLEAR_TABLE_OFFSET, 0x08", // Size of one entry in bytes + + // COPY_TABLE structure offsets + // Offsets must correspond to the Linker __copy_table structure + // Offsets are in bytes + // Structure + // 0. LONG : SRC - Source address to copy data from + // 1. LONG : DST - Destaination address to copy data to + // 2. LONG : SIZE - number of data to copy in bytes + ".equ COPY_TABLE_SRC, 0x00 + .equ COPY_TABLE_DST, 0x04 + .equ COPY_TABLE_SIZE, 0x08 + .equ COPY_TABLE_OFFSET, 0x0C", // Size of one entry in bytes + + // EXTERNAL SYMBOLS REQUIRED BY CRT0 + // application shared main entry + ".extern main, STT_FUNC, 0", + + // crt0 config structure from linker + ".extern __crt0_config, STT_OBJECT, 0", + + // EXPORTED SYMBOLS FROM CRT0 + // _crt0_reset : reset entry point from where to start inactive cores + ".global _crt0_reset + .type _crt0_reset STT_FUNC", + + // _start : shared multicore crt0 startup code entry point + ".global _start + .type _start STT_FUNC", + + // CRT0 RESET VECTOR + // Here execution starts after the Reset. + // The first duty is to force eventual address segment change in Aurix core + // from non-cached memory to a cacheable one + ".section .crt0_boot.code, \"ax\" + _crt0_reset: + movh.a %a15, hi:_start + lea %a15, [%a15] lo:_start + ji %a15", + + // CRT0 STARTUP CODE + // A multicore shared code implementation of 'C' runtime intialization + // located in a standard .text section that might be in cacheable region + ".section .text, \"ax\" + _start:", + + // CRT0 CONFIG TABLE BASE POINTER SETUP + // Config table contains parameters controlling crt0 startup execution. + // It is prepared by the linker file with the knowledge of the final placement. + // Registers used by the crt0 startup code + // 'A14` : is used as Core Entry Base Pointer in crt0 configuration structure + // throughout the statup asm code. + // The A14 register value is saved by Aurix core in upper context during subroutine calls. + "movh.a %a14, hi:__crt0_config + lea %a14, [%a14]lo:__crt0_config + mfcr %d15, $core_id /* read CoreID(0xfe1c) SFR register */ + and %d15, 7 /* mask the lowest 3 bits */ + mul %d15, %d15, CPUINIT_SIZE /* get the core entry base address */ + addsc.a %a14, %a14, %d15, 0", + + // SMALL ADDRESS REGISTERS INIT + // Values given by crt0 configuration structure from the linker file. + // Four dedicated registers, if they are used + // a0 - usually small data (rw) + // a1 - usually small const data (r) + // a8 - usually OS / application specific + // a9 - usually OS / application specific + "mfcr %d15, $psw + or %d15, %d15, 0x7f + andn %d15, %d15, 0x80 + or %d15, %d15, 0x100 + mtcr $psw, %d15", + + "ld.w %d15, [%a14] SDATA + mov.a %a0, %d15 + ld.w %d15, [%a14] SDATA2 + mov.a %a1, %d15 + ld.w %d15, [%a14] SDATA3 + mov.a %a8, %d15 + ld.w %d15, [%a14] SDATA4 + mov.a %a9, %d15", + + "mfcr %d15, $psw + andn %d15, %d15, 0x100 + mtcr $psw, %d15", + + // CSA CONTEXT AREA INIT + // Linked list initialization of CSA entries (TriCore specific feature) used to save + // function context during standard 'C' function calls. + // CSA entry and linked list has fixed structure given by AURIX architecture. + // Number of CSA entries (max 256 entries) is part of crt0 configuration in the linker file. + "mov %d4, 0 + mtcr $pcxi, %d4 + ld.w %d4, [%a14] CSA_SIZE + sh %d4, %d4, LW_OFFSET_SHIFT + mov.a %a4, %d4 + add.a %a4, -1 + mov %d4, CSA_ENTRY_SIZE + mov.a %a3, %d4 + ld.a %a15, [%a14] CSA + movh %d5, 0x000F + mov.d %d15, %a15 + sh %d15, %d15, -12 + and %d15, %d5 + mov.u %d5, 0xFFFF + mov.d %d4, %a15 + sh %d4, %d4, LW_OFFSET_SHIFT + and %d4, %d5 + or %d4, %d15 + mtcr $fcx, %d4 + loop_csa: + add %d4, 1 + st.w [%a15], %d4 + add.a %a15, %a3 + loop %a4, loop_csa + mtcr $lcx, %d4", + + // STACK INIT + // Mandatory operation before calling any 'C' function + // Two things to do + // 1. correct ECC checksum syndroms for complete Stack area by writing with required + // data size instructions + // 2. Stack pointer init used by 'C' code + // Startup code initialize both TriCore stack pointers, User and Interrupt, to the same area. + // - the code runs with 'PSW.IS = 1' after the reset -> shared stack + // - the separation of User and Interrupt stack is left on Application (usually OS) + // later on. + "ld.w %d4, [%a14] STACK + mov.a %a4, %d4 + ld.w %d4, [%a14] STACK_SIZE + mov.d %d1, %a4 + add %d1, %d1, %d4 + mov.a %sp, %d1 + mtcr $isp, %d1 + call clear_exec", + + // install trap handlers + "movh %d0,hi:first_trap_table #; load $btv + addi %d0,%d0,lo:first_trap_table + mtcr $btv,%d0 + isync", + // CRT0 PRE-INIT 'C' USER CODE + // Chance for user to execute HW init at the very beginning, before longer operations + // take place, like memory clear and copy of init data from Flash to RAM. + // In case of CORE dependent Hook execution, + // the application must read it ourselves (physical CoreID might not correspond + // to a consecutive sequence needed for array operations). + // Pre-init code MUST rely only on Stack variables only ! + "call Crt0PreInit", + + // CLEAR .BSS SECTIONS + // Areas to clear are given in the __clear_table config entry. + // The crt0 function is of WEAK type to allow the user implementation in the application + // by for example by 'C' specific routine + + "ld.w %d4, [%a14] CLEAR_TABLE", + "mov.a %a4, %d4", + "call Crt0BssInit", + + // COPY INITIALIZED DATA + // Initialization of data regions provided in __copy table in crt0 configuration structure. + // The crt0 function is of WEAK type to allow the user implementation in the application. + "ld.w %d4, [%a14] COPY_TABLE", + "mov.a %a4, %d4", + "call Crt0DataInit", + + // C++ GLOBAL OBJECT INITIALIZATION + // The ctor table (constructors to call) is provided as one of the crt0_configr structure entry. + // Each core can have its own ctor table array, if implemented in the linker file + // (not in BSP case) + "ld.w %d4, [%a14] CTOR_TABLE", + "mov.a %a4, %d4", + "call Crt0CtorInit", + + // CRT0 POST-INIT 'C' USER CODE + // Chance for user to execute specific code before jump to application entry, + // 'shared main()' in case of BSP + // In case of core dependent Hook execution, + // the application must read it ourselves (physical CoreID might not correspond + // to a consecutive sequence needed for array operations). + "call Crt0PostInit", + + // install interrupt handlers + "movh %d0,hi:__INTERRUPT_TABLE #; load $btv + addi %d0,%d0,lo:__INTERRUPT_TABLE + mtcr $biv,%d0 + isync", + + // CRT0 END : ENTRY TO APPLICATION + // Jump to the application entry point, shared across all cores in case of BSP examples + // In case of core dependent Hook execution, the application must read it ourselves, + // physical CoreID might not correspond to a consecutive sequence needed for array operations + // The return from the application is not expected, hard to say what the embedded system + // shall do here + "call main", + "j _exit", + +} + +// FUNCTION: _exit +global_asm!( + ".weak _exit", + ".type _exit, %function", + "_exit:", + "debug", /* debug stop in case of active debugging process, + otherwise 'nop' instruction */ + "j .", /* infinitive loop, waiting for eventual timeout watchdog */ +); +// FUNCTION: Crt0PreInit +// User hook before 'C' runtime initialization. Empty routine in case of crt0 startup code. +global_asm!( + ".weak Crt0PreInit", + ".type Crt0PreInit, %function", + "Crt0PreInit:", + "ret", +); + +// FUNCTION: Crt0PostInit +// User hook after 'C' runtime initialization. Empty routine in case of crt0 startup code. +global_asm!( + ".weak Crt0PostInit", + ".type Crt0PostInit, %function", + "Crt0PostInit:", + "ret", +); + +// FUNCTION: Crt0BssInit +// Default Crt0 BSS clear function. It goes through clear_table entries and calls the clear +// operation for each of them +// +// Input +// A[4] : core's clear_table base pointer +global_asm!( + ".weak Crt0BssInit", + ".type Crt0BssInit, %function", + "Crt0BssInit:", + "mov.aa %a13, %a4", // Local pointer for clear_table entry + "mov.a %a12, CLEAR_TABLE_OFFSET", // Clear_table next entry offset + "_table_bss_clear_loop:", + "ld.w %d15, [%a13] CLEAR_TABLE_DST", // Base address of the area to clear + "jeq %d15, -1, _table_bss_clear_loop_end", // Checks table termination value -1, + "mov.a %a4, %d15", // Prepare area start pointer for clear routine + "ld.w %d4, [%a13] CLEAR_TABLE_SIZE", // Get size of the area + "call clear_exec", // Call Clear routine with saving Upper Context + "add.a %a13,%a12", // Next row from BSS clear table + "j _table_bss_clear_loop", + "_table_bss_clear_loop_end:", + "ret", +); + +// FUNCTION: Crt0DataInit +// Default Crt0 DATA init function. It goes through copy_table entries and calls +// copy operation for each of them. +// +// Input +// A[4] : core's copy_table pointer +global_asm!( + ".weak Crt0DataInit", + ".type Crt0DataInit, %function", + + "Crt0DataInit:", + "mov.aa %a13, %a4", // Local Pointer for copy table + "mov.a %a12, COPY_TABLE_OFFSET", // Copy table item offset in bytes + "_table_data_copy_loop:", + "ld.w %d15, [%a13]COPY_TABLE_DST", // Start address of the destination copy area + "jeq %d15, -1, _table_data_copy_loop_end", // Checks table termination value -1, + "mov.a %a4, %d15", + "ld.w %d4, [%a13]COPY_TABLE_SRC", // First Address of the source copy table + "mov.a %a5, %d4", // store it into address register %a5 + "ld.w %d4, [%a13]COPY_TABLE_SIZE", // Get size of the area + "call copy_exec", // Call Copy routine + "add.a %a13,%a12", // Next row from BSS copy table + "j _table_data_copy_loop", + "_table_data_copy_loop_end:", + "ret", +); + +// FUNCTION: Crt0CtorInit +// Default global C++ object initialization. It goes through ctor table and calls +// global constructors. +// +// Input +// A[4] : CTOR table base address +global_asm!( + ".weak Crt0CtorInit", + ".type Crt0CtorInit, %function", + + "Crt0CtorInit:", + "jz.a %a4, _ctor_exec_end", // check against no table present + "ld.w %d4, [%a4+]4", // get number of entries + "mov.a %a15, %d4 ", // and store it into address register %a15 + "jz.a %a15, _ctor_exec_end", // check against no entry (size = 0) + "add.a %a15, -1", // consider always one 'loop' execution + "_ctor_exec_loop:", + "ld.w %d4, [%a4+]4", // read the function pointer + "mov.a %a13, %d4 ", // and store it into the address register %a13 + "calli %a13", // call the function + "loop %a15,_ctor_exec_loop", // go through all functions + "_ctor_exec_end:", + "ret", + ); + +// MODULE LOCAL ROUTINES +// Used only within this module + +// FUNCTION: clear_exec +// Executes the erase loop from start address for specified number of bytes. +// It uses 64bit Store instruction +// +// Input +// A[4] : start address +// D[4] : size in bytes +global_asm!( + "clear_exec:", + "jz %d4,_clear_exec_end ",// Return if size is zero + "add %d4,-1 ",// decrement to take into account always one loop execution + "sh %d4,-3 ",// adjustment of the clear loop for the double word write instruction + "mov.a %a15,%d4 ",// init loop counter + "mov %e14,0 ",// Zero value + "_clear_exec_loop:", + "st.d [%a4+]8,%e14 ",// Store 64bit value + "loop %a15,_clear_exec_loop ",// execution loop until zero + "_clear_exec_end:", + "ret", +); + +// FUNCTION: copy_exec +// Executes the copy loop from start address to end address. +// Routine is simple Byte copy without any optimization. +// +// Input +// A[4] : start write address +// A[5] : start read address +// D[4] : size in bytes +global_asm!( + "copy_exec:", + "mov %d15,%d4", + "jz %d15,_copy_exec_end", // Return if size is zero + "add %d15,-1", // decrement to take into account value 0 in loop + "mov.a %a15,%d15", + "_copy_exec_loop:", + "ld.b %d15, [%a5+]1", + "st.b [%a4+]1, %d15", + "loop %a15,_copy_exec_loop", + "_copy_exec_end:", + "ret", +); + +// Initial simple trap table +global_asm!( +" .section .traptab, \"ax\", @progbits", +".macro trapentry from=0, to=7", +" debug", +" mov.u %d14, \\from << 8", +" add %d14,%d14,%d15", +" mov.a %a14,%d14", +" addih.a %a14,%a14,0xdead", +" j _exit", +"0:", +" j 0b", +" nop", +" rfe", +" .align 5", +" .if \\to-\\from", +" trapentry \"(\\from+1)\",\\to", +" .endif", +".endm", +" .align 8", +" .global first_trap_table", +"first_trap_table:", +" trapentry 0, 7", +); + +// Defintion of the interrupt table +global_asm!( + ".altmacro", + ".macro inttab_entry.1 p,u ", + " .align 5", + " .globl __inttab_entry_\\u\\p ", + " .type __inttab_entry_\\u\\p ,@function ", + " __inttab_entry_\\u\\p : ", + " svlcx", + " movh.a %a14, hi: __INTERRUPT_HANDLER\\u\\p ", + " lea %a14, [%a14]lo: __INTERRUPT_HANDLER\\u\\p ", + " calli %a14", + " rslcx", + " rfe", + ".endm ", + ".macro inttab_entry from=0, to=10", + " inttab_entry.1 %(\\from), _ ", + " .align 5", + " .if \\to-\\from ", + " inttab_entry \"(\\from+1)\", \\to ", + " .endif", + ".endm ", + ".pushsection .interrupt_table, \"ax\",@progbits", + " .align 8", + " .globl __INTERRUPT_TABLE ", + " .type __INTERRUPT_TABLE, @object", + " __INTERRUPT_TABLE:", + " inttab_entry 0, 15", + " inttab_entry 16, 32", + ".popsection", +); + +// Defintion of the default interrupt handlers +global_asm!( + ".altmacro", + ".macro ih_name p,u", + " .weak __INTERRUPT_HANDLER\\u\\p", + " .type __INTERRUPT_HANDLER\\u\\p, @function", + " __INTERRUPT_HANDLER\\u\\p:", + ".endm ", + ".macro interrupt_hnd from=0, to=10", + " ih_name %(\\from), _ ", + " .if \\to-\\from ", + " interrupt_hnd \"(\\from+1)\", \\to ", + " .endif", + ".endm ", + ".pushsection .text.default_int_handler, \"ax\",@progbits", + "interrupt_hnd 0, 15", + "interrupt_hnd 16, 32", + " ret", + ".popsection", +); \ No newline at end of file diff --git a/tests/resources/project_files_cortex_m/.cargo/config.toml b/tests/resources/project_files_cortex_m/.cargo/config.toml new file mode 100644 index 0000000..a65b3bf --- /dev/null +++ b/tests/resources/project_files_cortex_m/.cargo/config.toml @@ -0,0 +1,15 @@ +rustflags = [ + # mapfile + # "-C", "link-arg=-Map=mapfile.map", + + # remove unsed sections + "-C", "link-arg=--gc-sections", + + # LLD (shipped with the Rust toolchain) is used as the default linker + "-C", "link-arg=-Tlink.x", + +] + +[build] +target = ["thumbv7em-none-eabihf"] + diff --git a/tests/resources/project_files_cortex_m/Cargo.toml b/tests/resources/project_files_cortex_m/Cargo.toml new file mode 100644 index 0000000..ee4ebfe --- /dev/null +++ b/tests/resources/project_files_cortex_m/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] +resolver = "2" +members = [ + "arm_example", + "cortex_test" +] \ No newline at end of file diff --git a/tests/resources/project_files_cortex_m/cortex_test/Cargo.toml b/tests/resources/project_files_cortex_m/cortex_test/Cargo.toml new file mode 100644 index 0000000..706d809 --- /dev/null +++ b/tests/resources/project_files_cortex_m/cortex_test/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "cortex_test" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +arm_example = {path="../arm_example",features=["all","rt"]} +rtic = {version="2.0.1",features=["thumbv7-backend"]} +cortex-m = {version = "*"} +[[bin]] +name = "main" +test = false +bench = false \ No newline at end of file diff --git a/tests/resources/project_files_cortex_m/cortex_test/build.rs b/tests/resources/project_files_cortex_m/cortex_test/build.rs new file mode 100644 index 0000000..219659c --- /dev/null +++ b/tests/resources/project_files_cortex_m/cortex_test/build.rs @@ -0,0 +1,18 @@ + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // // Put `memory.x` in our output directory and ensure it's + // // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + println!("cargo:rerun-if-changed=memory.x"); + println!("cargo:rustc-link-arg=-Tlink.x"); +} \ No newline at end of file diff --git a/tests/resources/project_files_cortex_m/cortex_test/memory.x b/tests/resources/project_files_cortex_m/cortex_test/memory.x new file mode 100644 index 0000000..3ac3b7b --- /dev/null +++ b/tests/resources/project_files_cortex_m/cortex_test/memory.x @@ -0,0 +1,31 @@ +MEMORY +{ + FLASH : ORIGIN = 0x10010000, LENGTH = 2048K + RAM : ORIGIN = 0x08008800, LENGTH = 222K +} + +/* This is where the call stack will be allocated. */ +/* The stack is of the full descending type. */ +/* You may want to use this variable to locate the call stack and static + variables in different memory regions. Below is shown the default value */ +/* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ + +/* You can use this symbol to customize the location of the .text section */ +/* If omitted the .text section will be placed right after the .vector_table + section */ +/* This is required only on microcontrollers that store some configuration right + after the vector table */ +/* _stext = ORIGIN(FLASH) + 0x400; */ + +/* Example of putting non-initialized variables into custom RAM locations. */ +/* This assumes you have defined a region RAM2 above, and in the Rust + sources added the attribute `#[link_section = ".ram2bss"]` to the data + you want to place there. */ +/* Note that the section will not be zero-initialized by the runtime! */ +/* SECTIONS { + .ram2bss (NOLOAD) : ALIGN(4) { + *(.ram2bss); + . = ALIGN(4); + } > RAM2 + } INSERT AFTER .bss; +*/ diff --git a/tests/resources/project_files_cortex_m/cortex_test/src/bin/main.rs b/tests/resources/project_files_cortex_m/cortex_test/src/bin/main.rs new file mode 100644 index 0000000..2b3f83c --- /dev/null +++ b/tests/resources/project_files_cortex_m/cortex_test/src/bin/main.rs @@ -0,0 +1,58 @@ +#![no_main] +#![no_std] + +#[rtic::app(device = arm_example,peripherals=true,dispatchers = [UARTINT])] +mod app { + use arm_example::timer; + use arm_example::*; + use cortex_m; + + #[shared] + struct Shared {} + #[local] + struct Local {} + + #[init] + fn init(ctx: init::Context) -> (Shared, Local) { + let device: arm_example::Peripherals = ctx.device; + unsafe { + // it is possible to use standard way of accessing register through Peripheral type + device.TIMER.bitfield_reg().init(|f| { + f.bitfieldenumerated() + .set(timer::bitfield_reg::BitfieldEnumerated::GPIOA_0) + .bitfieldw() + .set(3) + }); + } + + ( + Shared {}, + // initial values for the `#[local]` resources + Local {}, + ) + } + #[idle()] + fn idle(_cx: idle::Context) -> ! { + loop { + cortex_m::asm::nop(); + } + } + + #[task(binds = INT_FOO, local = [times: u32 = 0])] + fn set_some_regs(_cx: set_some_regs::Context) { + // Peripheral type is not required + unsafe { + TIMER.bitfield_reg().modify(|f| { + f.bitfieldenumerated() + .set(timer::bitfield_reg::BitfieldEnumerated::GPIOA_0) + .bitfieldw() + .set(3) + }); + } + } +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/tests/resources/project_files_generic/src/bin/main.rs b/tests/resources/project_files_generic/src/bin/main.rs new file mode 100644 index 0000000..2232225 --- /dev/null +++ b/tests/resources/project_files_generic/src/bin/main.rs @@ -0,0 +1,96 @@ +use arm_example::timer; +use arm_example::*; +fn main() -> ! { + unsafe { + // Verbose read modify + let register = TIMER.bitfield_reg(); + let register_value = register.read(); + let _bitfield_value = register_value.bitfieldr().get(); + // Modify value of register using fluent api + let new_register_value = register_value.bitfieldrw().set(23).bitfieldw().set(23); + register.write(new_register_value); + + // Create a register value from raw value + let register_value = timer::BitfieldReg::new(0x123); + register.write(register_value); + + // Register without bitfield + let register_value = TIMER.nobitfield_reg().read(); + let _numeric_value = register_value.get(); + let modified_register_value = register_value.set(23); + TIMER.nobitfield_reg().write(modified_register_value); + + // Modify + TIMER.bitfield_reg().modify(|f| { + f.bitfieldenumerated() + .set(timer::bitfield_reg::BitfieldEnumerated::GPIOA_0) + .bitfieldw() + .set(3) + }); + + // init + TIMER.bitfield_reg().init(|f| { + f.bitfieldenumerated() + .set(timer::bitfield_reg::BitfieldEnumerated::GPIOA_0) + .bitfieldw() + .set(3) + }); + + // Array of register bitfields + let mut a = TIMER.bitfield_reg().read(); + for x in 0..2 { + a = a + .fieldarray(x) + .set(timer::bitfield_reg::FieldArray::FALLING); + } + TIMER.bitfield_reg().write(a); + + // Array of registers + let reg_array = TIMER.arrayreg(); + for reg in reg_array { + let reg_val = reg.read(); + let old_val = reg_val.get(); + reg.write(reg_val.set(old_val + 1)); + } + + // Array of peripherals + for peri in UART { + peri.reg16bitenum().modify(|f| { + f.bitfield9bitsenum() + .set(uart::reg16bitenum::Bitfield9BitsEnum::VAL_0) + }); + } + + // Raw bitfield write. How to write an enumerated bitfield by passing an integer literal + TIMER.bitfield_reg().modify(|f| { + f.bitfieldenumerated() + .set(3.into()) + .bitfieldw() + .set(3) + }); + + // Use register marked with alternateGroup + TIMER.bitfield_reg_alt_group().modify(|f| f.set(32)); + + // Set and get raw values + TIMER.bitfield_reg().modify(|f| f.set_raw(32)); + let _: u32 = TIMER.bitfield_reg().read().get_raw(); + + // Get mask and offset for a register bitfield + let register_bitfield = TIMER.bitfield_reg().read().bitfieldr(); + let _offset = register_bitfield.offset(); + let _mask = register_bitfield.mask(); + + // Get mask and offset for a register bitfield fro boolean + let register_bitfield = TIMER.bitfield_reg().read().boolr(); + let _offset = register_bitfield.offset(); + let _mask = register_bitfield.mask(); + + // Test correct handling of SVD names starting with non XID_Start + // characters or collide with Rust keywords. + let value = FOO.r#in().read(); + FOO.r#in() + .write(value._self().set(foo::r#in::_Self::_1_VALUE)); + } + loop {} +} diff --git a/tests/resources/project_files_tracing/src/bin/main.rs b/tests/resources/project_files_tracing/src/bin/main.rs new file mode 100644 index 0000000..2f66a01 --- /dev/null +++ b/tests/resources/project_files_tracing/src/bin/main.rs @@ -0,0 +1,121 @@ +use arm_example::{timer::bitfield_reg, tracing, *}; +fn read_fn(addr: usize, len: usize) -> u64 { + println!("r addr=0x{:X}\tlen={:?}", addr, len); + 0x0 +} +fn write_fn(addr: usize, len: usize, val: u64) { + println!("w addr=0x{:X}\tlen={:?}\tval=0x{:X}", addr, len, val); +} +fn main() -> ! { + let _ = tracing::set_read_fn(read_fn); + let _ = tracing::set_write_fn(write_fn); + unsafe { + // Verbose read modify + let register = TIMER.bitfield_reg(); + let register_value = register.read(); + let _bitfield_value = register_value.bitfieldr().get(); + // Modify value of register using fluent api + let new_register_value = register_value.bitfieldrw().set(23).bitfieldw().set(23); + register.write(new_register_value); + + // Register without bitfield + let register_value = TIMER.nobitfield_reg().read(); + let _numeric_value = register_value.get(); + let modified_register_value = register_value.set(23); + TIMER.nobitfield_reg().write(modified_register_value); + + // Modify + TIMER.bitfield_reg().modify(|f| { + f.bitfieldenumerated() + .set(bitfield_reg::BitfieldEnumerated::GPIOA_0) + .bitfieldw() + .set(3) + }); + + // init + TIMER.bitfield_reg().init(|f| { + f.bitfieldenumerated() + .set(bitfield_reg::BitfieldEnumerated::GPIOA_0) + .bitfieldw() + .set(3) + }); + + // Array of register bitfields + let mut a = TIMER.bitfield_reg().read(); + for x in 0..2 { + a = a.fieldarray(x).set(bitfield_reg::FieldArray::FALLING); + } + TIMER.bitfield_reg().write(a); + + // Array of registers + let reg_array = TIMER.arrayreg(); + for reg in reg_array { + let reg_val = reg.read(); + let old_val = reg_val.get(); + reg.write(reg_val.set(old_val + 1)); + } + + // Array of peripherals + for peri in UART { + peri.reg16bitenum().modify(|f| { + f.bitfield9bitsenum() + .set(uart::reg16bitenum::Bitfield9BitsEnum::VAL_0) + }); + } + + // Raw bitfield write. How to write an enumerated bitifield with a value listed in the enumeration + TIMER.bitfield_reg().modify(|f| { + f.bitfieldenumerated() + .set(bitfield_reg::BitfieldEnumerated::new(3)) + .bitfieldw() + .set(3) + }); + { + use tracing::insanely_unsafe; + // Write a read-only register + TIMER.sr().write_read_only(timer::Sr::default()); + + // Read a write-only register + let _ = TIMER.int().read_write_only(); + } + } + loop {} +} + +#[cfg(test)] +mod test { + use test::{reg_name::reg_name_from_addr, *}; + fn assert_regname(addr: usize, name_expected: &str) { + match reg_name_from_addr(addr as u64) { + Some(name) => { + println!("name:{}, name_expected:{}", name, name_expected); + assert!(name.contains(name_expected)); + } + None => { + panic!( + "Address: {} is not in map of register names. This should not happen.", + addr + ); + } + } + } + #[test] + fn reg_name_test() { + TIMER.arrayreg()[0].addr(); + assert_regname(TIMER.arrayreg()[0].addr(), "TIMER.arrayreg()[0]"); + assert_regname(TIMER.bitfield_reg().addr(), "TIMER.bitfield_reg()"); + assert_regname(TIMER.int().addr(), "TIMER.int()"); + assert_regname(TIMER.r#match().addr(), "TIMER.r#match()"); + assert_regname(TIMER.nobitfield_reg().addr(), "TIMER.nobitfield_reg()"); + assert_regname(TIMER.prescale_rd().addr(), "TIMER.prescale_rd()"); + assert_regname(TIMER.prescale_wr().addr(), "TIMER.prescale_wr()"); + assert_regname(TIMER.sr().addr(), "TIMER.sr()"); + assert_regname(UART[0].reg16bitenum().addr(), "UART[0].reg16bitenum()"); + assert_regname(UART[0].reg16bitraw().addr(), "UART[0].reg16bitraw()"); + assert_regname(UART[0].reg1_()[0].addr(), "UART[0].reg1_()[0]"); + assert_regname(UART[0].reg1_()[1].addr(), "UART[0].reg1_()[1]"); + assert_regname(UART[0].reg32bitraw().addr(), "UART[0].reg32bitraw()"); + assert_regname(UART[0].reg8bitraw().addr(), "UART[0].reg8bitraw()"); + assert_regname(UART[0].regbitfieldraw().addr(), "UART[0].regbitfieldraw()"); + } +} diff --git a/tests/test_basic_svd_aurix.rs b/tests/test_basic_svd_aurix.rs new file mode 100644 index 0000000..f823374 --- /dev/null +++ b/tests/test_basic_svd_aurix.rs @@ -0,0 +1,116 @@ +#![cfg(aurix_tests)] +mod common; +use common::*; +use fs_extra::dir::CopyOptions; +use std::fs; +use std::{env, path::Path}; +use svd2pac::main; +use toml_edit::{array, value, Array, Document, Table}; + +/// This test requires Aurix Rust compiler pre-installed +#[test] +fn compile_generated_aurix() { + let xml_path = concat!(env!("CARGO_MANIFEST_DIR"), "/test_svd/simple_csfr.svd"); + + // Temp folder that should be deleted in case of test success. + let generated_code_folder = tempfile::tempdir_in(env::current_dir().unwrap()).unwrap(); + let args = [ + "", + "--disable-rust-fmt", + "--target=aurix", + xml_path, + generated_code_folder.path().to_str().unwrap(), + ]; + main(args); + //Patch toml and add required files. + let old_toml = fs::read_to_string(Path::new(&generated_code_folder.path().join("Cargo.toml"))) + .expect("Unable to read toml file"); + let mut parsed_toml = old_toml + .parse::() + .expect("Unable to parse toml file"); + let mut default_table = Array::new(); + default_table.push("all"); + default_table.push("csfr_cpu0"); + parsed_toml["features"]["default"] = value(default_table); + parsed_toml["dependencies"]["tc162-rt"]["path"] = value("tc162-rt"); + parsed_toml["bin"] = array(); + let bin_array = parsed_toml["bin"].as_array_of_tables_mut().unwrap(); + + let mut bin_table = Table::new(); + bin_table["name"] = value("main"); + bin_table["test"] = value(false); + bin_table["bench"] = value(false); + bin_array.push(bin_table); + let toml_string = parsed_toml.to_string(); + print!("{}", toml_string); + // Write to a file + fs::write( + Path::new(Path::new(&generated_code_folder.path().join("Cargo.toml"))), + toml_string, + ) + .expect("Unable to write toml file"); + + fs_extra::dir::copy( + "./tests/resources/project_files_aurix", + generated_code_folder.path(), + &CopyOptions::new().content_only(true).overwrite(true), + ) + .expect("Failed to copy required files to build cargo project"); + + assert_cargo_build(generated_code_folder); +} + +/// Generate PAC with tracing code but feature is disabled +#[test] +fn compile_generated_aurix_tracing() { + let xml_path = concat!(env!("CARGO_MANIFEST_DIR"), "/test_svd/simple_csfr.svd"); + + // Temp folder that should be deleted in case of test success. + let generated_code_folder = tempfile::tempdir_in(env::current_dir().unwrap()).unwrap(); + let args = [ + "", + "--disable-rust-fmt", + "--target=aurix", + "--tracing", + xml_path, + generated_code_folder.path().to_str().unwrap(), + ]; + main(args); + + //Patch toml and add required files. + let old_toml = fs::read_to_string(Path::new(&generated_code_folder.path().join("Cargo.toml"))) + .expect("Unable to read toml file"); + let mut parsed_toml = old_toml + .parse::() + .expect("Unable to parse toml file"); + let mut default_table = Array::new(); + default_table.push("all"); + default_table.push("csfr_cpu0"); + parsed_toml["features"]["default"] = value(default_table); + parsed_toml["dependencies"]["tc162-rt"]["path"] = value("tc162-rt"); + parsed_toml["bin"] = array(); + let bin_array = parsed_toml["bin"].as_array_of_tables_mut().unwrap(); + + let mut bin_table = Table::new(); + bin_table["name"] = value("main"); + bin_table["test"] = value(false); + bin_table["bench"] = value(false); + bin_array.push(bin_table); + let toml_string = parsed_toml.to_string(); + print!("{}", toml_string); + // Write to a file + fs::write( + Path::new(Path::new(&generated_code_folder.path().join("Cargo.toml"))), + toml_string, + ) + .expect("Unable to write toml file"); + + fs_extra::dir::copy( + "./tests/resources/project_files_aurix", + generated_code_folder.path(), + &CopyOptions::new().content_only(true).overwrite(true), + ) + .expect("Failed to copy required files to build cargo project"); + + assert_cargo_build(generated_code_folder); +} diff --git a/tests/test_basic_svd_cortex_m.rs b/tests/test_basic_svd_cortex_m.rs new file mode 100644 index 0000000..f411b92 --- /dev/null +++ b/tests/test_basic_svd_cortex_m.rs @@ -0,0 +1,34 @@ +#![cfg(not(aurix_tests))] +mod common; +use common::*; +use fs_extra::dir::CopyOptions; +use std::env; +use svd2pac::main; + +/// Test generic target code generation. +#[test] +fn compile_generated_cortex_m() { + let xml_path = concat!(env!("CARGO_MANIFEST_DIR"), "/test_svd/simple.xml"); + + // Temp folder that should be deleted in case of test success. + let workspace_folder = tempfile::tempdir_in(env::current_dir().unwrap()).unwrap(); + fs_extra::dir::copy( + "./tests/resources/project_files_cortex_m", + workspace_folder.path(), + &CopyOptions::new().content_only(true).overwrite(true), + ) + .expect("Failed to copy required files to build cargo project"); + + let generated_pack_folder = workspace_folder.path().join("arm_example"); + let args = [ + "", + "--target=cortex-m", + xml_path, + generated_pack_folder.to_str().unwrap(), + ]; + main(args); + + let license_path = generated_pack_folder.join("LICENSE.txt"); + assert!(license_path.exists(), "Not found LICENSE.txt"); + assert_cargo_build(workspace_folder); +} diff --git a/tests/test_basic_svd_generic.rs b/tests/test_basic_svd_generic.rs new file mode 100644 index 0000000..bb6584c --- /dev/null +++ b/tests/test_basic_svd_generic.rs @@ -0,0 +1,73 @@ +mod common; +use common::*; +use fs_extra::dir::CopyOptions; +use std::fs; +use std::{env, path::Path}; +use svd2pac::main; +use toml_edit::{array, value, Array, Document, Table}; + +/// Test generic target code generation. +#[test] +fn compile_generated_generic() { + let xml_path = concat!(env!("CARGO_MANIFEST_DIR"), "/test_svd/simple.xml"); + + // Temp folder that should be deleted in case of test success. + let generated_code_folder = tempfile::tempdir_in(env::current_dir().unwrap()).unwrap(); + let args = ["", xml_path, generated_code_folder.path().to_str().unwrap()]; + main(args); + + //Patch toml and add required files. + let old_toml = fs::read_to_string(Path::new(&generated_code_folder.path().join("Cargo.toml"))) + .expect("Unable to read toml file"); + let mut parsed_toml = old_toml + .parse::() + .expect("Unable to parse toml file"); + let mut default_table = Array::new(); + default_table.push("all"); + parsed_toml["features"]["default"] = value(default_table); + parsed_toml["bin"] = array(); + let bin_array = parsed_toml["bin"].as_array_of_tables_mut().unwrap(); + + let mut bin_table = Table::new(); + bin_table["name"] = value("main"); + bin_table["test"] = value(false); + bin_table["bench"] = value(false); + bin_array.push(bin_table); + let toml_string = parsed_toml.to_string(); + // Write to a file + fs::write( + Path::new(Path::new(&generated_code_folder.path().join("Cargo.toml"))), + toml_string, + ) + .expect("Unable to write toml file"); + + fs_extra::dir::copy( + "./tests/resources/project_files_generic", + generated_code_folder.path(), + &CopyOptions::new().content_only(true).overwrite(true), + ) + .expect("Failed to copy required files to build cargo project"); + + let license_path = generated_code_folder.path().join("LICENSE.txt"); + assert!(license_path.exists(), "Not found LICENSE.txt"); + assert_cargo_build(generated_code_folder); +} + +#[test] +fn test_license_text_option() { + let xml_path = concat!(env!("CARGO_MANIFEST_DIR"), "/test_svd/simple.xml"); + + // Temp folder that should be deleted in case of test success. + let generated_code_folder = tempfile::tempdir_in(env::current_dir().unwrap()).unwrap(); + let args = [ + "", + xml_path, + generated_code_folder.path().to_str().unwrap(), + "--license-file", + "./tests/resources/LICENSE.txt", + ]; + main(args); + let license_path = generated_code_folder.path().join("LICENSE.txt"); + assert!(license_path.exists(), "Not found LICENSE.txt"); + assert_files_eq("./tests/resources/LICENSE.txt", license_path); +} diff --git a/tests/test_basic_svd_tracing.rs b/tests/test_basic_svd_tracing.rs new file mode 100644 index 0000000..65076f8 --- /dev/null +++ b/tests/test_basic_svd_tracing.rs @@ -0,0 +1,67 @@ +mod common; +use common::*; +use fs_extra::dir::CopyOptions; +use std::fs; +use std::{env, path::Path}; +use svd2pac::main; +use toml_edit::{array, value, Array, Document, Table}; + +/// Test tracing code generation. +#[test] +fn compile_generated_tracing() { + let xml_path = concat!(env!("CARGO_MANIFEST_DIR"), "/test_svd/simple.xml"); + + // Temp folder that should be deleted in case of test success. + let generated_code_folder = tempfile::tempdir_in(env::current_dir().unwrap()).unwrap(); + let generated_test_folder = tempfile::tempdir_in(env::current_dir().unwrap()).unwrap(); + let args = [ + "", + xml_path, + generated_code_folder.path().to_str().unwrap(), + "--tracing", + ]; + + main(args); + + //Patch toml and add required files. + let old_toml = fs::read_to_string(Path::new(&generated_code_folder.path().join("Cargo.toml"))) + .expect("Unable to read toml file"); + let mut parsed_toml = old_toml + .parse::() + .expect("Unable to parse toml file"); + let mut default_table = Array::new(); + default_table.push("all"); + default_table.push("tracing"); + parsed_toml["features"]["default"] = value(default_table); + parsed_toml["bin"] = array(); + let bin_array = parsed_toml["bin"].as_array_of_tables_mut().unwrap(); + + let mut bin_table = Table::new(); + bin_table["name"] = value("main"); + bin_table["test"] = value(false); + bin_table["bench"] = value(false); + bin_array.push(bin_table); + let toml_string = parsed_toml.to_string(); + // Write to a file + fs::write( + Path::new(Path::new(&generated_code_folder.path().join("Cargo.toml"))), + toml_string, + ) + .expect("Unable to write toml file"); + + fs_extra::dir::copy( + "./tests/resources/project_files_tracing", + generated_code_folder.path(), + &CopyOptions::new().content_only(true).overwrite(true), + ) + .expect("Failed to copy required files to build cargo project"); + fs_extra::dir::copy( + generated_code_folder.path(), + generated_test_folder.path(), + &CopyOptions::new().content_only(true).overwrite(true), + ) + .expect("Failed to copy generated files to test cargo project"); + + assert_cargo_build(generated_code_folder); + assert_cargo_test(generated_test_folder); +}