EBC Exercise 11 gpio Polling and Interrupts

From eLinux.org
Revision as of 14:17, 13 September 2020 by James Werne (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

thumb‎ Embedded Linux Class by Mark A. Yoder

In the previous exercise (EBC Exercise 10 Flashing an LED) we saw how to interact with the general purpose I/O pins via the command shell and the sysfs files. These are rather easy ways to work with gpio; however they tend to be slow and require a lot of the CPU. In this exercise we explore using sysfs via C. We also see how using interrupts can greatly reduce the CPU usage and increase our max output speed.

gpio via C and sysfs

Since /sys/class/gpio/gpio60/value is just a file, we can read and write it from a C program just as easily as from the shell. Example of GPIO access from within a C program is a nice example of how it's done, but the page is gone. I've cleaned it up a bit and put a copy called togglegpio.c in exercises/gpio. If your git repository is set up just:

beagle$ cd exercises
beagle$ git pull
beagle$ cd gpio
beagle$ gedit togglegpio.c &

(Follow the instructions EBC_Exercise_05_Getting_Exercise_Support_Materials if you aren't set up for git.)

It's presently hardwired to use gpio130. Later you will get to make it work with any port.

  1. Compile and run it. Does the correct waveform appear on the oscilloscope?
  2. Use htop to measure the CPU usage.
  3. Try different periods. Make a chart of the input period vs. the measured period vs. CPU usage.
  4. How stable is the waveform? Look at several cycles. Are they always the same length. Explain.

This program is really interrupt based. When the usleep command is run, the process suspends until the correct time has elapsed. Other processes are allowed to run. When the time is up the CPU is interrupted and our process is allowed to continue.

gpio via Interrupts

Next we want to write some code that will read one gpio pin and copy its value to another. We could modify togglegpio.c to continually read one pin and write it to another, but that would wither be slow at responding to changes (a usleep is used between reads), or it would take all the CPU time (always reading in case a change was made).

A better approach is to let the OS tell you when the input has changed. In a traditional microprocessor one would set up the input pin to interrupt the processor when its input value has changed. We'll do something similar here.

The folks at RidgeRun have a nice example of how this is done.

Look over the example. The first part should be familiar. The new stuff starts here. It describes how to use the poll() command to wait until the gpio pin has changed. Your process will block (i.e. let other processes run) while poll() waits for an interupt to occur.

I've put a modified copy of gpio-int-test.c in gpio. Get it. Study it. Compile and run it. You'll need to setup an input signal. Use the switch from a previous exercise. It is on gpio7. Try it. Does the program respond correctly?

thumb‎ Embedded Linux Class by Mark A. Yoder