This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM623: GPIO Status Not Updating in Output Mode

Part Number: AM623
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

hI,

I am working with GPIO pins and experiencing an issue with the following behavior:

  • When the pin is configured as PIN_INPUT (in pinmux) both the write and status (read) operations are functioning as expected.
  • However, when the pin is configured as PIN_OUTPUT (in pinmux), while the write operation works and the pin is driven high/low, the status (read) does not update correctly. Even when the pin is set high, the status shows as low.

library using for gpio: libgpiod

  • When I use gpioset gpiochip0 42=1, the LED connected to GPIO pin 42 turns on in our custom board, indicating that the pin is successfully set to high.
  • However, when I try to read the status of the same pin using gpioget gpiochip0 42, it returns 0 (low) instead of 1 (high), even though the pin is set high.( issue occurs specifically when the pin is configured as PIN_OUTPUT)

I have ensured that the pinmux is configured correctly, but the issue persists.

Could you please help investigate why the status is not reflecting the output state?

Regards,Vikash

  • Hi Vikash,

    Thanks for your query.

    Can you please tell which SDK are you using?

    What is the version of the SDK used?

    Regards,

    Tushar

  • Hi Tushar,

    SDK: tisdk(yocto)- 09.02.01.09
    Regards,Vikash

  • Hi Tushar,

    Any update?

    Regards, Vikash

  • Hi Murali,

    I am routing your query to one of my team member who is more familiar on Linux development for further comment. Please expect response in a day or two.

    Regards,

    Tushar

  • Hi Vikash,

    gpioget and gpioset will change the direction of the GPIO to input and output respectively. When a GPIO changes direction, the previous context is lost so running 'gpioset xyz=1' then 'gpioget xyz' will always result in an unexpected result.

    Best Regards,

    Anshu

  • Hi Anshu,

    1.  Could you please clarify why I am getting the expected result when setting PIN_INPUT in the device tree for a GPIO pin?
    2.  As per my understanding pin which is output in HW design should be configured as PIN_OUTPUT in device tree file but it is not giving expected value when we are trying to read the status. Can you confirm the exact reason?
    3. Additionally, is it considered good practice to configure PIN_INPUT in the pinmux DTS for GPIO pins, or should it only be used under specific conditions?

    Regards, Vikash

  • Hi Vikash,

    Could you please clarify why I am getting the expected result when setting PIN_INPUT in the device tree for a GPIO pin?

    When you say expected state, are you measuring with a multimeter or reading the software output? When a GPIO has not been set a value, it will be in an undefined state (~0.5V),  but software give a different reading.

    As per my understanding pin which is output in HW design should be configured as PIN_OUTPUT in device tree file but it is not giving expected value when we are trying to read the status. Can you confirm the exact reason?

    Until software defines the output state as high or low, the state will be unknown. This is independent if the GPIO in the device tree is input or output.

    Additionally, is it considered good practice to configure PIN_INPUT in the pinmux DTS for GPIO pins, or should it only be used under specific conditions?

    When a GPIO is defined as an input in the device tree, its capable of being an input or output. When a GPIO is defined as an output in the device tree, it can be only an output. If you are confident that the GPIO will always be an output, then define the GPIO in the device tree as an output. Otherwise, keep as an input.

    Thanks,
    Anshu

  • Hi Anshu,

    Thank you for your response regarding the GPIO pin configuration issues I am facing. However, I would like some further clarification on a few points to better understand the situation:

    1. Expected State Measurement: When you mentioned the undefined state of the GPIO, I was measuring the state using both software output (via gpioget and gpioset) and a multimeter. Can you elaborate on the discrepancy between the software readings and the multimeter measurements?

    2. Output Configuration: You mentioned that the state will remain unknown until the software defines it. Could you clarify how configuring the pin as PIN_OUTPUT in the device tree affects this behavior? If the pin is intended to be an output in hardware design, why does it not reflect the correct status when read as an output?

    3. Best Practices for Pin Configuration: I appreciate your insights on whether to configure pins as PIN_INPUT or PIN_OUTPUT. Could you provide more context on scenarios where defining a GPIO pin as an input might be preferable, even when the hardware design dictates it should be an output?

    4. Understanding Configuration Needs: Lastly, could you help me understand why it seems necessary to configure the pin as an input in the device tree to achieve expected results for read/write operations, despite it being designated as an output in the hardware design?

    Your clarification on these points will be greatly appreciated.

    regards,Vikash

  • Hi Vikash,

    This will be a longer post with a goal of clearing up some confusion.

    Common Links to Refer to:

    How is the pad connected to input or output?

    Below is a simple diagram of Receiver and Transmitter for the pad. By using the independent enable signals on each buffer, we can allow the pad to receive and/or transmit. These buffers allow the capability to receive and transmit. This is true for most pads on the AM62x SoC, but not all.

    Each pad support multiple functions (GPIOs, UARTs, GPMC, I2C etc.) which will be discussed later.

    What controls these enable signals for the buffers?

     For each pad on the SoC, there is a PADCONFIG register to control the settings of the Pad. See Section 14.2.1.2 Pad Configuration Registers in the AM62x TRM.

    Within each register there are important bit fields to note.

    Bit 18 and 21 which control the enable signals (RXACTIVE & TX_DIS) of the pad's buffers from above diagram.

    This is the Mux Mode which tells the multiplexer what the function of the pin is. For most cases, GPIOs are Mux Mode 7.

    For more information on what each pad's possible mux modes, see the AM62x Datasheet Table 6-1. Pin Attributes. Since each Pad support multiple functions, the mux mode helps select which function to use.

    How can we control these enable signals in Linux?

    This is done via the Linux device tree. We can use Sysconfig to generate a sample pinmuxing for the device tree.

    Here is a sample output for GPIO0_42:

    &main_pmx0 {
    	maingpio0_pins_default: maingpio0-default-pins {
    		pinctrl-single,pins = <
    			AM62X_IOPAD(0x00ac, PIN_INPUT, 7) /* (L21) GPMC0_CSn1.GPIO0_42 */
    		>;
    	};
    };
    

    What are the AM62X_IOPAD (Pinmuxing) components?

    The first field is the PADCONFIG register address offset which is the last 3 hex bits defined in the TRM and datasheet.

    The second field controls the input/output buffer which will be discussed later.

    The third field is the mux mode of the pad.

    How does IOPAD relate to the PADCONFIG register?

    Refer to k3-pinctrl.h which defines the pin control bindings: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/arch/arm64/boot/dts/ti/k3-pinctrl.h?h=ti-linux-6.6.y

    The definitions are the exact same as the PADCONFIG registers bit fields seen in the TRM.

    #define PULLUDEN_SHIFT		(16)
    #define PULLTYPESEL_SHIFT	(17)
    #define RXACTIVE_SHIFT		(18)
    #define DEBOUNCE_SHIFT		(11)
    #define WKUP_EN_SHIFT		(29)

    Since the first field of the AM62X_IOPAD is the PADCONFIG register address offset, Linux knows to write to the correct register when booting.

    What does PIN_INPUT and PIN_OUTPUT mean in the device tree?

    See below how these macros are defined:

    #define INPUT_EN		(1 << RXACTIVE_SHIFT)
    #define INPUT_DISABLE		(0 << RXACTIVE_SHIFT)
    
    /* Only these macros are expected be used directly in device tree files */
    #define PIN_OUTPUT		(INPUT_DISABLE | PULL_DISABLE)
    #define PIN_INPUT		(INPUT_EN | PULL_DISABLE)

    Notice the following:

    • INPUT is only influenced by RXACTIVE (Bit 18 from PADCONFIG)
    • OUTPUT is not influenced by TX_DIS (Bit 21 from PADCONFIG), only RXACTIVE

    This means in the device tree, PIN_INPUT means both the input buffer and the output buffer is enabled. PIN_OUTPUT means only the output buffer is enabled and input buffer is disabled. Remember, enabling the buffers allow for the functionality to receive and transmit on the pad.

    As a simple test, you can configure the device tree's pinmux in different ways and see the value stored in PADCONFIG register as seen below.

    #GPIO0_42 in the device tree as PIN_INPUT
    
    #Device tree PMX
    AM62X_IOPAD(0x00ac, PIN_INPUT, 7)
    
    From the datasheet, GPIO0_42's PADCONFIG address is 0x000F40AC
    
    root@am62xx-evm:~# devmem2 0x000F40AC
    /dev/mem opened.
    Memory mapped at address 0xffffa925e000.
    Read at address  0x000F40AC (0xffffa925e0ac): 0x00050007
    
    
    #GPIO0_42 in the device tree as PIN_OUTPUT
    
    #Device tree PMX
    AM62X_IOPAD(0x00ac, PIN_OUTPUT, 7)
    
    root@am62xx-evm:~# devmem2 0x000F40AC
    /dev/mem opened.
    Memory mapped at address 0xffff98f03000.
    Read at address  0x000F40AC (0xffff98f030ac): 0x00010007

    Notice how only Bit 18 (RXACTIVE) changed in the register reading.

    After configuring a pad in the device tree and Linux is booted, what is the voltage on the pin?

    Remember, the Linux device tree function is to describe hardware to the kernel so the kernel can manage the hardware later. The pinmuxing from the device tree only impacts the pad's buffers (the ability to receive/transmit), not the GPIO peripheral itself.

    If you measure the pin with a multimeter or digital oscilloscope right after booting Linux, it will be around ~.5V to ~.7V. This is because the pin has not been told what to do so its in an undefined state. It is dependent on a software application or userspace command to tell it what to do.

    What does the GPIO userspace commands do?

    The userspace commands write to the GPIO registers. See Section 14.8.2.1 GPIO Registers in the AM62x TRM.

    As a simple test, we can run these commands and see how the value in the registers change. The registers of interest are GPIO_DIRxx (Direction) & GPIO_OUT_DATAxx(output drive state).

    ############### Before GPIO commands are ran ############### 
    root@am62pxx-evm:~# devmem2 0x00600038 #GPIO_DIR23
    /dev/mem opened.
    Memory mapped at address 0xffffad436000.
    Read at address  0x00600038 (0xffffad436038): 0xFFFFFFFF
    root@am62pxx-evm:~# devmem2 0x0060003C #GPIO_OUT_DATA23                                                                                                                                                             
    /dev/mem opened.
    Memory mapped at address 0xffff9ce7c000.
    Read at address  0x0060003C (0xffff9ce7c03c): 0x00000000
    
    
    
    ############### After gpioset ############### 
    root@am62pxx-evm:~# gpioset 0 42=1
    root@am62pxx-evm:~# devmem2 0x00600038 #GPIO_DIR23                                                                                                                                                             
    /dev/mem opened.
    Memory mapped at address 0xffffa07a1000.
    Read at address  0x00600038 (0xffffa07a1038): 0xFFFFFBFF
    root@am62pxx-evm:~# devmem2 0x0060003C #GPIO_OUT_DATA23                                                                                                                                                             
    /dev/mem opened.
    Memory mapped at address 0xffff9e734000.
    Read at address  0x0060003C (0xffff9e73403c): 0x00000400

    Until the gpioset command was ran, the registers were in a reset state, thus there is no voltage output on the GPIO pin.

    Do the gpio commands impact the PADCONFIG register?

    No they do not. See below for an example:

    ######### Before GPIO commands ######### 
    root@am62pxx-evm:~# devmem2 0x000F40AC
    /dev/mem opened.
    Memory mapped at address 0xffffbf0af000.
    Read at address  0x000F40AC (0xffffbf0af0ac): 0x00010007
    
    
    
    
    ######### After GPIO commands ######### 
    root@am62pxx-evm:~# gpioset 0 42=1
    root@am62pxx-evm:~# devmem2 0x000F40AC
    /dev/mem opened.
    Memory mapped at address 0xffff87c58000.
    Read at address  0x000F40AC (0xffff87c580ac): 0x00010007
    root@am62pxx-evm:~# gpioget 0 42
    0
    root@am62pxx-evm:~# devmem2 0x000F40AC
    /dev/mem opened.
    Memory mapped at address 0xffff91315000.
    Read at address  0x000F40AC (0xffff913150ac): 0x00010007

    Why does gpioinfo say a pin is input when the device tree says output before running gpioset/get?

    Remember from a previous example, the value in the Direction Register is 0xFFFFFFFF before any gpioset/get command are ran. For this register, each bit represents a GPIO pin where input = 1 and output = 0. All 'F's means every pin is input. 'gpioinfo' reads input for the gpio because the default state of the register and its waiting for gpioset to change it.

    The pinmuxing does not write to the GPIO registers.

    Quick Summary

    The Pinmuxing in the device tree only impact the pad's ability to recieve and transmit. Its not responsible for driving the GPIO direction/state, rather the application or userspace commands will do it.

    From here, I'll try to address the direct questions.

    1. Expected State Measurement: When you mentioned the undefined state of the GPIO, I was measuring the state using both software output (via gpioget and gpioset) and a multimeter. Can you elaborate on the discrepancy between the software readings and the multimeter measurements?

    There is an issue with this way of testing. When using gpioset then gpioget consecutively, the result of gpioset will be unexpected. This is because the value is not retained when switching directions of the GPIO. When switching from output -> input, the previous value that output has is not saved.

    If 'gpioset X=1', the measured voltage will be 3.3V which is expected. Then if you run 'gpioget X', the measured voltage is ~0V.

    When a pad (doesn't matter if its a GPIO or not) is undefined, it will typically measure around ~0.7V.

    Output Configuration: You mentioned that the state will remain unknown until the software defines it. Could you clarify how configuring the pin as PIN_OUTPUT in the device tree affects this behavior? If the pin is intended to be an output in hardware design, why does it not reflect the correct status when read as an output?

    I covered this in the detailed explanation. Short answer, pinmuxing changes the pad's ability to receive/transmit & the GPIO commands tell the SoC what the GPIO's state is by writing to the GPIO registers.

    Best Practices for Pin Configuration: I appreciate your insights on whether to configure pins as PIN_INPUT or PIN_OUTPUT. Could you provide more context on scenarios where defining a GPIO pin as an input might be preferable, even when the hardware design dictates it should be an output?

    If the pin will always be an output (like to drive a reset signal to an external peripheral), then you can keep it as an PIN_OUTPUT. If the pin will always be input (like for a GPIO interrupt to the SoC), then keep it as PIN_INPUT.

    If there is a reason to switch between input & output, then keep it as PIN_INPUT. I don't have a use case scenario for switching between input and output. I wouldn't expect this to be done very often since there are plenty of GPIOs to choose from.

    Understanding Configuration Needs: Lastly, could you help me understand why it seems necessary to configure the pin as an input in the device tree to achieve expected results for read/write operations, despite it being designated as an output in the hardware design?

    Can you clarify what read/write means? For a specific register? Which register?

    As mentioned before, if the GPIO is not expected to receive any data and only send data, then keep the GPIO as PIN_OUTPUT.

    Best Regards,

    Anshu