how to know the Interrupt/GPIO number for a specific pin in linux - linux

i'm doing a project in which i need to handle an interrupt in Linux.
the board i'm using is an ARM9Board based on the s3c6410 MCU by Samsung (arm 11 processor) and it has the following I/O interface :
as the image shows i have EINTx pins for external interrupts and GPxx pins as GPIO pins and i don't mind using any of them but i don't have their numbers !
For EINTx pins :
when i call
int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
unsigned long flags, const char *device);
i need the interrupt number to pass it as the first paramter of the function , so how can i get the irq number for example the EINT16 pin ?
For GPxx pins :
the same story as i need the GPIO pin nuumber to pass it to those functions
int gpio_request(unsigned gpio, const char *label);
int gpio_direction_input(unsigned gpio);
int gpio_to_irq(unsigned gpio);
i.e how do i know the GPIO number for the GPP8 pin ?
i searched the board documents and datasheet but it doesn't contain anything about how to get those numbers , any idea or help on where to look ?

The Embedded Linux you are using should have a GPIO driver that has #define statements for the GPIO pins. You can then get the IRQ number of the specific GPIO using something like:
irq_num = gpio_to_irq(S3C64XX_GPP(8));
The Linux GPIO lib support for that particular chip is available in the following file:
linux/arch/arm/mach-s3c6400/include/mach/gpio.h
There you will find all the #define statements for the various GPIO.
See the section on GPIO Conventions in their documentation:
http://www.kernel.org/doc/Documentation/gpio/gpio.txt

I was doing some work on the GPIO pin as well but it's on a different board, AM335x. Just to let you know, there's quite few of way to do it. One of the method we are using is using memory board to access (write or read) the GPIO pin.
This is a really good article to help me to get things working. Register access to the GPIOs of the Beaglebone via memory mapping

Related

Need to find and open a USB serial device on linux

I'm writing a small C application to run on my (Linux) QNAP NAS that will talk to an Arduino (I have no difficulty with any of the USB code for the arduino). (The arduino has a trusted application on it that accepts text commands via USB serial.)
My wish was to find it using the USB vendor/product IDs (only half implemented at the moment). What I have so far (see below) works quite nicely in that it does find the device.
// runs on NAS
#include <stdio.h>
#include <usb.h>
main () {
struct usb_bus *bus;
struct usb_device *dev;
usb_init();
usb_find_busses();
usb_find_devices();
for (bus = usb_busses; bus; bus = bus->next) {
for (dev = bus->devices; dev; dev = dev->next) {
printf("Trying %s/%s\n", bus->dirname, dev->filename);
printf("\tVendor = 0x%04x\n", dev->descriptor.idVendor);
printf("\tBus = 0x%03x\n", bus->location);
printf("\tFile = %s\n", dev->filename);
if (dev->descriptor.idVendor==0x403) {
printf("\t HEY, THIS IS MINE!\n");
usb_dev_handle *handle = usb_open(dev);
printf("\t HANDLE 0x%08x\n", (int) handle);
//printf(handle, "1,5,62,75\n");
usb_close(handle);
}
}
}
}
The trouble is that now I want to send/receive a little bit of text with the device and I don't know how to do that.
I have expected I should be generating a device name from something in the usb_device struct and then open it like a file (like one would do on Windows).
If that's correct, I need to know the correct way to find out the device name...
I believe I'm using libusb.
I happen to know that -- as currently configured/connected -- it's ttyUSB0 but I'd like to know that using code.
thank you!
I suggest using libusbp. It is a C library with a C++ wrapper, and there is example code showing how to get the name of a serial port based on the vendor ID and product ID of the USB device:
https://github.com/pololu/libusbp/blob/master/examples/port_name/port_name.cpp
libusb is a library used for low level communication with USB devices. But when your communication is limited just to reading device's USB descriptor - libusb is not the best tool.
Linux systems use udev subsystem to manage hot-plug devices. udev reads descriptors of all plugged USB devices and stores them in its database. libudev is the library that you should use to get such info like device names of enumerated devices. In your case you need to remember that usb_device and usb_interface are separate things - only the latter would have the tty device file assigned to it.
Alternatively you could just use udev config to assign a constant device name to your specific device. So you would not have to be looking for it.

Named GPIOs in DeviceTree

