wiki:TracingGPIOs

Tracing GPIOs

A General Purpose Input/Output? is usually a pin on a chip that can be configured and controlled directly by software. On the XScale CPUs, most of the pins can be configured either as "alternate function" controlled by hardware (like MMC controller pins) or as a GPIO that is driven directly by software. An important step in porting Linux to a handheld is figuring out what each GPIO controls.

Getting the tools

Most of our tracing and experimenting tools are located in the tools git repository. You can checkout a copy with:

git clone git://git.hackndev.com/tools

Or if you have commit access:

git clone git.hackndev.com:/srv/git/tools

To build the Linux tools you'll need an ARM cross-compiler (or a native compiler in Linux on your handheld). What I usually do is run Debian/armel and install gcc and git directly on the handheld. Then I ssh in over USB networking and clone, compile and run the tools on the device itself.

For the Palm OS tools like gpiotrace, we usually include a binary PRC along with the source to save you the trouble of setting up the Palm SDK.

Alternate Functions and directions

To start with we want to note all the pins that Palm OS configures as alternate functions. This is the quickest way to rule out most of the pins as being used for other functions. Begin by turning on all the functions you can in Palm OS (enable bluetooth, beam receive, phone etc). If there's a function like the camera that only works in a specific program, just run it briefly and then just quit it. Chances are the alternate functions will still be setup.

Next, run gpiotrace.prc briefly to get a dump of the GAFR registers. You just need to run it so it says "hack registered" and then go back to the Palm OS home screen. You can then take out the SD card and put it in your computer. Move GPIOs.txt off the SD card onto your hard disk somewhere and rename it to something meaningful like GPIOs-everything-on.txt. Now run gpiotrace2wiki to generate an initial GPIO table for the wiki, see Treo680Hardware for an example.

~/hackndev/tools/gpiotrace $ ./gpiotrace2wiki GPIOs-everything-on.txt
||'''GPIO'''||Dir||Level||AF||Function||
||'''0'''||In||0||0||af0||
||'''1'''||In||1||0||af0||
||'''2'''||In||1||0||SYS_EN||
||'''3'''||In||1||0||af0||
||'''4'''||In||1||0||af0||
||'''5'''||In||1||0||PWR_CAP<0>||
...

Now create a hardware page in the wiki for your handheld if one doesn't already exist and paste in the table. gpiotrace2wiki will attempt to name any GPIO configured as an alternate function. See the PXA developer's manual for details about what each mean. Any labelled "af0" you'll have to figure out as the pin is configured as a GPIO.

Tracing pins configured as GPIOs

For pins that are configured as GPIOs things get more interesting, generally the process goes something like:

  1. Run gpiotrace.prc
  2. Perform some interesting action.
  3. Rename GPIOs.txt to something meaningful.
  4. Analyze it with gpiotrace2html to try to figure out what GPIOs are related to the acion.
  5. Goto 1.

Remember: remove or rename GPIOs.txt between each run as gpiotrace will just append to it.

What gpiotrace does is register a callback with Palm OS so that on many system events (idle, application change etc) it will dump the contents of the GPIO registers to a GPIO.txt file on the SD card. The output looks like this:

GPLR [0xbfde1f7d] 0x0c0501fe 0xfc724dc4 0xd0dd2fff 0x01e1ff81 [0xbfde1f7d] || GPDR [0xbfde1f7d] 0xcff90400 0xff22bfc1 0x93cdffff 0x006dff81 [0xbfde1f7d] || GAFR_L [0xbfde1f7d] 0x0e000000 0x60088052 0x02aaaaaa 0x00000000 [0xbfde1f7d] || GAFR_U [0xbfde1f7d] 0xa500001a 0xaaa07959 0x45440f08 0x00000000 [0xbfde1f7d]
GPLR [0xbfde1f7d] 0x0c0501fe 0xfc724dc4 0xd2dd2cc0 0x01e1ff81 [0xbfde1f7d] || GPDR [0xbfde1f7d] 0xcff90400 0xff22bfc1 0x93cdffff 0x006dff81 [0xbfde1f7d] || GAFR_L [0xbfde1f7d] 0x0e000000 0x60088052 0x02aaaaaa 0x00000000 [0xbfde1f7d] || GAFR_U [0xbfde1f7d] 0xa500001a 0xaaa07959 0x45440f08 0x00000000 [0xbfde1f7d]
GPLR [0xbfde1f7d] 0x1c0505fe 0xfc724dc4 0xd0dd3fff 0x01e1ff81 [0xbfde1f7d] || GPDR [0xbfde1f7d] 0xcff90400 0xff22bfc1 0x93cdffff 0x006dff81 [0xbfde1f7d] || GAFR_L [0xbfde1f7e] 0x0e000000 0x60088052 0x02aaaaaa 0x00000000 [0xbfde1f7e] || GAFR_U [0xbfde1f7e] 0xa500001a 0xaaa07959 0x45440f08 0x00000000 [0xbfde1f7e]
GPLR [0xbfde1f7e] 0x0c0405fe 0xfc724dc4 0xd2dd3fff 0x01e1ff81 [0xbfde1f7e] || GPDR [0xbfde1f7e] 0xcff90400 0xff22bfc1 0x93cdffff 0x006dff81 [0xbfde1f7e] || GAFR_L [0xbfde1f7e] 0x0e000000 0x60088052 0x02aaaaaa 0x00000000 [0xbfde1f7e] || GAFR_U [0xbfde1f7e] 0xa500001a 0xaaa07959 0x45440f08 0x00000000 [0xbfde1f7e]

