无法修改 rp2040 上的外设寄存器



我抓耳挠头,因为我不能写和读一些/大多数外围寄存器。我在这里使用Rust和rp2040-hal.

中的设置代码。下面的代码尝试将0x42写入DMA的CH0_READ_ADDR寄存器(0x50000000)并将其读回来:

let ptr = (0x50000000 + 0x000) as *mut u16; // crtl
rprintln!("ptr {:p}", ptr);
unsafe {
rprintln!("reg_before {:b}", ptr.read_volatile());
ptr.write(0x42);
rprintln!("reg_after {:b}", ptr.read_volatile());
}

这个输出:

ptr 0x50000000
reg_before 0
reg_after 0

这种情况发生在我测试的几个寄存器中。然而,使用看门狗的划痕寄存器WATCHDOG_SCRATCH0(0x4005800c)(如数据表p.19中的示例所示),一切都如预期的那样工作。

我想也许外设没有时钟,但我在数据表中没有发现任何有用的东西。也许有人知道这里出了什么问题。

最小工作示例:

#![no_std]
#![no_main]
extern crate panic_rtt_target;
use cortex_m_rt::entry;
use rtt_target::{rprintln, rtt_init_print};
use rp2040_hal as hal;
use hal::pac;
use embedded_time::fixed_point::FixedPoint;
use rp2040_hal::clocks::Clock;
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
const XTAL_FREQ_HZ: u32 = 12_000_000u32;
#[entry]
fn entry() -> ! {
let mut pac = pac::Peripherals::take().unwrap();
let core = pac::CorePeripherals::take().unwrap();
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
let clocks = hal::clocks::init_clocks_and_plls(
XTAL_FREQ_HZ,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB,
&mut pac.RESETS,
&mut watchdog,
)
.ok()
.unwrap();
rtt_init_print!();
rprintln!("Hello registers!");
//let ptr = (0x4005800c) as *mut u16; // scratchreg
let ptr = (0x50000000 + 0x000) as *mut u16; // dma ch0 read addr
rprintln!("ptr {:p}", ptr);
unsafe {
rprintln!("reg_before {:b}", ptr.read_volatile());
ptr.write(0x42);
rprintln!("reg_after {:b}", ptr.read_volatile());
}
loop {
}
}

好的,发现了:是关于芯片复位的。

数据表在2.14.1中声明:

复位控制器复位的每个外设在上电复位时保持。它是由软件来取消重置它打算使用的外设。

所以在这种情况下,RESET寄存器的DMA位必须被清除:

pac.RESETS.reset.modify(|_, w| w.dma().clear_bit());

之后,可以按预期对寄存器进行读写。

最新更新