cancel
Showing results for 
Search instead for 
Did you mean: 

First read on GPIO configured as Digital Input reads wrong value

RMand
Senior

I am using STMCubeMX to generate HAL code to control the GPIO on a STM32L071Rb MCU.

I have set GPIO PA6 as "GPIO Input". The generated code initializes the GPIO by calling the function MX_GPIO_Init() where it "appears to be setting up the PA6 correctly".

This pin is pulled up on my PCB and reads properly under normal operating ocnditions.

However, the very first time that my program attempts to read this pin the HAL function returns a '0'. Subsequent calls to this same function and same pin return a '1'.

I copied the HAL code for reading a GPIO pin below. When I step through this code it looks like the first time for the PA6, the condition at line 8 FAILS and therefore the function returns the value GPIO_PIN_RESET. In the debugger, the value of GPIOx->IDR shows as 0x6000 and the value of GPIO_pin shows up as 0x40.

Do I need to take some extra steps in my initialization code such as: read all the GPIO once before starting any analysis, or change something in the STMCubeMx input configuration?

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  GPIO_PinState bitstatus;
  
  /* Check the parameters */
  assert_param(IS_GPIO_PIN_AVAILABLE(GPIOx,GPIO_Pin));
  
  if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
  {
    bitstatus = GPIO_PIN_SET;
  }
  else
  {
    bitstatus = GPIO_PIN_RESET;
  }
  return bitstatus;
}

7 REPLIES 7
S.Ma
Principal

Maybe pins are analog mode as option after reset? Is the issue at power up or also after reset?

TDK
Guru

Could be reading the pin value before the pullup has time to pull it up. Put a delay before the read to see if it has an effect. Capture the pin state on a scope.

If you feel a post has answered your question, please click "Accept as Solution".

The pin is configured as a GPIO_INPUT and not as an analog input. Here is the output of the STMCubeMx for PA6.

I not not sure how to interpret the "GPIO_NOPULL" -- I was assuming/hoping that if an external input is pulled up or down it will be truly reflected in the value being read back.

/*Configure GPIO pin : PA6 */
  GPIO_InitStruct.Pin = GPIO_PIN_6;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

I don't quite understand your logic here. There are probably a few hundred (maybe thousand) MCU instructions after the GPIO has been configured and before my application reads it the first time. So what exactly is the "delay" that I am shooting for?

Besides, this GPIO is periodically read for changes and those reads track the changes reasonably well.

Bottomline -- I would love to know what this delay would/should be and if there is any specification for that delay in the data sheet or reference manual.

BTW, I added a 1 second delay after the GPIO is configured and initialized, and before I read it for the first time.

Absolutely no difference -- same behaviour.

I do not understand why the value of the GPIO->IDR is a 0 on PA-6 when the input is actually pulled up high -- when the MCU executes this line:

if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)

> In the debugger, the value of GPIOx->IDR shows as 0x6000 

Then PA6 is indeed low.

Read out and check other GPIO registers.

Measure the voltage on the pin directly, osing oscilloscope, touching the pin itself, and observe IDR.

What is connected to that pin?

JW

prain
Senior III

also check the device errata sheet. check all peripherals connected to PA6 for unexpected behavior