paulv
Posts: 558
Joined: Tue Jan 15, 2013 12:10 pm
Location: Netherlands

Interesting GPIO pad changes with device tree

Thu Jun 04, 2015 8:14 pm

I have a little mystery that hopefully someone can explain. [edited]
I'm using the following Raspberry Pi :

Code: Select all

[email protected] ~ $ sudo cat /proc/cmdline
dma.dmachans=0x7f35 bcm2708_fb.fbwidth=656 bcm2708_fb.fbheight=416 bcm2708.board                            rev=0xd bcm2708.serial=0x4487f91f smsc95xx.macaddr=B8:27:EB:87:F9:1F bcm2708_fb.                            fbswap=1 sdhci-bcm2708.emmc_clock_freq=250000000 vc_mem.mem_base=0x1fa00000 vc_m                            em.mem_size=0x20000000  dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1                             root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
[email protected] ~ $

Code: Select all

[email protected] ~ $ uname -a
Linux pitest 3.18.14+ #793 PREEMPT Sat May 30 13:15:19 BST 2015 armv6l GNU/Linux
[email protected] ~ $
I’ll recap the GPIO pads here a bit, because it seems to me that a few things have recently changed a bit after the latest firmware release (using the device tree kernel?).

The following GPIO-ports have a pull-down by default: In order of the P-1 connector: GPIO-17, 27, 22, 10 (MOSI), 9 (MISO), 11 (SCLK), 23, 24 and 25.
This pull down is regardless of an SD card present, and the pads will be pulled-low as soon as 5V is applied to the Pi.
You can easily measure this pull effect when you connect two high value resistors (significantly higher than the 50K pull resistors on the SOC- I use 1MOhm) from the GPIO pad to 3V3 and from the pad to GND. This allows you to observe the pulling high, low or none (tri-state). All the above ports show a voltage of about 140mV, suggesting to me that the pad's 50K resistor is used to create this pull-down.

When you program a pull high on any of these pads for example, this pull setting is kept during a halted mode (sudo halt), and will only switch back to the default pull low after a reboot (shortening P6) or after a software reboot (sudo reboot).
I think this is changed with the most recent firmware change because earlier, the pull seemed to be kept (in some form of EEPROM) during these states and only loose the value after a full removal of the power. This is in the BCM2835-ARM-Peripherals datasheet:
The GPIO Pull-up/down Register controls the actuation of the internal pull-up/down control line to ALL the GPIO pins. This register must be used in conjunction with the 2 GPPUDCLKn registers.
Note that it is not possible to read back the current Pull-up/down settings and so it is the users’ responsibility to ‘remember’ which pull-up/downs are active.
The reason for this is that GPIO pull-ups are maintained even in power-down mode when the core is off, when all register contents is lost.
Interestingly, on my Pi now, this resetting of the pull state happens at the same time as the programming of the TXD and RXD pins, and that is 700mS into the boot sequence. The pull programming is no longer preserved over a reset or reboot, it defaults back during the boot process. If your connected hardware relied on this "feature", you better watch out.

So far so good, but there are 7 more rather special ports.
First of course the already mentioned TXD (GPIO-14) and RXD (GPIO-15). These ports are programmed to a pull-high 700mSec into the boot process, but we'll leave these two out for this discussion.

Then we have SDA0 (GPIO-2) and SCL0 (GPIO-3). As you can see on the Pi schematic, these ports are pulled high by 1K8 resistors mounted on the Pi PCB. These resistors are small in value so the pad will always read 3V3.

Now to the really interesting pads - GPCLK0 (GPIO-4), CE0 (GPIO-8) and CE1 (GPIO-7), because at first sight, they seem to behave differently.
These 3 ports are pulled high by default. They are not programmed by the SOC that way, because they are pulled high as soon as 5V is applied to the board, and even without an SD card present. I suspect again that the on-board 50K pull resistors are used, because if you use the 1M resistor measurement method above, the measured voltage is 3V0, not 3V3.
The interesting bit is that when you program the pull for these ports to low, the ports will stay that way, until we execute a halt and reset the SOC with J6. Again, after 700 mSec into the boot sequence, the pull is reset from our low setting to the default pull high again. The same happens with a sudo reboot. And again the pull goes high when also the TXD is activated, so again after 700 mSec into the boot sequence.

The screenshot below shows the TXD activity (top trace) during the boot sequence after a sudo reboot, and also the re-programming of the pull from the CE1 pad to the default high 700mSec into the boot sequence.
TXD and CE1.JPG
TXD and CE1.JPG (21.34 KiB) Viewed 3290 times
BTW, here is a screenshot with the older kernel versions:
TXD and GPIO older kernel.jpg
TXD and GPIO older kernel.jpg (40.02 KiB) Viewed 3238 times
Note the difference in the timing of the pull resetting of the CE1 pad.

