Hi Team,
I’m new to embedded Rust and currently working with the STM32F410RBT6 board. I’ve written a basic program in Rust on this board and successfully got the output. Now, I need to prove out the UART driver. I tried accessing the registers using their addresses, but I couldn’t get it to work.It throws unsafe errors. Please provide a solution, as this will be very helpful to me. I’ve attached my code repo for referenceGit_Repo.
By default, the stable-deref-trait
crate has the std
feature enabled. If you have a direct dependency on it, add default-features = false
to disable usage of std
:
[dependencies]
stable-deref-trait = { version = "1.2", default-features = false }
If stable-deref-trait
is not a direct dependency of your crate, please post the output of cargo tree --invert stable-deref-trait
to see what pulls it in.
This is the only error I could see in your screenshot, so if there’s more problems you would need to provide more information.
Hi @cod10129,
Thanks for your quick response. I tried adding stable-deref-trait = { version = "1.2", default-features = false }
as a dependency, but I am still facing the same problem.
I’ve attached the output of cargo tree --invert stable-deref-trait
in this comment, along with the error details. My repo has also been updated and shared for reference this.
My error status:
error[E0463]: can't find crate for std
|
= note: the thumbv7em-none-eabihf
target may not support the standard library
= note: std
is required by stable_deref_trait
because it does not declare #![no_std]
error[E0405]: cannot find trait Clone
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:129:50
|
129 | pub unsafe trait CloneStableDeref: StableDeref + Clone {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::clone::Clone;
|
error[E0405]: cannot find trait Sized
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:157:17
|
157 | unsafe impl<T: ?Sized> StableDeref for Box {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::marker::Sized;
|
error[E0405]: cannot find trait Sized
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:170:17
|
170 | unsafe impl<T: ?Sized> StableDeref for Rc {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::marker::Sized;
|
error[E0405]: cannot find trait Sized
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:172:17
|
172 | unsafe impl<T: ?Sized> CloneStableDeref for Rc {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::marker::Sized;
|
error[E0405]: cannot find trait Sized
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:174:17
|
174 | unsafe impl<T: ?Sized> StableDeref for Arc {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::marker::Sized;
|
error[E0405]: cannot find trait Sized
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:176:17
|
176 | unsafe impl<T: ?Sized> CloneStableDeref for Arc {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::marker::Sized;
|
error[E0405]: cannot find trait Sized
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:178:21
|
178 | unsafe impl<'a, T: ?Sized> StableDeref for Ref<'a, T> {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::marker::Sized;
|
error[E0405]: cannot find trait Sized
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:179:21
|
179 | unsafe impl<'a, T: ?Sized> StableDeref for RefMut<'a, T> {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::marker::Sized;
|
error[E0405]: cannot find trait Sized
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:181:21
|
181 | unsafe impl<'a, T: ?Sized> StableDeref for MutexGuard<'a, T> {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::marker::Sized;
|
error[E0405]: cannot find trait Sized
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:183:21
|
183 | unsafe impl<'a, T: ?Sized> StableDeref for RwLockReadGuard<'a, T> {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::marker::Sized;
|
error[E0405]: cannot find trait Sized
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:185:21
|
185 | unsafe impl<'a, T: ?Sized> StableDeref for RwLockWriteGuard<'a, T> {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::marker::Sized;
|
error[E0405]: cannot find trait Sized
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:187:21
|
187 | unsafe impl<'a, T: ?Sized> StableDeref for &'a T {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::marker::Sized;
|
error[E0405]: cannot find trait Sized
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:188:21
|
188 | unsafe impl<'a, T: ?Sized> CloneStableDeref for &'a T {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::marker::Sized;
|
error[E0405]: cannot find trait Sized
in this scope
--> C:\Users\MuthuArasan.cargo\registry\src\index.crates.io-6f17d22bba15001f\stable_deref_trait-1.2.0\src\lib.rs:189:21
|
189 | unsafe impl<'a, T: ?Sized> StableDeref for &'a mut T {}
| ^^^^^ not found in this scope
|
help: consider importing this trait
|
25 + use core::marker::Sized;
|
Some errors have detailed explanations: E0405, E0463.
For more information about an error, try rustc --explain E0405
.
error: could not compile stable_deref_trait
(lib) due to 15 previous errors
warning: build failed, waiting for other jobs to finish...
After checking some dependencies, I found that this is because probe-rs
does not support #![no_std]
. It needs std
functionality in the gimli
and object
crates. Your inverted tree shows how gimli
pulls in stable_deref_trait
. I’m not an expert in embedded, but I don’t think probe-rs
is meant to be used as a library running on the chip it’s probing. You’ll need to rethink your design.
It’s definitely true that probe-rs
needs std
available. What I’m not sure about is what device probe-rs
is intended to be run on (maybe a “host” machine connected to the embedded device via debug probe? Again, I’m not an embedded developer).
Hi @cod10129
I want to write a UART driver in Rust by accessing the registers directly, similar to how it is done in C, without using embedded-hal. Is this possible? If yes, please provide some guidance and references.
If you want to manually access specific registers, you'll need inline assembly with asm!
.
Memory-mapped registers are different, and can be accessed by just converting their memory addresses into a pointer. The source code of stm32f4xx-hal
would be a useful reference, although it's a lot of code.
For an example, assume there's a memory-mapped 4 byte register at address 0x4000
that you want to write 0xDEADBEEF
into. That can be done like so:
fn main() {
const ADDR: usize = 0x4000;
let ptr = ADDR as *mut u32;
// SAFETY: pretend there's an MMIO device at this address
unsafe {
ptr.write_volatile(0xDEADBEEF);
}
}
You can build abstractions around this similar to stm32f4-staging::Reg
for more ergonomic use.
The HAL crate already has a UART driver. May as well use it, since it works with higher level crates like embassy. It will get you up an running much sooner.
FWIW, I use embassy-rp
with a Raspberry Pi Pico, and it is a billion times better than trying to reinvent everything from scratch.
Hi @cod10129 @parasyte ,
I am currently using this method to run the code and hitting the write function, but the data is not showing up in the terminal. What could be the problem? Could you please guide me.
I have upadate my code here PFA.
#![no_std]
#![no_main]
use cortex_m::asm;
use cortex_m_rt::entry;
use core::ptr;
use stm32f4xx_hal::{pac, prelude::*};
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
cortex_m::asm::bkpt(); // Trigger breakpoint for debugging
loop {}
}
// Base addresses for UART peripherals
const UART1_BASE: u32 = 0x40011000; // USART1 base address
const UART2_BASE: u32 = 0x40004400; // USART2 base address
// Register offsets
const UART_SR: u32 = 0x00;
const UART_DR: u32 = 0x04;
const UART_BRR: u32 = 0x08;
const UART_CR1: u32 = 0x0C;
const UART_CR2: u32 = 0x10;
const UART_CR3: u32 = 0x14;
#[derive(Copy, Clone)]
enum Uart {
Uart1,
Uart2,
}
fn get_uart_base(uart: Uart) -> u32 {
match uart {
Uart::Uart1 => UART1_BASE,
Uart::Uart2 => UART2_BASE,
}
}
fn enable_peripherals(uart: Uart) {
let rcc = unsafe { &*pac::RCC::ptr() };
let gpioa = unsafe { &*pac::GPIOA::ptr() };
let gpiob = unsafe { &*pac::GPIOB::ptr() };
match uart {
Uart::Uart1 => {
rcc.apb2enr.modify(|_, w| w.usart1en().set_bit());
rcc.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
gpioa.afrh.modify(|_, w| w.afrh9().bits(7).afrh10().bits(7));
}
Uart::Uart2 => {
rcc.apb1enr.modify(|_, w| w.usart2en().set_bit());
rcc.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
gpioa.afrl.modify(|_, w| w.afrl2().bits(7).afrl3().bits(7));
}
}
}
fn uart_init(uart: Uart, baud_rate: u32, clock_freq: u32) {
let base = get_uart_base(uart);
unsafe {
//let brr = clock_freq / baud_rate;
let brr = 1667;
ptr::write_volatile((base + UART_BRR) as *mut u32, brr);
let cr1 = (1 << 13) | (1 << 3) | (1 << 2);
ptr::write_volatile((base + UART_CR1) as *mut u32, cr1);
ptr::write_volatile((base + UART_CR2) as *mut u32, 0x00);
ptr::write_volatile((base + UART_CR3) as *mut u32, 0x00);
}
}
fn uart_write(uart: Uart, data: u8) {
let base = get_uart_base(uart);
unsafe {
while (ptr::read_volatile((base + UART_SR) as *const u32) & (1 << 7)) == 0 {}
ptr::write_volatile((base + UART_DR) as *mut u32, data as u32);
}
}
fn uart_read(uart: Uart) -> u8 {
let base = get_uart_base(uart);
unsafe {
while (ptr::read_volatile((base + UART_SR) as *const u32) & (1 << 5)) == 0 {}
ptr::read_volatile((base + UART_DR) as *const u32) as u8
}
}
#[entry]
fn main() -> ! {
let selected_uart = Uart::Uart2;
enable_peripherals(selected_uart);
uart_init(selected_uart, 9600, 16_000_000);
for _ in 1..=10{
uart_write(selected_uart, b'H');
}
let _received = uart_read(selected_uart);
loop {
asm::nop();
}
}