简体   繁体   中英

Borrow of moved value error when using the STM32f1xx_hal crate

I am trying to enable the DMA peripheral on my STM32 bluepill and am getting the following error:

error[E0382]: borrow of moved value: `dp.RCC`
  --> src/main.rs:74:5
   |
36 |     let mut rcc = dp.RCC.constrain();   // RCC = Reset and Clock Control
   |                   ------ value moved here
...
74 |     dp.RCC.ahbenr.modify(|_, w| w.dma2en().set_bit());
   |     ^^^^^^ value borrowed here after move
   |
   = note: move occurs because `dp.RCC` has type `stm32f1::stm32f103::RCC`, which does not implement the `Copy` trait

I know this is a common issue when beginning to learn Rust. I have read into the docs on this and am still a bit confused as to what I need to do here to make this work.

Here is the code:

#![no_std]
#![no_main]

extern crate panic_halt; // you can put a breakpoint on `rust_begin_unwind` to catch panics

use cortex_m::asm;
use cortex_m_rt::entry;
use cortex_m_semihosting::hprintln;
use embedded_hal::spi::{Mode, Phase, Polarity};
use stm32f1xx_hal::{
    prelude::*,
    pac,
    spi::Spi,
    dma,
    stm32
};


#[entry]
fn main() -> ! {
    let dp = pac::Peripherals::take().unwrap();
    let mut rcc = dp.RCC.constrain();   // RCC = Reset and Clock Control
    dp.RCC.ahbenr.modify(|_, w| w.dma2en().set_bit());
}

I also attempted to use rcc.ahbenr.modify.... but that fails as the return from the RCC.constrain method is not the full AHBENR struct. Again, I know that this is something simple that I am just misunderstanding. Can anybody give me a point in the right direction for this? Thanks.

The problem here is that dp.RCC refers to the RCC API from the peripheral access crate (PAC), basically the raw register interface. By calling dp.RCC.constrain() , you take that raw API and transform it into a hardware abstraction layer (HAL) API, which is supposed to provide a safer, more convenient API layer on top of the raw register interface.

Doing this moves the PAC-level API, thereby making it unusable. This is intentional, as the HAL API could not uphold its correctness guarantee, if the user were allowed to just modify bits as they please.

As far as I can see, you have three options of solving this problem:

  1. Never call dp.RCC.constrain() .
  2. Use the HAL API for DMA.
  3. Get the PAC-level RCC API back after calling dp.RCC.constrain() .

If you choose option 1, you need to do the clock setup that the HAL API does for you manually. Maybe that's what you want, but it's certainly more work, and depending on the complexity of the microcontroller, might be error prone. I'd go for another option.

Option 2, using the HAL API for DMA: Whether this is an option depends on whether the HAL you're using supports that capability. You seem to be using stm32f1xx-hal , which does have a DMA API . There are various examples that use it in the project's repository.

As for option 3, many HAL APIs provide means to get back the PAC-level API (destroying the HAL API in the process). So you could use the HAL API for initialization, then get back the PAC API for lower-level access. stm32f1xx-hal doesn't seem to support that, unfortunately. If you know what you're doing, you could use unsafe means, like transmute to get back that PAC API, but it's probably better to just send a pull request to the HAL, adding a method that gives you back the PAC API.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM