Best Way to copy data from Kernel Driver to user space driver - linux

I am having a kernel driver which is currently reading data from a sensor.
Now I have to write a user space application which will call kernel's sensor_read() API and send data to cloud.
How can I expose kernel's sensor_read() call to user space and read this data from user space? Data is about 10 bytes.

How can I expose kernel's sensor_read() call to user space and read this data from user space?
Most likely you should use IIO kernel framework, as it's specifically designed for writing sensor drivers. IIO exposes necessary files for your driver (in /sys/bus/iio/ and /dev/iio*). You can read() those files, or poll() them (to handle interrupts).
Official documentation is available here. You can also use some existing drivers as a reference, look here: drivers/iio/ .
Before IIO framework was introduced, it was common to provide sysfs files for drivers manually. So if you use old enough kernel, that should be the way to write the driver: handle your bus (like I2C) and sysfs files manually. But still, the best way is to use new kernel and IIO.
I am working on a Gyro + accel sensor. Linux driver will be sending events of type EV_MSC for both of them
It's not unusual for chip to have more than one sensor on it. In that case you should create two different drivers: one for accelerometer, and one for gyro. This way you will have two different files, one file per sensor.
For example, look how it's done for LSM330DLC chip (accelerometer + gyro):
accel driver: drivers/iio/accel/st_accel_core.c
gyro driver: drivers/iio/gyro/st_gyro_core.c
Both drivers are calling iio_device_register() function from driver's probe function, which creates corresponding files (which you can read/poll). Refer to documentation for further details.
As per my understanding I will open both the input devices from user space and add then to list of FD's which we want to poll. So when there is a new event how I can determine whether this event is from Gyro or aceel?
If you are curious about how to handle two /dev/input/event* files in user space, you basically have two choices:
using blocking I/O: you can read/poll them in different threads
using non-blocking I/O: you can open those files as O_NONBLOCK and just read() them in the same one thread; if new data is not available yet -- it will return -1 and errno will be set to EAGAIN; you can do those reads in infinite loop, for instance
This answer contains example of how to handle input file in C. And here you can read about blocking/non-blocking I/O.

There are many ways to access sensors data from kernel space to userspace
Check for relevant driver of the sensor you used. Check whether it supports/provides sysfs support.
you can read the data from /sys/class/ interfaces. You need to ensure that the relevant parameters exported to sysfs.
For eg: Temperature sensors should have exported temperature values(equivalent factors) in sysfs entry.
Examples(Below examples are fictions only)
cat /sys/class/hwmon/tempsensor/value
cat /sys/class/hwmon/tempsensor/min_value
cat /sys/class/hwmon/tempsensor/max_value
In some drivers, you can read them through ioctl / read / write api's to read/write sensor data.

You can use IOCTL (ioctl/read) calls to access the kernel functions from User space.
Refer below link for sample:
http://www.tldp.org/LDP/lkmpg/2.4/html/x856.html

Related

Raspberry Pi program that interfaces with I/O (HID, SPI, GPIO)

I am working on a project using a Raspberry Pi where I need to create a GUI that can interface with the various peripherals. Specifically the program needs to:
-read the position data from a touchscreen, mouse, or other HID
-perform some math on on the position data
-store the data in a FIFO buffer
-output that data over the SPI port at a fixed frame rate
I have an electronics background, with some experience writing firmware for microcontrollers, but I'm a relative novice when it comes to this kind of stuff. I have done some research, and it looks like the mouse/touchcreen data is available by reading a file in the /dev/input directory, and I assume you can access the SPI port by reading or writing to some file in the /dev directory. (I am currently running Raspbian)
My initial thoughts were to write a simple C program that a) reads the touchscreen data file and stores it into a preallocated buffer in memory and b) writes the data that next in line to the SPI data file in order to write it out to the SPI port. Part (a) would fire off either on a timer interrupt and poll the touchcreen data to see if it's new, or fire off from a "new data" interrupt. Part (b), the SPI part of the program, would fire off at a fixed rate, probably from a timer interrupt.
So my questions are:
-Is it even possible (or easy) to access interrupts or system timers from the user space? I assume you would need to get hooks into the kernel somehow?
-If so, how would I make it so that my function runs whenever a interrupt or timer fires off?
-How easy is it to use the SPI DMA in user space? Does anyone have any experience doing that? I did a little research and it looks like you need to load a custom kernel driver, but I didn't know how tricky that would be.
-Is it possible to write out a parallel word on the GPIOs the way you would do it on a microcontroller (ie all at once by writing the word to the port's output register)?
I know there are plenty of higher level programming languages and wrappers that allow you to talk to the perepherals, but I'm a little hesitant doing it that way since the timing seems pretty tight. I need to output (3) 16-bit words per frame at ~1k frames per second. At 500kHz SPI bitrate, each frame is 96 us long, and at 1k frames per second, each period is 1ms. This is why SPI DMA, or even writing the data out as a parallel word would be a lot easier in terms of timing.
Thanks for the help!

Non-blocking i2c read from userspace

I'm trying to read and write data off i2c in slave mode and have found several examples to do this in userspace including this most relevant one from NXP (I'm using the iMX8MQ):
https://source.codeaurora.org/external/imx/imx-test/tree/test/mxc_i2c_slave_test/mxc_i2c_slave_test.c?h=imx_4.14.78_1.0.0_ga
However, it looks like if I want to read data, it would be a polling based implementation because it looks like i2c-dev does not provide a way to register userspace callbacks when i2c data is available. Not even sure if any Linux device drivers allow doing this at all. Am I correct in assuming that there is no non-blocking and asynchronous way of doing an i2c read from userspace in slave mode?
I'm not very familiar with writing device drivers so even if I wanted to implement my own, similar to this one:
https://github.com/torvalds/linux/blob/master/drivers/i2c/i2c-slave-eeprom.c
is it a good idea to call a userspace function when data became available (for instance when the driver received an I2C_SLAVE_STOP)?