The values in square brackets are timestamps in seconds.

When you're finished tracing just remove the SD card. On some handhelds rerunning gpiotrace will stop logging (it'll say "hack disabled") but on others this doesn't seem to work.

Once you have an interesting logfile, move it to your PC and rename it to something meaningful. You can then analyze it by running gpiotrace2html like this:

hackndev/tools/gpiotrace $ ./gpiotrace2html GPIOs-680-bt-on-off.txt > GPIOs-680-bt-on-off.html

Beware: large logs can generate several megabyte HTML pages which might cause your browser to use a lot of memory.

gpiotrace2html generates a sort of psuedo-graphical representation of the GPIO states using coloured HTML tables. In this example, Sleep_Walker ran gpiotrace and then toggled on and off the silent switch. If you scroll down to GPIO 15 and then across to frame 40, you can see where the silent switch is turned on for five seconds. Then if you look down at GPIO 44 you can see PALM OS activates the vibrator briefly to shake the phone and indicate it's now on silent mode. Sleep_Walker has posted a whole bunch of traces which might help you get an idea of the sort of things to trace.

Once you've figured out what something is, note it in the hardware page for your handheld in the wiki. Also, attach your trace logs to the wiki page so that you and others can find them later and re-analyse, or you can ask for help if you're unsure of what something means.

Quicker turnaround time

It takes quite a while to transfer your logs from handheld to PC and then analyse them. When looking at simple things like plugging in and out the AC power cable, I just run haret/p and dump the GPLR registers over and over while doing the action and looking for changes. You can press "up"to rerun the last command you did.

Note that in Palm OS the hardware registers are mapped to the virtual address 0x9XXXXXXXX instead of the physical address 0x4XXXXXXX. So for example, the PXA developer manual says that GPLR1 is at 0x40E00004, so in Palm OS it will be at 0x90E00004 and you'd use a haret/p dump command like:

dump 90e00004

Testing outputs

Warning: Please be careful when testing. Do NOT configure something Palm OS has as an input as an output. There is a chance you could damage your hardware by doing this by causing a high current in the circuit. However, configuring an output as an input is generally harmless as the inputs are high-impedance.

Once you have found some output GPIOs that are interesting (like LEDS, vibra) you might like to test them in Linux before writing a complete driver. There are a couple ways of doing this. In the older linux-hnd tree there is a "GPIOed" kernel module which you can enable that allows you to control and configure the GPIOs through /proc. I will, however, describe a different method that doesn't require any kernel support.

There are a group of tools devmem2.c, gpio-val.c and gpio-dir.c which from within Linux you can use to write directly to hadware registers, without needing any kernel drivers or special support. These work by mmaping the /dev/mem device which gives access to "raw" physical memory. You'll need to compile them like this:

$ path/to/arm/gcc -O2 devmem2.c -o devmem2
$ path/to/arm/gcc -O2 gpio-val.c -o gpio-val
$ path/to/arm/gcc -O2 gpio-dir.c -o gpio-dir

gpio-val will view or set (for outputs) the level of a GPIO. gpio-dir will view or set whether a GPIO is an output or input (0=input 1=output). Please take heed of the warning above when using this tool.

devmem2 lets you read and write to arbitrary memory addresses, which can be useful when experimenting with other registers, such as the USB ones.

Last modified 10 years ago Last modified on 10/27/08 11:53:56