Main Content

Pin Muxing

This example shows you how to use Embedded Coder® Support Package for BeagleBone® Black Hardware to set the correct hardware pin mux configuration to run Simulink® models accessing the physical pins of the BeagleBone Black hardware.

Introduction

BeagleBone Black hardware has two expansion headers, P8 and P9, that provide extensive I/O capability. Each expansion header has 46 connectors. A subset of these connectors are interfaced to the Sitara AM335x processor pins. The Sitara AM335x processor contains many peripheral interfaces such as general purpose digital I/O, I2C, SPI, etc. In order to reduce package size and lower overall cost, most of the I/O pins of the processor are multiplexed. Each I/O pin can assume one of 8 different modes that also select the functionality of the pin. The I/O pins of the processor must be configured to the desired mode for correct functionality.

In this example, we demonstrate how to configure the pin muxing of the BeagleBone Black hardware to achieve desired functionality. We show how to read the pin muxing configuration from within MATLAB® and change the pin muxing configuration to be compatible with I/O blocks used in a Simulink model.

Prerequisites

We recommend completing Get Started with Embedded Coder Support Package for BeagleBone Black Hardware example.

Required Hardware

To run this example you need the following hardware:

  • BeagleBone Black hardware

  • 1 k $\Omega$ resistor

  • 10 k $\Omega$ potentiometer

  • An LED

  • A breadboard and jumper cables

Task 1 - Display Pin Mux Configuration

In this task, you will display the current pin mux configuration of the P8 and P9 expansion headers.

1. Create a handle to a beaglebone_black object by executing the following on the MATLAB command window:

bbone = beaglebone_black

2. The beaglebone_black object has convenience functions to programmatically read the current pin muxing configuration of the BeagleBone Black expansion headers. To read the pin muxing configuration and draw a diagram as a MATLAB figure, execute the following command on the MATLAB command window:

showPinMux(bbone, 'P9')

The command above opens a MATLAB figure containing a picture of the P9 header and current pin function for each of the connectors on the expansion header. The picture is color coded with green indicating GPIO pins, red +5V, yellow +3.3V, dark gray ground, and blue analog input. You can also programmatically read the current pin configuration by executing the following command on the MATLAB prompt:

pinmux = readPinmux(bbone, 'P9')

The readPinmux method returns a structure containing information about the pin mux configuration including the pin number, mode, direction, pull-up / pull-down resistor state and slew rate. For more information about these parameters, refer to AM335x Sitara™ Processors data sheet.

Task 2 - Modify Pin Mux Configuration

The BeagleBone Black hardware running a Linux® kernel version 3.8 or newer uses a method called Device Tree Overlays (DT) to describe the pin mux configuration. A DT file is contains a description of hardware pin mux configuration. The BeagleBone Black Debian Linux distribution contains a number of DT files in the /lib/firmware folder. In this section, we use DT files to change the pin mux configuration.

1. To see a list of available DT files, execute the following on the MATLAB command line:

system(bbone, 'ls -al /lib/firmware/*.dtbo')

You will see an output similar to the following:

ans =
-rw-r--r-- 1 root root  1042 Apr 23  2014 /lib/firmware/ADAFRUIT-SPI0-00A0.dtbo
-rw-r--r-- 1 root root  1115 Apr 23  2014 /lib/firmware/ADAFRUIT-SPI1-00A0.dtbo
-rw-r--r-- 1 root root   865 Apr 23  2014 /lib/firmware/ADAFRUIT-UART1-00A0.dtbo
-rw-r--r-- 1 root root   865 Apr 23  2014 /lib/firmware/ADAFRUIT-UART2-00A0.dtbo
-rw-r--r-- 1 root root   865 Apr 23  2014 /lib/firmware/ADAFRUIT-UART4-00A0.dtbo
-rw-r--r-- 1 root root   865 Apr 23  2014 /lib/firmware/ADAFRUIT-UART5-00A0.dtbo
-rw-r--r-- 1 root root  1056 Apr 23  2014 /lib/firmware/BB-ADC-00A0.dtbo
...

The output contains a list of available DT files. Each file contains a pin mux configuration for a particular use. Some of the files belong to BeagleBone Black capes and are dynamically loaded at boot time. Some of the DT files help you configure pin mux for a particular BeagleBone Black peripheral. For example, the file BB-UART1-00A0.dtbo configures pins 19, 20, 24 and 26 of the P9 header for UART1 peripheral.

