Start a C program when BeagleBone boots
Posted: April 11, 2012 | Author: Nuno Alves | Filed under: Embedded Systems, Programming Languages | Tags: Beagle Bone, C/C++ | 12 Comments »I’ve been spending some time lately trying to turn the BeagleBone into a “single-serving” system for my prototypes. Most of these prototypes require running some program whenever the system gets power. Before you continue, I strongly recommend you read my previous BeagleBone posts, if you start feeling a bit lost.
So here I have a very simple circuit… 5 LEDs connected to 5 different pins (P8_3,P8_4,P8_5,P8_11,P8_12). I would like these LEDs to display a perform a simple pattern whenever the BeagleBone is turned ON. Something like the following video.
The code for this circuit is pretty straight forward and looks like this:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#include "BeagleBone_gpio.h" #include <signal.h> #define TRUE 1 #define FALSE 0 int forever = TRUE; void sighandler(int sig) { printf("CONTROL+C was caught... terminating in a friendly manner\n"); forever = FALSE; } int main() { int i=0; int pinID[]={P8_3,P8_4,P8_5,P8_11,P8_12}; int nbr_selectedPins=sizeof(pinID)/sizeof(*pinID); struct gpioID selectedPins[nbr_selectedPins]; pinMode_multiple(selectedPins,pinID,nbr_selectedPins,"out"); unsigned int data_to_write; signal(SIGABRT, &sighandler); signal(SIGTERM, &sighandler); signal(SIGINT, &sighandler); data_to_write=1; while(forever==TRUE) { for (i=0;i<4;i++) { digitalWrite_multiple(selectedPins,nbr_selectedPins,data_to_write); data_to_write=data_to_write<<1; delayms(500); } for (i=4;i>0;i--) { digitalWrite_multiple(selectedPins,nbr_selectedPins,data_to_write); data_to_write=data_to_write>>1; delayms(500); } } cleanup_multiple(selectedPins,nbr_selectedPins); return 1; } |
To compile and run this code, download my BeagleBone_IO library, save the above code as main.c and type the following commands:
gcc BeagleBone_gpio.o main.c -o main
./main
What is neat about my code, is that it is able to trap a signal whenever the user types CONTROL+C and ends the program normally… after performing some generic BeagleBone GPIO cleanup.
Anyway, I would like this program to run whenever my BeagleBone starts up. BeagleBone’s default OS is Angstrom Linux which uses systemd as the initialization scheduler. I am still learning about this, but according to the wikipedia entry and also to Kezhong’s Weblog, this daemon is meant to efficiently express services dependencies, by allowing more services to be launched in parallel at system startup while reducing the need to mess around with many scripts. I used to do this on ubuntu… and it was a mess.
Anyway, I would like to declare my LED blinking program as a service. So I need to execute the following steps:
Step #1: Create a script that will call the program that you wish you launch at boot time
This means we need to create a file in the /usr/bin/ directory with any name. For example, assuming that our compiled LED program is in /home/root/main we can create an executable simple script called myScript.sh with the following lines of code.
echo “/home/root/main” >> /usr/bin/myScript.sh
chmod u+x /usr/bin/myScript.sh
Step #2: Create the service file
Create the file /lib/systemd/myScript.service . Actually your service name can be anything you want… not restrained to myScript.service.
Step #3: Write the appropriate service settings
Your /lib/systemd/myScript.service can be for example:
Description=Run the LED pattern script
After=syslog.target network.target
[Service]
Type=simple
ExecStart=/usr/bin/myScript.sh
[Install]
WantedBy=multi-user.target
Step #4: Make a symbolic link
ln /lib/systemd/myScript.service myScript.service
Step #5: Make systemd take notice of it, activate the service immediately and enable the service to be started on boot-up
systemctl start myScript.service
systemctl enable myScript.service
After executing all commands on step 5, the LED program should immediately start. Try switching the BeagleBone power OFF & ON… and you will see the LED program.
How to terminate the script that is constantly running in the background?
If everything went okay, your script in constantly running in the background. To terminate it, you need to kill it. Use the top command and find out the process id (pid) of your looping program. As shown on the screenshot, my main pid is 13.
The following command will take care of terminating the job.
How disable the script from starting up at the boot time?
Just type:
Thanks to Piranha at the official BeagleBoard forum for guidance.
Cracking PDF-file passwords using a BeagleBone board
Posted: March 26, 2012 | Author: Nuno Alves | Filed under: Embedded Systems | Tags: Beagle Bone | 9 Comments »I am strong proponent of customized embedded systems; a single piece of hardware aimed at solving a single problem. If we have a particular task that is time intensive, repetitive, difficult to configure and somewhat “shady”, it is probably best to execute it in hardware. Lets consider a tool for recovering passwords from PDF-files. There are several downloadable software programs out there that allow you to recover a lost password from an encrypted PDF-file. Is this the best approach? Hardly.
In general I am very wary of installing software in my computer that I do not have access to its source code. Who knows what is happening behind the scenes. Sure, the program may be trying to find the password for my PDF-file, but at the same time it may be sending the same PDF-file to some “shady” folks together with all my computer passwords, credit card numbers and so on. Not good. Even if the password cracking program comes from a “reputable” software house, installing software always leave floating traces behind, which inevitably bloat our hard disks and slow things down.
My idea was simple: pick up a programmable embedded system with USB support and use that as my password cracking platform. This embedded system is to be completely isolated (not connected to any computer or network) and powered up from a 5V adapter. The user just has to attach a usb disk with the encrypted file, press a button and let the platform crack away.
I chose the TI’s BeagleBone; a powerful linux ready 700MHz embedded system retailing for about $85. For more information I recommend checking out the “Getting Started Guide” by Matt Richardson @ Make magazine, in addition to the official BeagleBone webpage.
Here is a video of my PDF-file password cracker in action.
For all intents and purposes, the BeagleBone is just a very portable linux computer. This means I could write all the brute-force and all I/O routines directly in C and BASH. It worked great.
In terms of performance, the BeagleBone is able to test about 7,000 words per second, whereas my macbook pro can to about 25,000. Since, I am just using a brute approach… It takes about 16 minutes to test every single 4 letter word (uppercase+lowercase+symbols), and 900 minutes to test every single 5 letter word. Obviously there is plenty of room for improvement here, such as a dictionary based option and even customized multi-core architectures with many BeagleBone CPUs. This last option is the most interesting one. While the BeagleBone prototype system costs around $85, the CPU itself costs around $5. With some clever engineering, we could potentially have a dedicated 10 core system for less than $300.
Regarding the technical details of this project look here for the LCD component and here for the digital I/O button implementation.
Controlling a HD44780 LCD on a BeagleBone (Part 2)
Posted: March 24, 2012 | Author: Nuno Alves | Filed under: Embedded Systems, Programming Languages | Tags: Beagle Bone, C/C++ | Leave a comment »On the previous post I described how a HD44780 can be integrated with a BeagleBone. For this post, I created a small HD44780 library for the BeagleBone that makes the process of writing text to a LCD as easy as it was on the Arduino.
First of all you need some files. Go to the github for this project (https://github.com/nunoalves/BeagleBone-HD44780) and place the following files into your BeagleBone:
These files provide all the necessary LCD I/O. In this post we will be discussing the example_03.c and example_04.c files that are also available on that same repository.
Once the files are on your BeagleBone, make all the appropriate connections, exactly as described on the previous post.
Instead of describing every single function in detail, its probably easier if you look at the following code (example_03.c), which performs some very basic LCD operations.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <assert.h> #include <time.h> #include "beagle_gpio.h" #include "beagle_hd44780.h" int main() { //specifies the pins that will be used int selectedPins[]={P8_14,P8_12,P8_11,P8_5,P8_4,P8_3}; const char *pinDescription[] = {"DB7","DB6","DB5","DB4","RS","E"}; struct gpioID enabled_gpio[6]; //initialized the screen initialize_Screen(enabled_gpio,selectedPins); //clear the screen from everything that may be in there clear_Screen(enabled_gpio); printf("... just cleared screen and now waiting for 5 secs.\n"); sleep(5); //writes two characters charToScreen('a',enabled_gpio); charToScreen('b',enabled_gpio); printf("... typed ab and now waiting for 5 secs.\n"); sleep(5); clear_Screen(enabled_gpio); //enables the blinking cursor enableBlinkingCursor(enabled_gpio); charToScreen('c',enabled_gpio); charToScreen('d',enabled_gpio); charToScreen('e',enabled_gpio); charToScreen('g',enabled_gpio); printf("... cleared screen, enabled blinking and wrote more stuff.\n"); sleep(5); //this instruction must be added or the LCD may not work as expected next //time... unless you reboot it. terminate_Screen(enabled_gpio,selectedPins); } |
You can compile, and run, this code with the following commands:
gcc -c beagle_hd44780.c
gcc beagle_gpio.o beagle_hd44780.o example_03.c
./a.out
This next sample code (example_04.c) shows how to write full strings and how to address a particular LCD position.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <assert.h> #include <time.h> #include "beagle_gpio.h" #include "beagle_hd44780.h" int main() { //specifies the pins that will be used int selectedPins[]={P8_14,P8_12,P8_11,P8_5,P8_4,P8_3}; //adding a simple description for each pin const char *pinDescription[] = {"DB7","DB6","DB5","DB4","RS","E"}; struct gpioID enabled_gpio[6]; initialize_Screen(enabled_gpio,selectedPins); //clear screen clear_Screen(enabled_gpio); //types "hi!" to the screen stringToScreen("hi!",enabled_gpio); //go to the bottom line and write something else //note: goto_ScreenLine(0,enabled_gpio) will go to the top line. goto_ScreenLine(1,enabled_gpio); stringToScreen("there!",enabled_gpio); //really... don't forget to terminate the screen terminate_Screen(enabled_gpio,selectedPins); } |
You can compile, and run, this code with the following commands:
gcc -c beagle_hd44780.c
gcc beagle_gpio.o beagle_hd44780.o example_04.c
./a.out
Have fun!
Controlling a HD44780 LCD on a BeagleBone (Part 1)
Posted: March 22, 2012 | Author: Nuno Alves | Filed under: Embedded Systems, Programming Languages | Tags: Beagle Bone, C/C++, Doxygen | 8 Comments »Hitachi HD44780 compatible LCD screens are those common displays we see all over the place. Getting them to display some information is fairly easy, as all you have to do is send the appropriate bits to each of the LCD screen inputs.
In this post I will describe the steps I took to integrate a Hitachi HD44780 LCD with the BeagleBone board. First of all you need a LCD display. From my Arduino days, I had a couple of them laying around my lab. In this tutorial, I used a fairly inexpensive Microtivity LCD Module 1602. Because this LCD module requires a 5V source, and the BeagleBone GPIO pins only provide 3.3V, you need to get power from other sources: either connect a 5V DC adaptor to the BeagleBone and use P9_5 which provides +5V, or use any adapter that you have in your house to deliver the appropriate voltage with a voltage regulator. If you opt for the voltage regulator route, I recommend you get a 9V adaptor and use this neat sparkfun kit, just make sure the ground of this external voltage supply is connected to the ground pin of the BeagleBone. Of course you can bypass all these problems, by getting a +3.3V LCD display, but they will be more expensive.
Once you have acquired the LCD and connected to an appropriate power source, use the following connections.
| LCD Pin # | LCD Pin Description | LCD Pin Connects to |
| 1 | VSS | Ground |
| 2 | VDD | +5V |
| 3 | VO | Attach a potentiometer here to adjust contrast |
| 4 | Register Select (RS) | BeagleBone pin P8_4 |
| 5 | Read/Write (R/W) | Ground |
| 6 | Clock Enable (E) | BeagleBone pin P8_3 |
| 7 | Data Bit 0 | Unconnected |
| 8 | Data Bit 1 | Unconnected |
| 9 | Data Bit 2 | Unconnected |
| 10 | Data Bit 3 | Unconnected |
| 11 | Data Bit 4 | BeagleBone pin P8_5 |
| 12 | Data Bit 5 | BeagleBone pin P8_11 |
| 13 | Data Bit 6 | BeagleBone pin P8_12 |
| 14 | Data Bit 7 | BeagleBone pin P8_14 |
| 15 | Backlight Anode (+) | +5V (or lower) |
| 16 | Backlight Cathode (-) | Ground |
Source-Code
The code below will prompt you to enter a bitstream into the LCD screen. Keep in mind that you need the library beagle_gpio.h, or else the program will not compile. You can find all the necessary files to run the program in the following github site (https://github.com/nunoalves/BeagleBone-HD44780). You can compile, and run, this code by typing the following commands in the BeagleBone terminal:
gcc beagle_gpio.o example_01.c
./a.out
rm -f a.out
Once the code is compiled you will be asked to type the appropriate bitstream. If you type the following bits, you will type the word “hi” on the LCD.
If you would like to manually type different characters look at the following table:
… And here is a screen shot of the program output.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <assert.h> #include <time.h> #include "beagle_gpio.h" #define DISPLAY_DATA_ON_SCREEN 1 /** * @brief This program (example_01.c) shows how to write data into a * HD44780 LCD display using the manual process of setting up every * single pin with a binary value. For a complete description of these * (and more) HD44780 commands, read the article by Julyan llett, * "How to use intelligent L.C.D.s - Part One". * * @section Setup * Set-up the HD44780 screen as follows: * Pin 1 - VSS - Connect to ground * Pin 2 - VCC - Connect to +5V (or lower voltage depending on your LCD) * Pin 3 - VO - Attach a potentiometer here to adjust contrast * Pin 4 - Register Select (RS) - Connect to P8_4 * Pin 5 - Read/Write (R/W) - Connect to ground * Pin 6 - Clock (Enable) - Connect to P8_3 * Pin 7 - Data Bit 0 - Do not connect anything to it * Pin 8 - Data Bit 1 - Do not connect anything to it * Pin 9 - Data Bit 2 - Do not connect anything to it * Pin 10 - Data Bit 3 - Do not connect anything to it * Pin 11 - Data Bit 4 - Connect to P8_5 * Pin 12 - Data Bit 5 - Connect to P8_11 * Pin 13 - Data Bit 6 - Connect to P8_12 * Pin 14 - Data Bit 7 - Connect to P8_14 * Pin 15 - Backlight Anode (+) - Connect to +5V (or lower) * Pin 16 - Backlight Cathode (-) - Connect to ground * * @section Compilation * Compile, and run, this code on the beagleBone terminal with the command: * * gcc -c beagle_gpio.c ; gcc beagle_gpio.o example_01.c ; ./a.out ; rm -f a.out ; * * @return Returns a 1 upon succesful program termination **/ int main() { //Specifies which pins we are going to use int selectedPins[]={P8_14,P8_12,P8_11,P8_5,P8_4,P8_3}; //A little description for each of the selectedPins[]. //This makes debugging a LOT easier... const char *pinDescription[] = {"DB7","DB6","DB5","DB4","RS","E"}; int nbr_selectedPins=sizeof(selectedPins)/sizeof(*selectedPins); unsigned int data_to_write=0; //these two lines initalize all the selected pins struct gpioID enabled_gpio[nbr_selectedPins]; initialize_each_enabled_gpio(enabled_gpio,selectedPins,nbr_selectedPins); //display some information on the beglebone screen if (DISPLAY_DATA_ON_SCREEN) display_each_enabled_gpio(enabled_gpio,nbr_selectedPins,pinDescription); //======================================================================== //START: Manually feeding commands into the HD44780 LCD //======================================================================== //For example: the following command will type the letter 'hi' in the //LCD //RS ; DB7 ; DB6 ; DB5 ; DB4 ; Stop sending commands? //0 ; 0 ; 0 ; 1 ; 1 ; No - (this command initializes the screen) //0 ; 0 ; 0 ; 1 ; 0 ; No - (this command send LCD to 4 bit mode) //0 ; 0 ; 0 ; 0 ; 0 ; No - (enable display with cursor part 1) //0 ; 1 ; 1 ; 1 ; 1 ; No - (enable display with cursor part 2) //1 ; 0 ; 1 ; 1 ; 0 ; No - (first part of character 'h') //1 ; 1 ; 0 ; 0 ; 0 ; No - (second part of character 'h') //1 ; 0 ; 1 ; 1 ; 0 ; No - (first part of character 'i') //1 ; 1 ; 0 ; 0 ; 1 ; No - (second part of character 'i') //0 ; 0 ; 0 ; 1 ; 1 ; Yes - (go back into 8 bit mode) int pinSelect, terminate_operation, i, pinData; terminate_operation=0; while (terminate_operation==0) { data_to_write=0; printf("Write value for pin %s:\n",pinDescription[4]); scanf("%d",&pinData); data_to_write=bitWrite(data_to_write,pinData,i); turn_ON_OFF_pins(enabled_gpio,data_to_write,nbr_selectedPins,1,pinDescription); for (i=0; i<4; i++) { printf("Write value for pin %s:\n",pinDescription[i]); scanf("%d",&pinData); data_to_write=bitWrite(data_to_write,pinData,i); turn_ON_OFF_pins(enabled_gpio,data_to_write,nbr_selectedPins,1,pinDescription); } pulsePin(enabled_gpio,data_to_write,nbr_selectedPins,DISPLAY_DATA_ON_SCREEN, pinDescription, 5, 1); printf("Stop sending commands? (1=yes):\n"); scanf("%d",&terminate_operation); } //======================================================================== //END: Manually feeding commands into the HD44780 LCD //======================================================================== //we should now tell the OS that we are done with the GPIOs cleanup_GPIO(enabled_gpio,selectedPins,nbr_selectedPins); } |
Finally, if you would like to know more about controlling these LCD devices I suggest this website, and the article “How to use intelligent L.C.D.s – Part One” by Julyan llett, which can be found here.
In a future post, I will release another library that will allow us to automatically display text without manually typing the entire bitstream.
Addressing multiple BeagleBone GPIO pins in C
Posted: March 17, 2012 | Author: Nuno Alves | Filed under: Embedded Systems, Programming Languages | Tags: Beagle Bone, C/C++, Doxygen | 2 Comments »Since I am in the process of writing a HD44780 compatible LCD display driver for the beagle bone, I need to have a very simple piece of C code that writes data to multiple GPIO pins at the same time. In particular I need to have a function that when given a binary value, will turn ON/OFF may GPIO pins. For example, lets say the end-user is using the following 5 GPIO pins, P8_3, P8_4, P8_5, P8_11 and P8_12. Now lets say he just wants to turn ON pins P8_4 and P8_11, while leaving the others OFF. I created a neat piece of code that takes the pin selection in a binary format, and performs the appropriate ON/OFF switching operations. The latest version of this code can be found at the following github repository, https://github.com/nunoalves/BeagleBone-GPIO-in-C.
While this code works quite well, it is not really complete. For starters, I haven’t included all BeagleBone GPIO pins. You can include them all yourself in the function initialize_each_enabled_gpio(). Please refer to this earlier blog post for hints about how to do it. I also haven’t split this code into a different header file, so it’s its own library. I will do so, after I release the drivers for the HD44780 LCD display. Finally, this code could need some cleaning and optimization…
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 |
/** * @file main.c * * @brief Addressing multiple BeagleBone GPIO pins in C * @details Self-contined program that will turn ON/OFF a specified group of * of GPIO pins in the beaglebone board. This code was possible due to prior * efforts by Christian Mitchell, Markus Klink and Matt Richardson. To compile * and run this code, type something like "gcc main.c ; ./a.out ; rm -f a.out" * * @author Nuno Alves * @date 17/March/2012 **/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <assert.h> #include <time.h> //If DEBUG is defined to TRUE (1), intermediate debug messages will be displayed //when code is executing. You may set it to FALSE (0) for no debug information. #define DEBUG 1 //The following #defines make it easier for the user to add differnt pins #define P8_3 0 #define P8_4 1 #define P8_5 2 #define P8_11 3 #define P8_12 4 /** @brief Contains all elements which we need to pass into the beagleboard * to specify which GPIO pin we want to turn ON/OFF **/ struct gpioID { char *PINNAME; //eg. P8_3 char * GPIOID; //e.g: gpio1[6] int GPIONUMBER; //e.g: 38 char *GPIOMUX; //e.g: gpmc_ad6; }; /** * @brief Writes a value to a particular GPIO, logic-HIGH or logic-LOW. * @param GPIONUMBER The GPIO number (e.g. 38 for gpio1[6]) * @param value The logic value we want to write to the GPIO (0 or 1) **/ void write_GPIO_value(int GPIONUMBER, int value) { char export_filename[50]; FILE *f = NULL; sprintf(export_filename, "/sys/class/gpio/gpio%d/value",GPIONUMBER); f = fopen(export_filename,"w"); assert(f!=NULL); fprintf(f , "%d",value); pclose(f); } /** * @brief Tells the OS that we are done with using GPIOs * @param selected_GPIOs[] initialized array of gpioID. * @param selectedPins[] Array with the user specified pins * @param sizeof_selectedPins Number of pins that were specified by the user **/ void cleanup_GPIO(struct gpioID selected_GPIOs[],int selectedPins[], int nbr_selectedPins) { char export_filename[50]; FILE *f = NULL; int i; for (i=0; i<nbr_selectedPins;i++) { //unexport the pin f = fopen("/sys/class/gpio/unexport","w"); assert(f!=NULL); fprintf(f, "%d",selected_GPIOs[i].GPIONUMBER); pclose(f); } } /** * @brief Initializes all the user specified pins * @param selected_GPIOs[] Un-initialized array of gpioID. At the end of this * function, the selected_GPIOs[] array will be initialized. * @param selectedPins[] Array with the user specified pins * @param sizeof_selectedPins Number of pins that were specified by the user **/ void initialize_each_enabled_gpio(struct gpioID selected_GPIOs[],int selectedPins[], int nbr_selectedPins) { int i; //this variable will contain the location of the file that we need to //set to mode 7 char export_filename[50]; FILE *f = NULL; //You are not allowed to use more than 32 active pins. This is not a //beagleboard limitation, but a limitation of this code. assert (nbr_selectedPins<=32); //cycles every userdefined pin, and inializes its contents in the //selected_GPIOs[] array. for (i=0; i<nbr_selectedPins;i++) { switch (selectedPins[i]) { case P8_3: selected_GPIOs[i].PINNAME="P8_3"; selected_GPIOs[i].GPIOID="gpio1[6]"; selected_GPIOs[i].GPIONUMBER=38; selected_GPIOs[i].GPIOMUX="gpmc_ad6"; break; case P8_4: selected_GPIOs[i].PINNAME="P8_4"; selected_GPIOs[i].GPIOID="gpio1[7]"; selected_GPIOs[i].GPIONUMBER=39; selected_GPIOs[i].GPIOMUX="gpmc_ad7"; break; case P8_5: selected_GPIOs[i].PINNAME="P8_5"; selected_GPIOs[i].GPIOID="gpio1[2]"; selected_GPIOs[i].GPIONUMBER=34; selected_GPIOs[i].GPIOMUX="gpmc_ad2"; break; case P8_11: selected_GPIOs[i].PINNAME="P8_11"; selected_GPIOs[i].GPIOID="gpio1[13]"; selected_GPIOs[i].GPIONUMBER=45; selected_GPIOs[i].GPIOMUX="gpmc_ad13"; break; case P8_12: selected_GPIOs[i].PINNAME="P8_12"; selected_GPIOs[i].GPIOID="gpio1[12]"; selected_GPIOs[i].GPIONUMBER=44; selected_GPIOs[i].GPIOMUX="gpmc_ad12"; break; default: //This statement should never be reached... since //the program won't even compile if the user //specified a bad pin specification. break; } } //set the each mux pin to mode 7 for (i=0; i<nbr_selectedPins;i++) { //set mux to mode 7 sprintf(export_filename, "/sys/kernel/debug/omap_mux/%s", selected_GPIOs[i].GPIOMUX); f = fopen(export_filename,"w"); if (f == NULL) { printf( "\nERROR: There was a problem opening /sys/kernel/debug/omap_mux/%s\n", selected_GPIOs[i].GPIOMUX); printf("\n%s\t%s\t%s\t%d\n\n", selected_GPIOs[i].PINNAME, selected_GPIOs[i].GPIOID, selected_GPIOs[i].GPIOMUX, selected_GPIOs[i].GPIONUMBER); assert(f!=NULL); } fprintf(f, "7"); pclose(f); //export the pin f = fopen("/sys/class/gpio/export","w"); if (f == NULL) { printf( "\nERROR: There was a problem opening /sys/kernel/debug/omap_mux/%s\n", selected_GPIOs[i].GPIOMUX); printf("\n%s\t%s\t%s\t%d\n\n", selected_GPIOs[i].PINNAME,selected_GPIOs[i].GPIOID,selected_GPIOs[i].GPIOMUX,selected_GPIOs[i].GPIONUMBER); assert(f!=NULL); } fprintf(f, "%d",selected_GPIOs[i].GPIONUMBER); pclose(f); //set the appropriate io direction (out) sprintf(export_filename, "/sys/class/gpio/gpio%d/direction", selected_GPIOs[i].GPIONUMBER); f = fopen(export_filename,"w"); if (f == NULL) { printf( "\nERROR: There was a problem opening /sys/class/gpio/gpio%d/direction\n", selected_GPIOs[i].GPIONUMBER); printf("\n%s\t%s\t%s\t%d\n\n",selected_GPIOs[i].PINNAME,selected_GPIOs[i].GPIOID,selected_GPIOs[i].GPIOMUX,selected_GPIOs[i].GPIONUMBER); assert(f!=NULL); } fprintf(f , "out" ); pclose(f); write_GPIO_value(selected_GPIOs[i].GPIONUMBER,0); } } /** * @brief Displays all information for each of the user specified pins. * This function has no purpose besides live debugging. * @param selected_GPIOs[] An valid (initialized) array of gpioID * @param nbr_selectedPins Number of pins that were specified by the user **/ void display_each_enabled_gpio(struct gpioID selected_GPIOs[],int nbr_selectedPins) { int i; printf("\n"); printf("PINNAME\tGPIOID\t\tGPIOMUX\t\tGPIONBR\n"); printf("++++++++++++++++++++++++++++++++++++++++++++++++\n"); for (i=0; i< nbr_selectedPins; i++) { printf("%s\t%s\t%s\t%d\n",selected_GPIOs[i].PINNAME,selected_GPIOs[i].GPIOID,selected_GPIOs[i].GPIOMUX,selected_GPIOs[i].GPIONUMBER); } printf("\n"); } /** * @brief Cycles through the entire array of selected_GPIOs[] and turns ON/OFF * each associated GPIO. * @param selected_GPIOs[] An valid (initialized) array of gpioID * @param data_to_write An unsigned integer (32 bits), where each bit contains the * information regarding the status of each pin: 1=turn pin ON, 0=turn pin OFF * @param nbr_selectedPins Number of pins that were specified by the user **/ void turn_ON_OFF_pins(struct gpioID selected_GPIOs[],unsigned int data_to_write,int nbr_selectedPins) { int i; for (i=0;i<nbr_selectedPins;i++) { //code that turns ON/OFF a pin write_GPIO_value(selected_GPIOs[i].GPIONUMBER,bitRead(data_to_write,i)); //this is just for debugging purposes if (DEBUG) { if (bitRead(data_to_write,i) == 1) printf("turning ON"); else printf("turning OFF"); printf( "\t%s (%s %d %s)\n",selected_GPIOs[i].PINNAME,selected_GPIOs[i].GPIOID,selected_GPIOs[i].GPIONUMBER,selected_GPIOs[i].GPIOMUX); } } if (DEBUG) printf("\n"); } /** * @brief Writes a bit into a particular location in an unsigned int variable (32 bits) * @param groupOfBits Some data resides in these 32 bits * @param bitVal The bitVal is wither a 1 or a 0 * @param bitLoc Where in the groupOfBits, the value of bitVal will be written. * Keep in mind that the bitLoc values ranges 0 to 31 * @return Returns the updated groupOfBits **/ unsigned int bitWrite(unsigned int groupOfBits, int bitVal, int bitLoc) { if (bitVal==1) groupOfBits |= 1 << bitLoc; else groupOfBits &= ~(1 << bitLoc); return(groupOfBits); } /** * @brief Returns the bit value of a particular location in an unsigned int variable (32 bits) * @param groupOfBits Some data resides in these 32 bits * @param bitLoc Where in the groupOfBits, the value of bitVal will be written * @return Retuns an integer with the bit value (1 or 0) that resides in bitLoc **/ int bitRead(unsigned int groupOfBits, int bitLoc) { unsigned int bit = groupOfBits & (1 << bitLoc); if (bit!=0) bit=1; return(bit); } /** * @brief This is the main function with a sample test program. * @return Returns a 1 upon succesful program termination **/ int main() { int selectedPins[]={P8_3,P8_4,P8_5,P8_11,P8_12}; int nbr_selectedPins=sizeof(selectedPins)/sizeof(*selectedPins); //This variable data_to_write will contain the information which specified //the pins that will be ON or OFF unsigned int data_to_write=0; //Define an array of gpios which will contain all the user selected pins and //its associated information struct gpioID enabled_gpio[nbr_selectedPins]; //Initializes all user defined pins initialize_each_enabled_gpio(enabled_gpio,selectedPins,nbr_selectedPins); if (DEBUG) display_each_enabled_gpio(enabled_gpio,nbr_selectedPins); //At this point in the code there are 5 selected pins: //P8_3, P8_4, P8_5, P8_11, P8_12 //All these pins are intially OFF. //If I just want to turn ON pins P8_4 and P8_11, I need to look at my //selectedPins[] array: Since positions start at 0, pin P8_4 is on position 1 //and P8_11 is on position 3. Therefore I need to set the bits 1 and 3 on //the variable data_to_write. In base 2, setting bit1 and 3 looks like: //00000000 00000000 00000000 00001010 (base 2) //Which is equivalent to the value 10, in base 10. data_to_write=10; turn_ON_OFF_pins(enabled_gpio,data_to_write,nbr_selectedPins); sleep(1); //sleep for 1 second //In addition to the pins that are already ON (P8_4, P8_11), I now //also want to turn ON pin P8_12. Since P8_12 is on position 4, I //need to write a 1 to position 4. data_to_write=bitWrite(data_to_write,1,4); turn_ON_OFF_pins(enabled_gpio,data_to_write,nbr_selectedPins); //Of course, I could have done something like //data_to_write=26; //turn_ON_OFF_pins(enabled_gpio,data_to_write,nbr_selectedPins); //Which would have yielded the exact same outcome. sleep(1); //sleep for 1 second //Now I would like to turn OFF pin P8_11, while leaving pins P8_4 & P8_12 ON //Since pin P8_11 is on position 3 data_to_write=bitWrite(data_to_write,0,3); turn_ON_OFF_pins(enabled_gpio,data_to_write,nbr_selectedPins); sleep(1); //sleep for 1 second //we should now tell the OS that we are done with the GPIOs cleanup_GPIO(enabled_gpio,selectedPins,nbr_selectedPins); } |
Here is a screenshot of the program running in the BeagleBone.

To compile and run this code just type the following commands in the BeagleBone terminal.
./a.out
Finally, for those of you that are Doxygen fans, here is a printout of the code documentation.
BeagleBone tutorial: Blinking LEDs using bash
Posted: March 16, 2012 | Author: Nuno Alves | Filed under: Embedded Systems, Programming Languages | Tags: Bash, Beagle Bone | Leave a comment »While what I am demonstrating this post has already been accomplished by others (e.g. Matt Richardson, Akademii, Dan Watts and Brian Jepson), I found it useful for me to go through the motions of writing my own version of the “Blinking LED” project in a BeagleBone board. The following script switches between high and low signals, on several pins, and uses that information to drive some connected LEDs.
Without further ado, here is the code.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
#!/bin/bash function blinkPIN { PIN=${1} GPIONUMBER=0; GPIOMUX=0; GPIOID=0; echo "... blinking ${PIN}" if [ "${PIN}" == "P8_3" ]; then GPIOID=gpio1[6]; GPIONUMBER=38; GPIOMUX=gpmc_ad6; fi if [ "${PIN}" == "P8_4" ]; then GPIOID=gpio1[7]; GPIONUMBER=39; GPIOMUX=gpmc_ad7; fi if [ "${PIN}" == "P8_5" ]; then GPIOID=gpio1[2]; GPIONUMBER=34; GPIOMUX=gpmc_ad2; fi if [ "${PIN}" == "P8_6" ]; then GPIOID=gpio1[3]; GPIONUMBER=35; GPIOMUX=gpmc_ad3; fi if [ "${PIN}" == "P8_11" ]; then GPIOID=gpio1[13]; GPIONUMBER=45; GPIOMUX=gpmc_ad13; fi if [ "${PIN}" == "P8_12" ]; then GPIOID=gpio1[12]; GPIONUMBER=44; GPIOMUX=gpmc_ad12; fi if [ "${PIN}" == "P8_14" ]; then GPIOID=gpio0[26]; GPIONUMBER=26; GPIOMUX=gpmc_ad10; fi if [ "${PIN}" == "P8_15" ]; then GPIOID=gpio1[15]; GPIONUMBER=47; GPIOMUX=gpmc_ad15; fi if [ "${PIN}" == "P8_16" ]; then GPIOID=gpio1[14]; GPIONUMBER=46; GPIOMUX=gpmc_ad14; fi if [ "${PIN}" == "P8_17" ]; then GPIOID=gpio0[27]; GPIONUMBER=27; GPIOMUX=gpmc_ad11; fi if [ "${PIN}" == "P8_18" ]; then GPIOID=gpio2[1]; GPIONUMBER=65; GPIOMUX=gpmc_clk_mux0; fi if [ "${PIN}" == "P8_20" ]; then GPIOID=gpio1[31]; GPIONUMBER=63; GPIOMUX=gpmc_csn2; fi if [ "${PIN}" == "P8_21" ]; then GPIOID=gpio1[30]; GPIONUMBER=62; GPIOMUX=gpmc_csn1; fi if [ "${GPIONUMBER}" != 0 ]; then #set the mux pin to mode 7 echo 7 > /sys/kernel/debug/omap_mux/${GPIOMUX} #export the pin echo ${GPIONUMBER} > /sys/class/gpio/export fi #if this file does not exist, then we cant use that pin if [ -f "/sys/class/gpio/gpio${GPIONUMBER}/direction" ]; then #set the direction to output echo "out" > /sys/class/gpio/gpio${GPIONUMBER}/direction COUNT=0 until [ $COUNT -gt 5 ]; do echo "1" > /sys/class/gpio/gpio${GPIONUMBER}/value sleep 0.25 echo "0" > /sys/class/gpio/gpio${GPIONUMBER}/value sleep 0.25 let COUNT=COUNT+1 done #un-export the pin echo ${GPIONUMBER} > /sys/class/gpio/unexport else echo "...ERROR: could not use ${PIN}" fi } blinkPIN P8_3 blinkPIN P8_4 blinkPIN P8_5 blinkPIN P8_11 blinkPIN P8_12 blinkPIN P8_14 blinkPIN P8_15 blinkPIN P8_16 blinkPIN P8_17 blinkPIN P8_20 blinkPIN P8_21 #blinkPIN P8_6 #I can't seem to enable the mux for pin to MODE 7 #blinkPIN P8_18 #I can't seem to enable the mux for pin to MODE 7 |
To run this code, save it into a file (e.g. pin_io.sh), and type the following commands on your BeagleBone terminal.
./pin_io.sh
To actually blink LEDs, connect them to the following pins: P8_3, P8_4, P8_5, P8_11, P8_12, P8_14, P8_15, P8_16, P8_17 P8_20 and P8_21. If you do not know where these pins are, make sure you read theĀ BeagleBone system reference manual. Keep in mind that P8, or Port 8, is the expansion port next to the small user LEDs, and the following digit is the respective pin number.
If you would like to add more LEDs and pins to my source code, you must look into the BeagleBone system reference manual, and search for Table 8: Expansion Header P8 Pinout. Search for the signal names that start with gpio and in my script, insert another line of code after:
|
1 2 3 |
if [ "${PIN}" == "P8_21" ]; then GPIOID=gpio1[30]; GPIONUMBER=62; GPIOMUX=gpmc_csn1; fi |
Replace P8_21 with a new pin identifier (e.g. P8_26), assign the associated GPIOID (e.g. gpio1[29] for P8_26 ), assign the associated GPIONUMBER (e.g. 61 for P8_26, see footnotes [1] for more information about this) and finally assign the associated GPIOMUX (e.g. gpmc_csn0, which is the MODE0 “name” as described on Table 9-P8 Mux Options Modes 0-3.
[1] GPIONUMBER comes directly from the GPIOID. Consider gpioXX[YY], so the GPIONUMBER is XX*32 + YY. If we have gpio1[29], then the GPIONUMBER is 1*32+29 = 61. Yes, I could have included a function that could calculate the number on the spot, but that would have made the code a lot harder to understand. If you want to include a function that does this, you may use the following code:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#GPIOnumber initialized to zero, outside the function getGPIOid GPIOnumber=0 function getGPIOid { INPUT=${1} #for example: gpio1[6] arr2=$(echo $INPUT | tr "[|]|gpio" "\n") arrIN=(${arr2//;/ }) FIRST_NUMBER=${arrIN[0]} SECOND_NUMBER=${arrIN[1]} let MULTIPLICATION=32*${FIRST_NUMBER} let ADDITION=${MULTIPLICATION}+${SECOND_NUMBER} GPIOnumber=${ADDITION} } |
Loading a new beaglebone OS onto a SD card using Mac OS X
Posted: March 11, 2012 | Author: Nuno Alves | Filed under: Embedded Systems | Tags: Beagle Bone, Mac OS X | 11 Comments »Installing a new version of the angstrom Linux distribution onto a beagle bone board is as simple as copying the operating system into a SD card. For Mac OS X users, this task can be done through the terminal.
Step #1 – Go to the beaglebone angstrom website, and download the latest *.img.xz pre-compiled file.
Step #2 – Since xz is probably not installed in your base Mac OS X system, download the homebrew software package. After you install homebrew you can also install xz by typing the following in the command line:
Step #3 – In order for you to uncompress the OS into the SD card you need to have administrator privileges. In my computer, I have an account called administrator, so first I need to substitute my current user identity with the administrator. This can be done using the su command. You also need to be in the superuser mode, so after su you also need to use sudo.
sudo -s
Unlike what is reported on the angstrom website you probably won’t be able to write to the SD card without running unmount first. When you try to uncompress the OS file into the SD card you will probably get a Resource busy error message.
Here is a summary of all commands this far:

Step #4 – In order to overwrite all the partitions on the SD card, you have to make sure the mac OS isn’t using it first. On the command line, type mount and once you know in which directory the device is mounted on (eg. /Volumes/BEAGLE_BONE), type:
Step #5 – Once that is done you need to figure out what is the system identifier for your SD card (e.g. disk1). Just type:
Step #6 – You are now ready to load the OS into the SD card. This process will take around 30 minutes.








