This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

GPIO pin reading wrong value

There seems to be an issue when reading GPIO pins returning false readings. I am using two pins for I2C communication, 26 and 27, I am configuring them with the required configuration for using I2C and then setting them high. However, when I go to read the inputs of these pins (which are floating, the only thing attached to them is an oscilloscope) they are falsely read as high when they are low (verified on the scope). When I then manually read the pin status from gdb I correctly see that both pins are low. Even stranger is that on the first power up I do not see the issue and the pins are correctly read as low, but if run the code a second time without restarting then I start to see the issue.

NRF_GPIO->PIN_CNF[SCLPin] = 
    (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
  | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos)
  | (GPIO_PIN_CNF_PULL_Disabled  << GPIO_PIN_CNF_PULL_Pos)
  | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos)
  | (GPIO_PIN_CNF_DIR_Output     << GPIO_PIN_CNF_DIR_Pos);    

NRF_GPIO->PIN_CNF[SDAPin] = 
    (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
  | (GPIO_PIN_CNF_DRIVE_S0D1     << GPIO_PIN_CNF_DRIVE_Pos)
  | (GPIO_PIN_CNF_PULL_Disabled  << GPIO_PIN_CNF_PULL_Pos)
  | (GPIO_PIN_CNF_INPUT_Connect  << GPIO_PIN_CNF_INPUT_Pos)
  | (GPIO_PIN_CNF_DIR_Output     << GPIO_PIN_CNF_DIR_Pos);    

nrf_gpio_pin_set(SDAPin);
nrf_gpio_pin_set(SCLPin);

unsigned int SDAVal = nrf_gpio_pin_read(SDAPin);
unsigned int SCLVal = nrf_gpio_pin_read(SCLPin);
SDAVal = nrf_gpio_pin_read(SDAPin);
SCLVal = nrf_gpio_pin_read(SCLPin);
SDAVal = nrf_gpio_pin_read(SDAPin);
SCLVal = nrf_gpio_pin_read(SCLPin);
SDAVal = nrf_gpio_pin_read(SDAPin);
SCLVal = nrf_gpio_pin_read(SCLPin);
SDAVal = nrf_gpio_pin_read(SDAPin);
SCLVal = nrf_gpio_pin_read(SCLPin);
SDAVal = nrf_gpio_pin_read(SDAPin);
SCLVal = nrf_gpio_pin_read(SCLPin);

if( SDAVal && SCLVal )
{
    //Continue with I2C initialisation here
}

I've added the pin reading multiple times to ensure it isn't related to errata 3.48 (using the Rev 1 sillicon). Here's output from debugging with GDB:

Breakpoint 1, ###
    at ###.c
:229
229         if( SDAVal && SCLVal )
(gdb) print SDAVal
$1 = 0 '\000'
(gdb) c
Continuing.

--- this is where I rerun the function ---

Breakpoint 1, ###
    at ###.c
:229
229         if( SDAVal && SCLVal )
(gdb) print SDAVal
$2 = 1 '\001'
(gdb) print nrf_gpio_pin_read(26)
$3 = 0
(gdb) print nrf_gpio_pin_read(27)
$4 = 0
(gdb) print nrf_gpio_pin_read(1)
$5 = 1

Any idea why this is happening? I'm using the S132 v5.0.0 softdevice on an nRF52832

  • Strange. Maybe the GPIO logic needs some time to stabilize after a power on reset.

    1. What happens if you try to put a small delay before you read the pins?
    2. As I understand it you do not power off the device between the first faulty, and the second correct reading? Only a pin or softreset?
    3. You notice that one or both of the pins reads low at the line if( SDAVal && SCLVal )?
    1. That seems to somewhat resolve it - for a short period of time. With a delay of 3ms it now works fine if I run the code as many times as I want in a row, if however I leave the module alone idle and then run it again after about 10 seconds, it goes back to the old behavior of wrongly detecting the pins as high.
    2. No reset at all, we have a command line interface for running parts of code, when no command is entered the system is idle.
    3. Both pins wrongly read high.
    1. Do you have anything connected to the pins that can be messing with the voltage levels? Logic low is not the default state of a TWI bus so I imagine that if you have a TWI slave connected it may be manipulating the logic levels under certain conditions.
    2. How do you use the Scope? Are you triggering on positive edges or something? Are you sure are capturing every event that might drive the pins high for short periods of time?
    3. Can you upload more of your code?
    1. There is nothing connected to the pins, no I2C slave devices, either nothing is connected or the scope is connected.
    2. I've used it in triggering mode and in non-triggering mode, when it wrongly reads that the pin status is high I can see on the scope that it is low
    3. I'll have to play more with the code and see if I can get a sample project showing the issue when I get time.
  • I have managed to recreate the behaviour on my desk. I'll ask around and figure out if this is expected or not. It is holiday season in Norway now, so I can't promise any answers before after new year.

    In the meantime, it seems to work as one would expect if you just enable the pullup resistor. Pulldown doesn't work of some reason.

Related