stm32f1_hal/
bb.rs

1//! Bit banding
2//!
3//! Support for the manipulation of peripheral registers through bit-banding.
4//! Not all peripherals are mapped to the bit-banding alias region, the peripheral bit-band region
5//! is from `0x4000_0000` to `0x400F_FFFF`. Bit-banding allows the manipulation of individual bits
6//! atomically.
7
8use core::ptr;
9
10// Start address of the peripheral memory region capable of being addressed by bit-banding
11const PERI_ADDRESS_START: usize = 0x4000_0000;
12const PERI_ADDRESS_END: usize = 0x400F_FFFF;
13
14const PERI_BIT_BAND_BASE: usize = 0x4200_0000;
15
16/// Clears the bit on the provided register without modifying other bits.
17///
18/// # Safety
19///
20/// Some registers have reserved bits which should not be modified.
21#[inline]
22pub unsafe fn clear<T>(register: *const T, bit: u8) {
23    unsafe {
24        write(register, bit, false);
25    }
26}
27
28/// Sets the bit on the provided register without modifying other bits.
29///
30/// # Safety
31///
32/// Some registers have reserved bits which should not be modified.
33#[inline]
34pub unsafe fn set<T>(register: *const T, bit: u8) {
35    unsafe {
36        write(register, bit, true);
37    }
38}
39
40/// Sets or clears the bit on the provided register without modifying other bits.
41///
42/// # Safety
43///
44/// Some registers have reserved bits which should not be modified.
45#[inline]
46pub unsafe fn write<T>(register: *const T, bit: u8, set: bool) {
47    let addr = register as usize;
48
49    assert!((PERI_ADDRESS_START..=PERI_ADDRESS_END).contains(&addr));
50    assert!(bit < 32);
51
52    let bit = bit as usize;
53    let bb_addr = (PERI_BIT_BAND_BASE + (addr - PERI_ADDRESS_START) * 32) + 4 * bit;
54    unsafe {
55        ptr::write_volatile(bb_addr as *mut u32, u32::from(set));
56    }
57}