{"id":13423323,"url":"https://github.com/rust-embedded/register-rs","last_synced_at":"2025-12-30T04:44:54.270Z","repository":{"id":57659459,"uuid":"140081711","full_name":"rust-embedded/register-rs","owner":"rust-embedded","description":"Unified interface for type-safe MMIO and CPU register access in Rust","archived":true,"fork":false,"pushed_at":"2021-07-05T20:46:28.000Z","size":50,"stargazers_count":48,"open_issues_count":0,"forks_count":10,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-02-28T10:45:13.295Z","etag":null,"topics":["bare-metal","cpu","embedded","mmio","no-std","operating-system","register","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rust-embedded.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-07T12:18:04.000Z","updated_at":"2025-01-05T09:55:17.000Z","dependencies_parsed_at":"2022-09-08T01:11:14.297Z","dependency_job_id":null,"html_url":"https://github.com/rust-embedded/register-rs","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fregister-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fregister-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fregister-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rust-embedded%2Fregister-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rust-embedded","download_url":"https://codeload.github.com/rust-embedded/register-rs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243766796,"owners_count":20344815,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bare-metal","cpu","embedded","mmio","no-std","operating-system","register","rust"],"created_at":"2024-07-31T00:00:30.801Z","updated_at":"2025-12-12T15:21:29.883Z","avatar_url":"https://github.com/rust-embedded.png","language":"Rust","readme":"[![crates.io](https://img.shields.io/crates/d/register.svg)](https://crates.io/crates/register)\n[![crates.io](https://img.shields.io/crates/v/register.svg)](https://crates.io/crates/register)\n\n# Deprecated\n\n**DEPRECATED: This crate is no longer supported, and dependents are instead recommended to switch to\n[tock-registers](https://crates.io/crates/tock-registers).**\n\n**register-rs** was started with a single goal: To bring the goodness of `tock-registers`, which in\nthe past was only available for `MMIO` registers, to `CPU` registers as well, to provide a unified\ninterface for both. Since release [0.7.0](https://crates.io/crates/tock-registers/0.7.0),\n`tock-registers` now itself provides the infrastructure to implement the `tock` register traits for\n`CPU` registers, rendering this crate obsolete.\n\n# register-rs\n\nUnified interface for type-safe MMIO and CPU register access in Rust.\n\n## Outline\n\n- [Usage](#usage)\n  - [Defining MMIO registers](#defining-mmio-registers)\n    - [The Deref pattern for drivers](#the-deref-pattern-for-drivers)\n  - [Defining CPU registers](#defining-cpu-registers)\n- [License](#license)\n- [Contribution](#contribution)\n\n## Usage\n\nThis crate uses the tock-register-interface, please refer to their\n[Readme](https://github.com/tock/tock/tree/master/libraries/tock-register-interface) for the whole\nAPI. Make sure to check the `register_structs!` explanation, especially the fact that you must\n[explicitly annotate gaps].\n\n[explicitly annotate gaps]: https://github.com/tock/tock/tree/master/libraries/tock-register-interface#defining-registers\n\n### Defining MMIO registers\n\n```rust\nuse register::{mmio::*, register_bitfields, register_structs};\n\nregister_bitfields! {\n    u32,\n\n    GPFSEL1 [\n        FSEL14 OFFSET(12) NUMBITS(3) [\n            Input = 0b000,\n            Output = 0b001,\n            TXD0 = 0b100\n        ],\n\n        FSEL15 OFFSET(15) NUMBITS(3) [\n            Input = 0b000,\n            Output = 0b001,\n            RXD0 = 0b100\n        ]\n    ]\n}\n\nregister_structs! {\n    #[allow(non_snake_case)]\n    pub RegisterBlock {\n        (0x000 =\u003e GPFSEL1: ReadWrite\u003cu32, GPFSEL1::Register\u003e),\n        (0x004 =\u003e SYSTMR_HI: ReadOnly\u003cu32\u003e),\n        (0x008 =\u003e @END),\n    }\n}\n\nfn main() {\n    let regs = 0x1337_0000 as *const RegisterBlock;\n\n    unsafe { (*regs).SYSTMR_HI.get() };\n}\n```\n\n#### The Deref pattern for drivers\n\nThe `MMIO` part of this crate can and will often be used for implementing device drivers. In this\ncase, you might find the `Deref pattern` useful for referencing your registers. It alleviates you\nfrom manually dereferencing each time a register access is due, and also encapsulates the `unsafe`\nkeyword.\n\nHere is an example (extending the code snippet from above):\n\n```rust\nregister_bitfields! {\n    u32,\n\n    // omitted\n}\n\nregister_structs! {\n    #[allow(non_snake_case)]\n    pub RegisterBlock {\n        // omitted\n    }\n}\n\npub struct DeviceDriver {\n    base_addr: usize,\n}\n\nimpl ops::Deref for DeviceDriver {\n    type Target = RegisterBlock;\n\n    fn deref(\u0026self) -\u003e \u0026Self::Target {\n        unsafe { \u0026*self.ptr() }\n    }\n}\n\nimpl DeviceDriver {\n    pub fn new(base_addr: usize) -\u003e Self {\n        DeviceDriver { base_addr }\n    }\n\n    /// Returns a pointer to the register block\n    fn ptr(\u0026self) -\u003e *const RegisterBlock {\n        self.base_addr as *const _\n    }\n\n    fn do_something(\u0026self) -\u003e u32 {\n        self.GPFSEL1.set(0x1337);\n        self.SYSTMR_HI.get()\n    }\n}\n```\n\n### Defining CPU registers\n\nFor CPU registers, you only need to implement the respective read/write trait. All other methods are\nprovided by default.\n\n```rust\n#![feature(llvm_asm)]\n\nuse register::{cpu::RegisterReadWrite, register_bitfields};\n\nregister_bitfields! {u32,\n    pub CNTP_CTL_EL0 [\n        /// Enables the timer.\n        ENABLE        OFFSET(0)  NUMBITS(1) [],\n\n        /// Timer interrupt mask bit.\n        IMASK         OFFSET(1)  NUMBITS(1) [],\n\n        /// The status of the timer.\n        ISTATUS       OFFSET(2)  NUMBITS(1) []\n    ]\n}\n\nstruct Reg;\n\nimpl RegisterReadWrite\u003cu32, CNTP_CTL_EL0::Register\u003e for Reg {\n    /// Reads the raw bits of the CPU register.\n    #[inline(always)]\n    fn get(\u0026self) -\u003e u32 {\n        let reg;\n        unsafe {\n            llvm_asm!(\"mrs $0, CNTP_CTL_EL0\" : \"=r\"(reg) ::: \"volatile\");\n        }\n        reg\n    }\n\n    /// Writes raw bits to the CPU register.\n    #[inline(always)]\n    fn set(\u0026self, value: u32) {\n        unsafe {\n            llvm_asm!(\"msr CNTP_CTL_EL0, $0\" :: \"r\"(value) :: \"volatile\");\n        }\n    }\n}\n\nstatic CNTP_CTL_EL0: Reg = Reg {};\n\nfn main() {\n    CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::SET);\n}\n\n```\n\n## Testing\n\nIn order to use this crate in `custom_test_frameworks` environments, please set the\n`no_std_unit_tests` feature flag in your dependency section.\n\nOtherwise, you might encounter errors like the following:\n\n```console\nerror[E0463]: can't find crate for `test`\n  --\u003e src/bsp/driver/bcm/bcm2xxx_gpio.rs:52:1\n   |\n52 | / register_structs! {\n53 | |     #[allow(non_snake_case)]\n54 | |     RegisterBlock {\n55 | |         (0x00 =\u003e GPFSEL0: ReadWrite\u003cu32\u003e),\n...  |\n66 | |     }\n67 | | }\n   | |_^ can't find crate\n   |\n   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)\n\nerror: aborting due to previous error\n```\n\n## License\n\nLicensed under either of\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or\n  http://www.apache.org/licenses/LICENSE-2.0)\n- MIT License ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the\nwork by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any\nadditional terms or conditions.\n","funding_links":[],"categories":["no-std crates","Rust"],"sub_categories":["WIP"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frust-embedded%2Fregister-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frust-embedded%2Fregister-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frust-embedded%2Fregister-rs/lists"}