I am doing some experiments on SAMA5D27-SOM1-EK1 board. I am using Linux operating system. I am exploiting GPIOS of my board. There is RED LED defined at GPIO 10 and USER button defined at GPIO 29. I wrote C++ program to control LED of the board and here is the code :
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
#define LED0_PATH "/sys/class/leds/red"
void removeTrigger(){
// remove the trigger from the LED
std::fstream fs;
fs.open( LED0_PATH "/trigger", std::fstream::out);
fs << "none";
fs.close();
}
int main(int argc, char* argv[]){
if(argc!=2){
cout << "Usage is makeLED and one of: on, off, flash or status"
<< endl;
cout << "e.g. makeLED flash" << endl;
}
string cmd(argv[1]);
std::fstream fs;
cout << "Starting the LED flash program" << endl;
cout << "The LED Path is: " << LED0_PATH << endl;
// select whether it is on, off or flash
if(cmd=="on"){
removeTrigger();
fs.open (LED0_PATH "/brightness", std::fstream::out);
fs << "1";
fs.close();
}
else if (cmd=="off"){
removeTrigger();
fs.open (LED0_PATH "/brightness", std::fstream::out);
fs << "0";
fs.close();
}
else if (cmd=="flash"){
fs.open (LED0_PATH "/trigger", std::fstream::out);
fs << "timer";
fs.close();
fs.open (LED0_PATH "/delay_on", std::fstream::out);
fs << "50";
fs.close();
fs.open (LED0_PATH "/delay_off", std::fstream::out);
fs << "50";
fs.close();
}
else if (cmd=="status"){
// display the current trigger details
fs.open( LED0_PATH "/trigger", std::fstream::in);
string line;
while(getline(fs,line)) cout << line;
fs.close();
}
else{
cout << "Invalid command" << endl;
}
cout << "Finished the LED flash program" << endl;
return 0;
This seems to work fine : When I tape ./target_bin off
the Red Led turn off and the same for on
and flash
commands.
But when I tried to control LED ( RED / GPIO 10 ) with BUTTON ( USER / GPIO 29 ) I added this part of code :
else if (cmd=="button"){
removeTrigger();
fs.open (LED0_PATH "/trigger", std::fstream::out);
fs << "gpio";
fs.close();
fs.open (LED0_PATH "/gpio", std::fstream::out);
fs << "29";
fs.close();
}
And now when I tape ./target_bin button
It shows me an error :
nirq: Flags mismatch irq 80. 00002083 (ledtrig-gpio) vs. 00000083 (USER) leds red: request_irq failed with error -16
Can Anyone help me out please ?
And now when I tape [sic] ./target_bin button It shows me an error :
nirq: Flags mismatch irq 80. 00002083 (ledtrig-gpio) vs. 00000083 (USER) leds red: request_irq failed with error -16
Error 16 is "Device or resource busy".
The device or resource in question is the gpio_key for the push button.
Note that the error message mentions "USER", which happens to be the label
assigned to the gpio_key for the push button in the Device Tree file at91-sama5d27_som1_ek.dts.
gpio_keys {
...
pb4 {
label = "USER";
gpios = <&pioA PIN_PA29 GPIO_ACTIVE_LOW>;
...
};
};
In order for GPIO 29 to be used as a LED trigger, it must be an available, i.e. unused, GPIO.
However the default dts file configures that GPIO 29 to be a gpio_key, and therefore that GPIO is owned by the gpio_key driver.
GPIO 29 is not an unused pin, and is not available for use as a LED trigger (i.e. ownership cannot be transferred to the ledtrig-gpio driver).
You can either use the push-button gpio_key as an input-event device as currently configured, or reconfigure the GPIO 29 so that it is not a gpio_key and available for use as a LED trigger.
ADDENDUM
[responses to comments]
But when i search for the devices which are " USED " on my board with gpioinfo | grep "[used]" command I find that RED led is used before I run my program : line 10: "PA10" "red" output active-high [used] but my code does not show an error for it.
Are you complaining that you did not get a LED error?
I fail to understand what point you are trying to make.
Why would it show an error for BUTTON ...
As I already explained the dts file configures GPIO 29 (i.e. the push button) to be a gpio_key, and assigning GPIO 29 to be a LED trigger causes a conflict.
To be more specific, the LED trigger driver (ledtrig-gpio) requires that the interrupt be configured for "one-shot" mode.
* IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished.
* Used by threaded interrupts which need to keep the
* irq line disabled until the threaded handler has been run.
...
#define IRQF_ONESHOT 0x00002000
This (new) interrupt mode (i.e. 0x00002083) conflicts with the existing mode/flags (i.e. 0x00000083) established by the gpio_keys driver.
This conflict means that this GPIO cannot be used simultaneously for both a gpio_key (input event) and a LED trigger.
Therefore you have to choose in which mode this GPIO will operate.
... and not for LED ?
You mean you want the error to occur on the LED?
You don't get to choose which device causes an error when you perform a specific operation.
The operation you requested, i.e. assign a specific GPIO (which is already installed as a gpio_key) to be the LED trigger, failed during the assignment of the (new) interrupt handler for the gpio_key.
So the error is reported for the gpio_key, and not the LED.
For further confirmation to quell your doubts:
Since the error message mentions "irq 80", you should look up this "irq 80" in the /proc/interrupts file on your board.
That file should indicate that "irq 80" is associated with "GPIO 29" (which per the DT is a gpio_key).
For yet another procedure to quell your doubts:
Locate an unused PIO pin that is accessible and unused (by any peripheral or any driver/process as a gpio).
Assign that pin as the LED trigger.
No error should occur (assuming you selected an unused pin).
Short the pin to ground or VDD_3V3 to change the (default) state of the LED.
How can I reconfigure the button USER so that it is not a gpio_key and be available for use as a LED trigger ?
As I already wrote, the Device Tree file at91-sama5d27_som1_ek.dts is where the GPIO with the push button is declared to be a gpio_key, and I also posted a snippet of the salient lines of that node.
If you do not want that GPIO to be configured as a gpio_key, then the Device Tree file needs to be modified by removing that node (and of course recompiled into a dtb).