Let’s take a quick look at an example C++ program which reads CPU temperature and controls an LED using sysfs. This example is a bit specific in that it’s only been tested on our NXP i.MX6 powered TS-4900 or TS-7970 running Yocto Linux, but the principles could be applied to other embedded systems as well. If you’re interested in the nitty gritty details about sysfs, take a look at The sysfs Filesystem by Patrick Mochel. Suffice it to say for our purposes, sysfs makes it easy for us to interact with system hardware using plain text files located in the /sys/ directory. The file to control the red LED is /sys/class/leds/red-led/brightness. The file to read the CPU temperature is /sys/class/thermal/thermal_zone0/temp. If we want to turn the red LED on, we simply write a ‘1’ to the file, and not surprisingly, writing a ‘0’ will turn it off. If you’ve booted up your TS-4900 or TS-7970, you can see this by running the shell commands: Home
echo 1 > /sys/class/leds/red-led/brightness echo 0 > /sys/class/leds/red-led/brightness
The CPU temperature data is recorded as a 5 digit number. The first two digits represent the temperature in ºC and the remaining three digits are remainders for precision. So, a value of 54321 means 54.321 ºC. You can read the CPU temperature using the system command:
cat /sys/class/thermal/thermal_zone0/temp
Pro Tip: This five digit temperature reading is also known as millicelcius. Best practice would be to keep it in this format for any calculations or comparisons and display it as decimal when ready to display it to a human.
That’s all we need to know in order to create a C++ program, so let’s jump into the code. All of our development will be done onboard, so fire up your TS-4900 or TS-7970 in order to follow along. You can download a tarball of all the demo files here or clone the git repository here. After downloading and extracting, you’ll find a header file, two source files, and a makefile: imx6.h, imx6.cpp, main.cpp, and Makefile.
Pro Tip: Just use ‘wget’ to download the source files directly to the board. This is usually more convenient than using SCP to copy from your desktop to the board as it skips the transferring step.
There’s nothing too special about the files. The imx6.h header file contains all of our function and class declarations while the imx6.cpp source file contains the implementation of the functions and Imx6 class. As far as the implementation details, we’re simply using input and output file streams to write and read from the files in sysfs. For example, the following code block turns the red LED on or off, depending on the input variable:
int IMX6::setLed(int led) { ofstream ofile("/sys/class/leds/red-led/brightness"); ofile << led; ofile.close(); return 0; }
And the following code block reads the current LED status:
int IMX6::ledStatus() { string val; ifstream ifile("/sys/class/leds/red-led/brightness"); ifile >> val; ifile.close(); return std::stoi(val); }
You could take it a step further from ofstream and ifstream and use a library like libudev, but this was beyond the scope of our simple program.
The main.cpp source file contains our main() function and calls the functions within the Imx6 class and does something with them. First, we instantiate our Imx6 class using: Home
IMX6* imx6 = new IMX6();
Then, we demonstrate the use of all the class functions (aka methods):
imx6->setLed(led); imx6->ledStatus(); imx6->getCurrentTemperature();
Our main function turns on the red LED, reads the temperature for ten seconds, turns off the LED, turns the red LED on another time to demonstrate ledStatus() , and then restores initial LED state before exiting.
The Makefile is included to take the guesswork out of compiling. Simply run make while in the imx6-demo directory to compile. You can see this in the terminal output below:
root@ts-imx6:~/imx6-demo# make && ./imx6-demo g++ -std=c++11 -o imx6-demo imx6.cpp main.cpp Turning on red LED to indicate temperature is being read... Current temperature: 56.978 Current temperature: 55.894 Current temperature: 55.352 Current temperature: 54.810 Current temperature: 54.810 Current temperature: 54.810 Current temperature: 54.810 Current temperature: 54.268 Current temperature: 54.268 Current temperature: 54.810 Turning off red LED to indicate temperature is no longer being read... Sleeping for a couple seconds for the next bit... Turning red LED on for to demonstrate imx6->ledStatus()... It's on! Returning red LED to initial state and exiting. root@ts-imx6:~/imx6-demo#
Running make clean will delete the imx6-demo file.
Pro Tip: String two commands together by using ‘&&’ logical operator. This way, the second command will only run if the first succeeded. In the case above, imx6-demo would not run if the make command failed.
That concludes our simple C++ program to read and write to the sysfs in order to read CPU temperature and toggle the red LED on an NXP i.MX6 powered TS-4900 or TS-7970.
Anything we missed? Something you’d like to point out to the readers? We’d like to encourage you to leave your comments below. They’ll be appreciated!