In the previous exercise ([[EBC Exercise 02 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'll explore using sysfs via C. We'll also see how using interrupts can greatly reduce the CPU usage and increase our max output speed.

+

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 ==

+

== <span style="color:green">gpio via C and sysfs </span>==

−

Since <code>/sys/class/gpio/gpio130/value</code> is just a file, we can read and write it from a C program just as easily as from the shell. [http://www.avrfreaks.net/wiki/index.php/Documentation:Linux/GPIO#Example_of_GPIO_access_from_within_a_C_program Here] is a nice example of how it's done. I've cleaned it up a bit and put a copy called '''togglegpio.c''' [http://www.rose-hulman.edu/~yoder/Beagle/exercises/ here]. ''(I think you will need to change line 165 to <code>fd = open(buf, O_RDONLY);</code> for it to work. The RidgeRun folks may need to be notified too -- [[User:Garbear|Garbear]])''. Get a copy and look it over. It' presently hardwired to use gpio130. Later you will get to make it work with any port.

+

Since <code>/sys/class/gpio/gpio60/value</code> is just a file, we can read and write it from a C program just as easily as from the shell. [http://www.avrfreaks.net/wiki/index.php/Documentation:Linux/GPIO#Example_of_GPIO_access_from_within_a_C_program Example of GPIO access from within a C program] is a nice example of how it's done. 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.

# Compile and run it. Does the correct waveform appear on the oscilloscope?

# Compile and run it. Does the correct waveform appear on the oscilloscope?

# Use '''htop''' to measure the CPU usage.

# Use '''htop''' to measure the CPU usage.

# Try different periods. Make a chart of the input period vs. the measured period vs. CPU usage.

# Try different periods. Make a chart of the input period vs. the measured period vs. CPU usage.

+

# 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.

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.

Line 20:

Line 29:

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.

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 [https://www.ridgerun.com/ RidgeRun] have a nice [https://www.ridgerun.com/developer/wiki/index.php/How_to_use_GPIO_signals example] of how this is done. Look over the example. The first part should be familiar. The new stuff starts [https://www.ridgerun.com/developer/wiki/index.php/How_to_use_GPIO_signals#GPIO_interrupts_from_user_space 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.

+

The folks at [https://www.ridgerun.com/ RidgeRun] have a nice [https://www.ridgerun.com/developer/wiki/index.php/How_to_use_GPIO_signals example] of how this is done.

−

I've put a modified copy of '''gpio-int-test.c''' [http://www.rose-hulman.edu/~yoder/Beagle/exercises/ here]. Get it. Study it. Compile and run it. You'll need to setup an input signal. gpio4 is the User button. Try it. Does the program respond correctly?

+

Look over the example. The first part should be familiar. The new stuff starts [https://www.ridgerun.com/developer/wiki/index.php/How_to_use_GPIO_signals#GPIO_interrupts_from_user_space 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?

== Assignments ==

== Assignments ==

−

=== Modify togglegpio.c ===

+

=== <span style="color:green">Modify togglegpio.c </span>===

# Modify togglegpio.c to take the gpio number.

# Modify togglegpio.c to take the gpio number.

−

# Clean things up a bit and use the structure of '''gpio-int-test.c'''.

# Presently one parameter specifies both the on and off time. Modify the code so the on and off times are controlled separately.

# Presently one parameter specifies both the on and off time. Modify the code so the on and off times are controlled separately.

# Modify gpio-init-test.c to count the number of times the User button has been pressed. Set '''edge''' to only count releases.

# Modify gpio-init-test.c to count the number of times the User button has been pressed. Set '''edge''' to only count releases.

# Copy gpio-init-test.c to '''gpioThru.c''' and modify it to copy the value of one port to another. You'll have to add code to open a second gpio port for writing (check '''gpio_set_dir''').

# Copy gpio-init-test.c to '''gpioThru.c''' and modify it to copy the value of one port to another. You'll have to add code to open a second gpio port for writing (check '''gpio_set_dir''').

−

# gpio 131 is attached to pin 19 of the Main Extension Header on the Beagle. Attach a function generator to this pin. Be sure to set the HiLevel to 1.8V and the LoLevel to 0. Does the output track the input?

+

# gpio7 is attached to pin P9_42 on the Bone. Attach a function generator to this pin. Be sure to set the HiLevel to 3.3V and the LoLevel to 0. Does the output track the input?

# What's the highest frequency the output will track the input? What's the CPU usage?

# What's the highest frequency the output will track the input? What's the CPU usage?

# What's the delay from when the input changes to when the output changes?

# What's the delay from when the input changes to when the output changes?

+

+

{{YoderFoot}}

Latest revision as of 09:58, 31 May 2013

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.

Contents

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. 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:

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

Compile and run it. Does the correct waveform appear on the oscilloscope?

Use htop to measure the CPU usage.

Try different periods. Make a chart of the input period vs. the measured period vs. CPU usage.

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.

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?

Assignments

Modify togglegpio.c

Modify togglegpio.c to take the gpio number.

Presently one parameter specifies both the on and off time. Modify the code so the on and off times are controlled separately.

Add in interrupt handler (see gpio-int-test.c) to trap ctrl-C and close things properly.

What's the highest frequency you can see on the 'scope?

Modify gpio-int-test.c

Modify gpio-init-test.c to count the number of times the User button has been pressed. Set edge to only count releases.

Copy gpio-init-test.c to gpioThru.c and modify it to copy the value of one port to another. You'll have to add code to open a second gpio port for writing (check gpio_set_dir).

gpio7 is attached to pin P9_42 on the Bone. Attach a function generator to this pin. Be sure to set the HiLevel to 3.3V and the LoLevel to 0. Does the output track the input?

What's the highest frequency the output will track the input? What's the CPU usage?

What's the delay from when the input changes to when the output changes?