How a device driver recognise the peripheral mapping in embedded unix

In most example project for embedded system there is a system file in which we can find structures for different peripheral as well as the memory mapping of the peripheral register, in addition there is also a module per peripheral that contains basic function to manipulate the periheral like: periph_enable, periph_write, periph_read; this is the architecture i have in mind when i tackle a new project.
Actually i started to work with a BF609 but now with an embedded linux in it, my task consist in writing a communication driver with another device via UART, as usual i tried to look for the files i used to use but in vain, i can't find the mapping of the different peripheral.
I started to read this book, i undrestand that the kernel see each device like a file and that a driver is mainly the implementation of the open, close, read and writefunctions in these file but i still don't undrestand how these functions communicate with peripheral registers.
My questions:
1) How device drivers recognise the mapping of the peripheral is there sth i missed, is there any example that explain how to implement simple read and write functions via UART for example
2) Where can i find the mapping of the peripheral in the buildroot directory
Thanks in advance

How to use linux device model and /sys filesystem?

I'm new in developing Linux driver.
Traditionally, If i want to create char device, I just need to implement read write and ioctl functions, and register it by register_chrdev_region with corresponding Major device ID. And then use mknod to create a device file of that Major device ID. Then call read write open in user space will then call the corresponding functions by kernel.
But now i'm studying Linux device model and sys filesystem, which is added in kernel 2.6. I'm told if possible, Don't use /dev filesystem, as linux now has a good device model to handle device and driver.This confused me, so I'll summarize my confusion into some questions:
How do I create a char device in /sys? To be more specific, how do I create a null device just like /dev/null?
How do I call my char device driver function from userspace?
I heard that udev is based on sys filesystem to create device file in /dev. Why? Since I'm told "If possible, Don't use /dev filesystem", why does udev use /sys to create file in /dev?
Does a file in sys have any conceptions like char device file or block device?
In /dev, open write from user space will finally map to functions in file operation structure defined by me, then what functions will be called when I open or write to files in /ssy?
Without context your statement about /dev is not clear. Anyway:
You cannot create char devices on sysfs. The main purpose of sysfs is to export information and allow the user to adjust single values (just navigate under /sys/ for some examples). Char devices usually does much complicated things.
If you mean how you call your driver's open,read,write,ioctl, ... well, by doing open(2), read(2), write(2), ioctl(2) (look at man pages of these commands)
when a device appear, the kernel create a directory under /sys. For example take a look at ls /sys/bus/usb/devices/. All that directories are created when an USB device appear. You can try by plug/unplug USB devices. udev put an eye on sysfs to detect new devices and according to the information from sysfs it create the device under /dev. This happens when the driver, somehow, calls device_add(). Often this functions is invoked by other register functions like: device_create, device_register, or other from other sub-systems.
the idea of sysfs is to provide information about the devices and drivers loaded. So you can change device, bus and driver options. Or manually attach a device to a module
Actually, behind the sysfs attributes there is a set of file_operation, where open, read and write are managed by the kernel and not by your driver. In order to create a sysfs attribute you have to provide the pair of function show and store to read/write something from/to the driver. Then the kernel will route the requests to your correct attribute

Transfer data from linux to fpga and inversely?

I have booted a ubuntu on a ZedBoard. I want to transfer data between fpga and linux. For example, I want to write or read a register from linux. What is best way for doing it? I have not any idea.
Thanx.
First of all, you need to specifically say what you want to do, for example. if you want to access the IO signals on the FPGA, you need to first add the GPIO module to your system, synthesize and implement it.
Then you use the Linux GPIO Driver to access the port as it is explained in this page:
Linux GPIO Driver
The GPIO driver fits in the Linux GPIO framework which is not a char
mode driver. Yet it does provide access to the GPIO by user space
through the sysfs filesystem. This allows each GPIO signal to be read
and written in similar manner to a char mode device. The interface is
somewhat documented in the kernel tree at Documentation/gpio.txt. The
following text is aimed to augment, not replace the existing
documentation.
For other, more complex interfaces you need to create your own driver or use one of the drivers that are available and modify it to fit your needs.

Resources