I'm scratching my head because I can't write and read some/most peripheral registers. I'm using Rust here and the setup code from the rp2040-hal.
The following code tries to write 0x42
to the DMA's CH0_READ_ADDR
register (0x50000000
) and reads it back:
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());
}
This outputs:
ptr 0x50000000
reg_before 0
reg_after 0
This happens with several registers I tested. However, with the Watchdog's scratch register WATCHDOG_SCRATCH0
(0x4005800c
) (as suggested in the example on datasheet p.19), everything works as expected.
I thought that maybe that peripheral is not clocked or so, but I didn't find anything useful in the datasheet. Perhaps somebody has an idea on what's going wrong here.
#![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 {
}
}
Ok, found out: It is about the resets of the chip.
The datasheet states in 2.14.1:
Every peripheral reset by the reset controller is held in reset at power-up. It is up to software to deassert the reset of peripherals it intends to use.
So in this case the DMA
bit of the RESET
register has to be cleared:
pac.RESETS.reset.modify(|_, w| w.dma().clear_bit());
Afterwards the registers can be written to and read from as expected.