2. Display the pin muxing configuration of the P9 header by executing the following on the MATLAB command line:

showPinMux(bbone, 'P9')

Do not close the figure window. This will be the base pin mux configuration we compare against.

3. To change the functionality of the P9_21 pin from GPIO_23 to EHRPWM0B, execute the following on the MATLAB command line:

system(bbone, 'echo bone_pwm_P9_21 | sudo tee /sys/devices/bone_capemgr.*/slots')

If you encounter an error while loading DT files, check kernel messages to figure out the source of the error. For example, execute the following to see the end of the kernel message log:

system(bbone, 'dmesg | tail')

The output contains a log of events leading to the loading of the DT file. Most errors are related to pin conflicts. That is two DT files trying to use the same pin. If you try to load the bone_pwm_P9_21 twice you will receive an error message the second time indicating that P9_21 has already been claimed.

4. Display the pin muxing configuration of the P9 header by executing the following command at the MATLAB prompt:

showPinMux(bbone, 'P9')

Compare the new figure against the one you generated in step 2 above. You should see that P9_21 is mapped to EHRPWM0B functionality.

5. Display the loaded DT files by executing the following at the MATLAB prompt:

system(bbone, 'cat /sys/devices/bone_capemgr.*/slots')

The output should be similar to the following:

ans =
0: 54:PF---
1: 55:PF---
2: 56:PF---
3: 57:PF---
4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
7: ff:P-O-L Override Board Name,00A0,Override Manuf,bone_pwm_P9_21

Note that the bone_pwm_P9_21 DT has been loaded at slot 7.

6. To unload the bone_pwm_P9_21 loaded at slot 7, execute the following on the MATLAB command line:

system(bbone, 'echo -7 | sudo tee /sys/devices/bone_capemgr.*/slots')

Viewing the DT slots after executing the command above should result in the following output:

system(bbone, 'cat /sys/devices/bone_capemgr.*/slots')
ans =
0: 54:PF---
1: 55:PF---
2: 56:PF---
3: 57:PF---
4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI

Task 3 - Digital I/O Pins

BeagleBone Black hardware has 65 general purpose digital I/O (GPIO) pins exposed on the P8 and P9 headers. Not all of these 65 pins have been configured as digital I/O. Some of these pins are used by the Linux kernel for other functionality. For example, most of the digital I/O capable pins on the P8 header are reserved for eMMC, HDMI and audio over HDMI functionality. A comprehensive list of digital I/O pins available on BeagleBone Black are shown in the following diagram.

Using any one of the digital I/O pins indicated with a light blue background in the diagram above results in loss of eMMC functionality. Your BeagleBone Black uses eMMC to boot by default therefore you should avoid re-configuring eMMC pins as digital I/O. Using any of the pins indicated with a yellow background in the diagram above results in losing HDMI video output and/or audio over HDMI. If your BeagleBone Black hardware is not connected to a monitor, you may use these pins as digital I/O provided that you disable the corresponding DT file loaded at boot time that reserves pins for HDMI functionality.

1. BeagleBone Black Linux kernel stores groups of pins reserved for eMMC, HDMI, etc. in a number of files under /sys/kernel/debug/pinctrl/44e10800.pinmux/ directory. To read the contents of the pingroups file that provides information on the groups of pins dedicated to a specific functionality, execute the following on the MATLAB command line:

system(bbone, 'sudo cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pingroups')
ans =
registered pin groups:
group: pinmux_userled_pins
pin 21 (44e10854)
pin 22 (44e10858)
pin 23 (44e1085c)
pin 24 (44e10860)
group: pinmux_rstctl_pins
pin 20 (44e10850)
...

The output shows pins dedicated to user LEDs at the very top. The information contained in the pingroups file refer to kernel pin numbers that are not necessarily correlated with the pin numbers on the P8 and P9 headers. Execute the following on the MATLAB command line to see a formatted output of the pins currently used by the kernel:

printPinGroups(bbone)

This function eliminates pins that are not mapped to the P8 or P9 headers and displays P8 and P9 pin numbers instead of kernel pin numbers.

2. When using GPIO Read or GPIO Write blocks, choose pin numbers that are dedicated to GPIO functionality. If you want to use GPIO pins currently dedicated to some other functionality you must first take care of the pin muxing configuration. The generated code does not attempt to dynamically change the pin muxing configuration at run-time. It is your responsibility to ensure that pin muxing configuration matches desired use case. Use showPinMux method of the beaglebone_black object to determine pins that can be used as GPIO and use these pin numbers in GPIO Read and GPIO Write blocks.

