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}