There are three pins capable of PWM (pulse-width modulation) exposed on the C3/C4 BeagleBoard expansion header. PWM is useful for control of a number of devices, from LEDs (which can be faded smoothly with PWM) to DC motors. For robotics, this means that three hobby servos can easily be controlled by the Beagle given nothing more than a simple level-shifting circuit, with no CPU usage to speak of.

Alternative approaches are possible. servodrive is a kernel module that emits servo control PWM using straight GPIO (this page also claims that straight 1.8 V from the Beagle is sufficient to control servos). This page shows how to use threading and GPIO to accomplish PWM in userspace. The rest of this page focuses on use of the OMAP's hardware PWM capabilities.

Contents

OMAP Mux Configuration

Because the PWM pins are not set as such by default, the OMAP's mux must be configured to expose them before they can be used. See BeagleBoardPinMux for more details on this procedure. The short version is to add the following lines to the definition of board_mux[] in arch/arm/mach-omap2/board-omap3beagle.c (this has been tested with the 2.6.33 OMAP branch of the kernel).

Obviously these lines should precede the line terminating the array. This will likely be in a block conditional on CONFIG_OMAP_MUX, so you need to have the CONFIG_OMAP_MUX option set in your kernel config.

Activating PWM via Timer Registers

PWM output on the BeagleBoard is done via the OMAP processor's general-purpose timer mechanism, described in the OMAP35x TRM in section 16.2.4 (page 2546, or page 2698 of the DM3730 TRM). To briefly summarize this (and simplify significantly), the general-purpose timer is a continuously-incrementing counter that can be configured to toggle the PWM output high when a certain value is reached, and low when it overflows. By adjusting the first number the duty cycle can be set. Setting the value the counter starts at can be used to set the frequency of the PWM.

Each GP timer has a 4K block for memory-mapped registers (see TRM Table 16-12, page 2558 OMAP3530 or page 2710 DM3730). The start addresses of these blocks for the timers on the BeagleBoard are listed below.

BeagleBoard C3/C4 GP Timer Base Addresses

Timer

Base address

Expansion header pin

GPTIMER9

0x4904 0000

4

GPTIMER10

0x4808 6000

6

GPTIMER11

0x4808 8000

10

These are the registers relevant to our purpose:

BeagleBoard C3/C4 GP Timer Registers

Name

TRM section

Offset

Description

TCLR

16.3.2.6 (p. 2568/2719)

0x024

Control register.

TCRR

16.3.2.7 (p. 2570/2721)

0x028

The counter. Increments with the clock when the timer is running.

TLDR

16.3.2.8 (p. 2571/2722)

0x02c

Timer load register. Holds the value assumed by TCRR when it overflows.

TMAR

16.3.2.11 (p. 2575/2725)

0x038

Value to be compared with the counter.

Interacting with Timer Registers in Linux

The best way to interact with the timer registers is to use the kernel module in development as a Google Summer of Code project (this driver is currently, as of July 2010, in development).

Historically interaction with the registers could be done via the special device /dev/mem. This file contains a live view of the contents of physical memory --- meaning that reading and writing to the physical address of a timer register as an offset in /dev/mem reflects the actual thing.

There is one complication, though, in that reads and writes to the OMAP registers cannot be done with byte-oriented I/O (such as the write() system call); however, this can be worked around by using the mmap() syscall. This means that a pointer to a register can be cast to volatile uint32_t* and function correctly.

OMAP3530 PWM library

There is a small library available to simplify manipulating the timer registers via /dev/mem. It is made available under the LGPL 2.1 or MIT license.

Information regarding compilation of this program is not included in any README file so to ease compilation problems use the following. Keep in mind this has been only tested when compiled on the beagleboard and not cross-compiled though it should still shed light if you have problems.