3. If you don't use HDMI output of your BeagleBone Black hardware, you may disable the corresponding DT file that reserves pins for HDMI output. To do this you edit a file called uEnv.txt stored in the boot partition of the BeagleBone Black hardware file system. The boot partition your BeagleBone Black hardware appears as a removable drive on your host computer. Locate the drive corresponding to your BeagleBone Black hardware and use an editor to add the following line to the uEnv.txt file:

optargs=capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN

After saving the uEnv.txt file, reboot:

system(bbone, 'shutdown -r now')

Wait about 30 seconds and reconnect to your BeagleBone Black hardware to check the pin mux configuration.

bbone = beaglebone_black
showPinMux(bbone, 'P8')

Task 4 - ADC Pins

BeagleBone Black hardware has 7 analog input pins on the P9 header. Analog input pins are indicated by dark green in the following diagram.

The analog input pins are labeled as AIN_0, AIN_1, AIN_2, AIN_3, AIN_4, AIN_5, AIN_6 in the diagram above. The VDD_ADC and GND_ADC pins are used as reference voltage levels for analog inputs with VDD_ADC at +1.8 Volts. Each analog input pin can handle a maximum of 1.8 volts. Do not apply voltages higher than 1.8 volts to analog input pins.

1. To enable analog input functionality, you use cape-bone-iio DT file. Execute the following on the MATLAB command line to enable analog input:

system(bbone, 'echo cape-bone-iio | sudo tee /sys/devices/bone_capemgr.*/slots')

2. To verify the pin mux configuration, display the P9 header pin muxing diagram:

showPinMux(bbone, 'P9')

You should see that pins P9_33 to P9_40 are configured as analog input pins.

3. In addition to configuring appropriate pin muxing, the cape-bone-iio DT file also enables the Linux ADC driver. The analog input values can be read directly from a file after loading the cape-bone-iio DT file. To read the analog voltage value at pin P9_39 (AIN0), execute the following on the MATLAB command line:

system(bbone, 'cat /sys/devices/ocp.*/helper.*/AIN0')

You should see an output similar to the following.

ans =
1723

This is the voltage value in milli-volts applied to the P9_39 pin. Try connecting P9_39 (AIN0) to P9_34 (GND_ADC) and then reading the analog voltage value again. This time, you should read a small value close to zero.

Task 5 - PWM Pins

BeagleBone Black hardware has 8 PWM outputs mapped to 14 pins on the P8 and P9 headers.

Some of the PWM outputs can be muxed to one of the two alternate pins. For example, EHRPWM0B, can be muxed to either P9_21 or P9_29 but not to both pins at the same time.

1. BeagleBone Black hardware comes with a set of DT files for configuring pin muxing for PWM output and loading Linux drivers. To see a list of DT files dealing with PWM outputs execute the following on the MATLAB command line:

system(bbone, 'ls -al /lib/firmware/*pwm*')

You should see an output similar to the following:

ans =
-rw-r--r-- 1 root root 1181 Apr 23 20:57 /lib/firmware/am33xx_pwm-00A0.dtbo
-rw-r--r-- 1 root root 1091 Apr 23 20:57 /lib/firmware/bone_pwm_P8_13-00A0.dtbo
-rw-r--r-- 1 root root 1091 Apr 23 20:57 /lib/firmware/bone_pwm_P8_19-00A0.dtbo
-rw-r--r-- 1 root root 1091 Apr 23 20:57 /lib/firmware/bone_pwm_P8_34-00A0.dtbo
-rw-r--r-- 1 root root 1091 Apr 23 20:57 /lib/firmware/bone_pwm_P8_36-00A0.dtbo
-rw-r--r-- 1 root root 1091 Apr 23 20:57 /lib/firmware/bone_pwm_P8_45-00A0.dtbo
-rw-r--r-- 1 root root 1091 Apr 23 20:57 /lib/firmware/bone_pwm_P8_46-00A0.dtbo
-rw-r--r-- 1 root root 1091 Apr 23 20:57 /lib/firmware/bone_pwm_P9_14-00A0.dtbo
-rw-r--r-- 1 root root 1091 Apr 23 20:57 /lib/firmware/bone_pwm_P9_16-00A0.dtbo
-rw-r--r-- 1 root root 1091 Apr 23 20:57 /lib/firmware/bone_pwm_P9_21-00A0.dtbo
-rw-r--r-- 1 root root 1091 Apr 23 20:57 /lib/firmware/bone_pwm_P9_22-00A0.dtbo
-rw-r--r-- 1 root root 1097 Apr 23 20:57 /lib/firmware/bone_pwm_P9_28-00A0.dtbo
-rw-r--r-- 1 root root 1091 Apr 23 20:57 /lib/firmware/bone_pwm_P9_29-00A0.dtbo
-rw-r--r-- 1 root root 1091 Apr 23 20:57 /lib/firmware/bone_pwm_P9_31-00A0.dtbo
-rw-r--r-- 1 root root 1097 Apr 23 20:57 /lib/firmware/bone_pwm_P9_42-00A0.dtbo

