nrf-rs / nrf-pacs

Peripheral Access Crates (PACs) for nRF microcontrollers
BSD Zero Clause License
27 stars 12 forks source link

Issues reading GPIOs #5

Closed ade-sede closed 3 years ago

ade-sede commented 4 years ago

I am on an nRF52840-DK. Messing around with the PAC to see if it is suitable for my project. I was not able to read a switch input from a GPIO, so I tried the following:

#![no_main]
#![no_std]

use cortex_m_rt::entry;
use cortex_m_semihosting::hprintln;

#[allow(unused_imports)]
use panic_semihosting;

use nrf52840_hal as hal;
use hal::nrf52840_pac as pac;

#[entry]
fn main() -> ! {
    hprintln!("Hello, world!").unwrap();

    let peripherals = pac::Peripherals::take().unwrap();
        let p0 = peripherals.P0;

    p0.pin_cnf[31].write(|pin| pin.dir().input());
    p0.pin_cnf[31].write(|pin| pin.pull().pulldown());
    hprintln!("{:?}", p0.in_.read().pin31().bit()).unwrap();

    p0.pin_cnf[31].write(|pin| pin.pull().pullup());
    hprintln!("{:?}", p0.in_.read().pin31().bit()).unwrap();
    loop {}
}

Semi-hosting output :

Hello, world!
false
false

I assume my pull up should make me read a one, therefore the second statement print should print true. Am I missing something essential or is there a problem here ?

Dirbaio commented 3 years ago

The issue is .write() completely overwrites the register, setting all the bits that you don't write to their reset values, so with the 2nd write you're undoing the first. If you want to modify a bit without affecting the others, you can use .modify() which does a RMW. More efficiently, you can do a single write to set both bits.

This should work:

    p0.pin_cnf[31].write(|pin| pin.dir().input.pull().pulldown());
    hprintln!("{:?}", p0.in_.read().pin31().bit()).unwrap();

    p0.pin_cnf[31].write(|pin| pin.dir().input.pull().pullup());
    hprintln!("{:?}", p0.in_.read().pin31().bit()).unwrap();