rust-embedded / svd2rust

Generate Rust register maps (`struct`s) from SVD files
Apache License 2.0
709 stars 151 forks source link

The ability to obtain offset values for the modifiable bit fields of registers #582

Open AndreySmirnov81 opened 2 years ago

AndreySmirnov81 commented 2 years ago

To be able to manipulation of peripheral registers through bit-banding, the values of the offset of the modifiable bit fields in the registers are required.

For example, there are functions for bit-banding here: https://docs.rs/stm32f1xx-hal/0.9.0/stm32f1xx_hal/bb/index.html

Implementation variant:

pub mod perih_name {
   ...
   pub mod reg_name {
      ...
      pub const field_name_OFFSET: u8 = ...;
      ...
   }
   ...
}

Example of an implementation variant (stm32f1):

pub mod rcc {
   ...
   pub mod apb2enr {
      ...
      pub const USART1EN_OFFSET: u8 = 14;
      ...
      impl<'a> USART1EN_W<'a> {
         ...
         pub fn bit(self, value: bool) -> &'a mut W {
            self.w.bits = (self.w.bits & !(0x01 << USART1EN_OFFSET)) | ((value as u32 & 0x01) << USART1EN_OFFSET);
            self.w
         }
      }
      ...
      impl R {
         ...
         pub fn usart1en(&self) -> USART1EN_R {
            USART1EN_R::new(((self.bits >> USART1EN_OFFSET) & 0x01) != 0)
         }
         ...
      }
      ...
   }
   ...
}

Usage example:

unsafe {
   use stm32f1xx_hal::{self as hal, pac};
   hal::bb::set(&(*pac::RCC::PTR).apb2enr, pac::rcc::apb2enr::USART1EN_OFFSET);
}
burrbull commented 2 years ago

I like the idea.

burrbull commented 2 years ago

But I don't think we need to use it in bit or read methods as it give us nothing except compilation deceleration.

Also for bit-banging it is useful only for 1-bitwise writable fields. So the question is do we need constants for all fields or only for such ones.

burrbull commented 2 years ago

cc @rust-embedded/tools Any thoughts about the idea. Could offset constants be useful somewhere else? Free constant or associated on writer?

RamDav commented 1 year ago

I have the same problem an would need this. In c i usually liked to build my register initialization values from macros which used the values provided by the CMSIS peripherals files. and use this to setup a register with one compile time calculated value.