2. In order to use the PWM outputs you first need to load am33xx_pwm DT by executing the following on the MATLAB command line.

system(bbone, 'echo am33xx_pwm | sudo tee /sys/devices/bone_capemgr.*/slots')

This DT file enables PWM output and loads Linux PWM driver.

3. To configure a particular pin for PWM output you need to load the DT file for that pin. For example, to configure P9_21 for PWM output execute the following on the MATLAB command line.

system(bbone, 'echo bone_pwm_P9_21 | sudo tee /sys/devices/bone_capemgr.*/slots')

4. To verify that P9_21 is configured for PWM output view the pin muxing diagram for P9 header:

showPinMux(bbone, 'P9')

You should observe that P9_21 has become EHRPWM0B.

5. If you try to configure P9_29 as PWM at the same time as P9_21, you receive an error.

system(bbone, 'echo bone_pwm_P9_29 | sudo tee /sys/devices/bone_capemgr.*/slots')
Error executing command: bone_pwm_P9_29
tee: /sys/devices/bone_capemgr.9/slots: File exists

This is because P9_21 pins is already muxed for EHRPWM0B signal from the processor. You cannot map the same EHRPWM0B signal to two different pins at the same time.

Task 6 - Build an LED Dimmer Application

In this task, we put together the concepts we learned to create an LED dimmer application. We use a PWM output to control the brightness of an LED according to the value read from an ADC input connected to a potentiometer.

1. Connect a 10 k $\Omega$ potentiometer, and LED and a resistor to the BeagleBone Black hardware as seen in the following circuit diagram. To simulate a variable voltage applied to AIN0, we use a 10 k $\Omega$ potentiometer.

The potentiometer (POT), in this example, is a three-terminal device with terminals 1 and 3 comprising the end points of a resistor embedded in the POT. The second terminal is connected to a variable wiper. As the wiper moves, the resistance values across terminals 1 and 2 and terminals 2 and 3 change. In this circuit, POT acts as a variable voltage divider. As you move the knob of the potentiometer, the voltage seen at terminal 2 changes between VDD_ADC (~1.8 V) and GND_ADC.

2. Execute the following commands on the MATLAB command line to setup required pin muxing configuration if you have not done so already:

system(bbone, 'echo cape-bone-iio | sudo tee /sys/devices/bone_capemgr.*/slots')
system(bbone, 'echo am33xx_pwm | sudo tee /sys/devices/bone_capemgr.*/slots')
system(bbone, 'echo bone_pwm_P9_21 | sudo tee /sys/devices/bone_capemgr.*/slots')

Note that if you loaded one of the DT files above in preceding steps, you may get an error. This is normal. Make sure all required DT files are loaded at this step. After loading the DT files, display the pin muxing diagram to verify that P9_39 and P9_21 are muxed to ADC and PWM peripherals:

showPinMux(bbone, 'P9')

3. Open the beaglebone_led_dimmer Simulink model.

This model uses P9_39 pin as analog input and P9_21 pin as PWM output. The pin numbers used for PWM, ADC are displayed on the corresponding Simulink blocks. The model is configured to run in External Mode. Click on the Play button to generate code for the model, download it to the BeagleBone Black hardware and run it.

4. Once the model starts running, double click on the ADC output and Duty cycle blocks to view the output of the Analog Input block and the input to the PWM block. Try playing with the POT knob while executing the loop above. You should observe that the voltage value displayed on the ADC output scope changes. You should also observe that the brightness of the LED changes in response to a change the POT knob position.

5. Click Stop button to stop the model.

Other Things to Try

Change the model to use a different pin for PWM, for example P9_14.