So here is my question: How can the default for these 3 pads be pull-high already at power-up and without any code seemingly running (no SD card present)?

Are these 3 pads really different, or is the same method used for all the pads, also those that are pulled low by default? Common sense would dictate a yes, but what is the implication of all this?

My only explanation is that the pull settings for all pads are indeed stored in some form of EEPROM, and they will stay that way after a full powercycle.

In any case, with the latest kernel, using device trees, all pads now reset to their default state during a (re)boot and after a power cycle.

Can someone please confirm or explain this?

paulv
Posts: 558
Joined: Tue Jan 15, 2013 12:10 pm
Location: Netherlands

Re: Interesting GPIO pad changes with device tree

Mon Jun 08, 2015 11:43 am

Here is some more interesting information regarding the GPIO pads.

Many most likely do not know or realize that over the course of the many Debian kernel changes for the Raspberry Pi, the GPIO pad configuration has been changed.

In earlier kernel versions, the GPIO pads defaulted to no-pull, or tri-state. This is probably the reason why the RPi.GPIO.cleanup() for Python still works that way. It turns all pads to input, with no pull, or tri-state. That code was not updated to reflect the latest changes. (I submitted a change request).

In the meantime however, the pads now default to a pull-low. Interestingly, this is also the default pull action for the BMC2835 SoC, because when the SoC is powered-up without an SD card present, this is what you can measure on the pads. This also coincides with the latest datasheet. (table 6.2 of the BCM2835_PDF_Datasheet)

Furthermore, the timing of the various pads also changed. Initially the pads where set about 1 second into the boot process, and right now, it only takes about 700mS. You still should take care of your connected hardware, because in these first 700mS., several pads are changing state.

I have made a table to show the differences between the oldest kernel version I happened to still have, the 3.6.11+ #538 release and also the very latest kernel, 3.18.14+ # 793 from May 30st, 2015.
Unfortunately, I know of no easy format to put a table in this forum post, so I had to jump through some hoops to show my Excel table here:
GPIO Kernel Versions.jpg
GPIO Kernel Versions.jpg (54.45 KiB) Viewed 3187 times
Note that all measurements were made with two 1MOhm resistors connected to a GPIO pad. One from 3V3 to the pad, and one from the pad to GND.
Where I show 140mV, that means a pull-low.
When it shows 3V0 or 3V3, that is a pull-high, and where I shows 1V0, that means no-pull or tri-state.
A green cell means that this is a situation that is unusual and changes during the boot process.


You can debate this, but I believe that with the newer kernel, things are improved from the older one. With the older kernel code, the GPIO pads moved from a pull-low to a tri-state about a second into the boot process. Keeping the pins at a pull-low as a default, is fine as long as the pads are configured as inputs, which they are. It's more straightforward to have external stuff work with this.

Unfortunately, with all these changes, we have lost the ability to program a pad with a certain pull, and keep it that way. We first lost the ability to program that across power cycles, and now even across a re(boot) or restart. The designers apparently still use this feature (GPCLK0, CE0, CE1 - look at the post above), but users have no more access to it.

I tried to rpi-update to even earlier versions of the kernel, but could not get a bootable SD card, maybe one of you is more successful because I am pretty sure there were more changes earlier on.

It is a pity that there is not more information forthcoming with the kernel releases when it comes to GPIO related changes. The Pi has GPIO, it is a major feature and is used a lot. Unfortunately, this function is already shrouded with some lacking information and specifications. My point is that the developers should try to be more careful, and inform the millions of users better.

notro
Posts: 695
Joined: Tue Oct 16, 2012 6:21 pm
Location: Drammen, Norway

Re: Interesting GPIO pad changes with device tree

Mon Jun 08, 2015 1:11 pm

I don't know anything about the initial poweron state, but the firmware sets the gpios. It uses a builtin gpio setup unless /boot/dt-blob.dts exists. The default is shown in the file linked to at the bottom of this page: https://www.raspberrypi.org/documentati ... uration.md

When Linux boots with Device Tree it can set pins depending on whether a device is enabled or not (spi, i2c and i2s are disabled by default).
See the gpio sub nodes which are linked from their respective drivers: https://github.com/raspberrypi/linux/bl ... b-plus.dts
Ref: https://www.kernel.org/doc/Documentatio ... 5-gpio.txt

Code: Select all

&gpio {
  spi0_pins: spi0_pins {
    brcm,pins = <7 8 9 10 11>;
    brcm,function = <4>; /* alt0 */
  };
};

&spi0 {
  pinctrl-names = "default";
  pinctrl-0 = <&spi0_pins>;
};
Some drivers sets the pins directly for use without Device Tree, like i2c-bcm2708. See bcm2708_i2c_init_pinmode() in https://github.com/raspberrypi/linux/bl ... -bcm2708.c

Return to “Device Tree”