I am trying to create a device tree for an embedded system, and would like to expose a few GPIOs to userspace. These are not and should not be used by kernel drivers. For instance, there is a USB device soldered to the board that is controlled by a user-space driver. It has a GPIO reset line, which the userspace library needs to access.
I would like these to be exposed by name in sysfs somewhere so that userspace can access /sys/class/gpio/usbreset instead of needing to know the magic gpio number and needing to specifically "export" it. I have tried setting it up as a GPIO hog, which initializes the GPIO, but its name does not appear in sysfs, and the gpio cannot be exported when it is hogged. I know that I can pick another kernel driver type such as LED, but it is not an LED, and this does not seem very clean to me.
What is the right way to export a named GPIO in sysfs?
You can use the "gpio-leds" type in the devtree. Make sure you have CONFIG_LEDS_GPIO in your kernel. Set up your devtree as described in Documentation/devicetree/bindings/leds/leds-gpio.txt. I know, it says "LED", but the driver just wiggles the GPIO, and doesn't care what's hooked up to it.
Example devtree entry (copied from the docs):
run-control {
compatible = "gpio-leds";
red {
gpios = <&mpc8572 6 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
green {
gpios = <&mpc8572 7 GPIO_ACTIVE_HIGH>;
default-state = "on";
};
};
Those entries will be accessible by name in sysfs, and you can manipulate them from userspace there.
I propose writing a simple kernel module to ask for the GPIO and then exporting a link, the link can be named and hence suitable for your request.
https://www.kernel.org/doc/Documentation/gpio/sysfs.txt
from the link above:
After the GPIO has been exported, gpiod_export_link() allows creating
symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can
use this to provide the interface under their own device in sysfs with
a descriptive name

Register level access in linux device driver

I have only 2 weeks experience in linux driver development, but have good experience on embedded c programming. I have only tried character device driver in linux. Now i wish to try a device driver for a set of LED's connected to GPIO. I am using BeagleBone Black. I wish to access it from the register level and not by just calling any driver. (I am doing this to learn the basics)
I wish my driver GPIO access code to be somewhat like below
void SetLED(unsigned char LED,unsigned char Status){
//Read the port register
//BitWise Operation according to function parameters
//Write back to the register
}
But i need some help on how to access the registers directly in linux. I have got the actual address of the port OUT register from the datasheet as 0x4804C13C
Pardon me if i am breaking any basics in my question. I am really new to linux.
Your driver has to call
struct resource *request_mem_region(unsigned long start, unsigned long len, char *name);
to register exclusive access to that region of memory.
Then it must use ioread8(),ioread16(), etc. and iowrite8(),iowrite16(), etc.

linux gpio c api

I have an powerpc board with 3.2 kernel running on it. Accessing gpio with sysfs works as expected e.g.
> echo 242 > /sys/class/gpio/export
> cat /sys/class/gpio/gpio242/value
> 1
Is there no API to direct access gpio pins from user space? Must I deal with the text based sysfs interface?
I seach for something like:
gpio_set(int no, int val);
Thanks
Klaus
GPIO access through sysfs has been deprecated since Linux 4.8.
The new way for user space access is through libgpiod, which includes a library to link with (obviously), as well as some tools which can be run from the command line (for scripting convenience). Notably, GPIO lines are referenced with the line name string rather than an integer identifier, like with sysfs. E.g.
gpioset $(gpiofind "USR-LED-2")=1
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/README
Edit: sysfs direct access for GPIOs is deprecated, new way is programmatic through libgpiod
sysfs is the lowest level at which you will be able to manipulate GPIO in recent kernels. It can be a bit tedious but it offers several advantages over the old style API:
No ugly ioctl
Can be scripted very easily (think startup scripts)
For inputs, the "value" file can easily be poll-ed for rising/falling/both edges and it will be very reactive to hardware interrupts
I have no example code at the moment but when accessing them through C code, I often implemented a very simple wrapper manipulating file descriptors and having variations of the following interface:
int gpio_open(int number, int out); /* returns handle (fd) */
int gpio_close(int gpio);
int gpio_set(int gpio, int up);
int gpio_get(int gpio, int *up);
int gpio_poll(int gpio, int rising_edge, int timeout);
From then, the implementation is pretty straightforward.
Once you have the devices created in the vfs tree, you can open them like typical files assuming you have a driver written and have the correct major and minor numbers assigned in the makedev file that creates the gpio pins on the vfs tree.
Every GPIO is memory mapped as a register, so you can access to it through /dev/mem. See here. If you want to access directly to a GPIO you have to work at kernel space level

Where can I find the IRQ number in request_irq function?

I'm learning device driver programming in Linux. I am wondering where I could find the IRQ number to be used as the "irq" parameter in the request_irq function?
int request_irq (unsigned int irq,
void (*handler) (int, void *, struct pt_regs *),
unsigned long irqflags,
const char *devname,
void *dev_id);
Thanks
You seem learning the device programming from the wrong side - without a device.
If you have e.g. device on PCI but, then its IRQ is negotiated by the PCI and is available via Linux PCI subsystem.
If you have some custom wired device, quite often its IRQ line is hardwired and you should ask the people who made the custom device where it was wired to and what IRQ it is.
Otherwise buy yourself a copy of LDD3 - it's worth it and describes all that in details.
If you have only a single interrupt controller the irq number is simply the hardware IRQ number.
If you have more then one PIC you need to look in the board specific initialization include files to see which offset was given to the specific PIC your device is connected to and add that to the hardware IRQ number.
It is usually an include file named irqs.h in the include/ directory of of the board specific files. E.g. for an Arm based Bcmring board, the file is in linux/arch/arm/mach-bcmring/include/mach/irqs.h

Resources