UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Participant igal_kroyter
Participant
4,892 Views
Registered: ‎09-13-2016

Module installation on 2016.4

Jump to solution

Hello,

 

I am trying to add a custom module on Petalinux 2016.4 image.ub.

 

The module supposed to handle 4 different devices which use adjacent memory mapped registers on the PL.

 

I added 4 devices (I think I did it correctly - no errors during compilation) which point to their physical addresses on the PL and are compatible with the same module.

 

After the ZCU102 is brought up I cannot

insmod mymodule

 (because it is not found).

But I can

modprobe mymodule

why?

Then when I try to find my module (after utilizing modprobe) I actually see it 

cat /proc/modules

but when I try to find my devices they are not listed upon:

cat /proc/devices

What registration function is my module (driver) is missing to register each one of the devices.

suggestions will be appreciated.

 

BTW all drivers *module_init function is invoked per entry in the device tree and prints out the physical to virtual address mapping.

 

Thanks,

 

Igal

0 Kudos
1 Solution

Accepted Solutions
Scholar rfs613
Scholar
8,723 Views
Registered: ‎05-28-2013

Re: Module installation on 2016.4

Jump to solution

Let's start with a char driver, as shown in chapter 3 of LDD. In this driver, there will be a call to register the character device. There are multiple ways of doing this, here is one of them:

register_chrdev(driver_major, "driver_name", &driver_ops);

where "driver_major" is an integer, "driver_name" is a string, and "driver_ops" is a structure containing pointers to functions for reading, writing, and so on.

 

The key here is the "driver_major" number. This can be a fixed number, managed by you. For best results, use a number that is not already used by some other driver. Let's assume you pick the value 42.

 

When the driver is loaded, the character device will be created, and it will be visible under /proc/devices with the major number and the driver_name. This just confirms that the driver is loaded; but it does not give you a way to access the functions in the driver.

 

To complete this, we need a "device node", which are typically found in /dev/ directory. Again, these can be created manually, so let's make one, with the following shell command:

mknod /dev/mydevice c 42 1

Note that I used a different name "mydevice" rather than "driver_name", although you can use the same name if you like. Typically however the driver will use one name, and the /dev/ nodes will have instance numbers appended. For example the standard serial driver is "ttyS", but the device(s) are /dev/ttyS0, /dev/ttyS1, etc...

 

You userspace code then can open /dev/mydevice and perform operations on it.

 

The process I have just described is the fundamental of how drivers and userspace interact on Unix/Linux. Nowadays, there are methods to automatically create the /dev/ entry, by using different calls in the driver. This involves some additional helpers such as "udev" and/or "devtmpfs". But the end result is the same: a device node gets created, with the major/minor number matching up with the driver.

9 Replies
Scholar rfs613
Scholar
4,884 Views
Registered: ‎05-28-2013

Re: Module installation on 2016.4

Jump to solution
For "insmod" you need to provide the full path/filename of the module. This includes the .ko suffix. If the module is in a different directory, you must provide the pathname too.

In contrast, when you type "modprobe mymodule", it will load "mymodule.ko" and any dependent modules automatically. It knows to look for module information in /lib/modules/`uname -r`/modules.* files, these are generated at kernel build-time.

This behaviour is not specific to Zynq; you'll see the same behaviour on other Linux systems.
0 Kudos
Participant igal_kroyter
Participant
4,878 Views
Registered: ‎09-13-2016

Re: Module installation on 2016.4

Jump to solution

@rfs613,
thank you for the prompt reply.

 

I have used the following line (per your reply) and it worked for me:

insmod /lib/modules/4.6.0-xilinx/extra/mymodule.ko

How about my other question, regarding the identifications of the devices?

 

Thanks,

 

Igal

0 Kudos
Scholar rfs613
Scholar
4,867 Views
Registered: ‎05-28-2013

Re: Module installation on 2016.4

Jump to solution

Then when I try to find my module (after utilizing modprobe) I actually see it 

cat /proc/modules

but when I try to find my devices they are not listed upon:

cat /proc/devices

What registration function is my module (driver) is missing to register each one of the devices.

suggestions will be appreciated.


You may not be missing anything. It is not required for drivers to appear under /prod/devices. For example if you run "lsmod" on your Linux desktop, you will see many modules are loaded, but most of them do not appear in /proc/devices.

 

To appear under /proc/devices, your driver would need to register either a character device, or a block device. There are many ways to accomplish this, see for example the Linux Device Drivers book, chapter 3 and 16 (available online https://lwn.net/Kernel/LDD3/). The book pre-dates the device tree, so there are newer functions than the ones described in that book.

 

However, you would only create a char/block interface if it makes sense for your driver. Devices like serial ports typically use char devices, while hard disks use block devices. It really depends what your driver does, and how userspace interacts with it.

0 Kudos
Participant igal_kroyter
Participant
4,851 Views
Registered: ‎09-13-2016

Re: Module installation on 2016.4

Jump to solution

@rfs613,

 

 

 

0 Kudos
Scholar rfs613
Scholar
4,827 Views
Registered: ‎05-28-2013

Re: Module installation on 2016.4

Jump to solution


Well there are many options for this, including char/block/network devices, /proc interfaces, /sys interfaces, to name but a few. Let me assume a plain old character device, that is the first example given in LDD3.

 

Applications typically interact by opening a file (/dev/something) and performing read/write operations on it. The files under /dev are not real files, but rather they associate to a driver in the kernel. Take for example the serial port:

$ ls -l /dev/ttyS0
crw-rw---- 1 root dialout 4, 64 Mar 20 13:47 /dev/ttyS0

This is a character device (note the "c" at beginning of the line), with major=4 and minor-64. The major number is how the "file" relates to the kernel driver, which would have registered a driver for the same major=4 number.

 

In the 'old days' the driver would be compiled with major=4, and the /dev entry was manually created using "mknod" command.

 

These days, the assignment of major/minor numbers is largely automated, thanks to thinks like udev and devtmpfs. Drivers can essentially just specify the name they want, and it will appear in /dev/ automatically,  using dynamically assigned major/minor values.

0 Kudos
Participant igal_kroyter
Participant
4,821 Views
Registered: ‎09-13-2016

Re: Module installation on 2016.4

Jump to solution

@rfs613

thank you again for your time.

 

But how do you suggest for me access my module?

 

Thanks,

 

Igal

0 Kudos
Highlighted
Scholar rfs613
Scholar
4,817 Views
Registered: ‎05-28-2013

Re: Module installation on 2016.4

Jump to solution

igal_kroyter wrote:

But how do you suggest for me access my module?


 It really depends on what your module does, what level of performance / safety you need, etc.

 

Looking back at your original post:


igal_kroyter wrote:

The module supposed to handle 4 different devices which use adjacent memory mapped registers on the PL.


So for something like this, I likely would not bother with a driver at all. Instead, I would use /dev/mem (standard kernel driver) to map the registers directly into userspace memory. Pretty much exactly what the devmem utility program does. The downside is that there is no protection between userspace and the hardware. So debugging problems can be difficult, and if the PL ever changes, then you have no "abstraction" layer to handle it.


A more formal method would be a char device, with four instances. Userspace would then read and write from this device, and the driver would turn those operations into PL register calls. You can come up with any protocol you want, such as passing around a structure, or some other method. Using ioctl() on the char device is also common.

 

And another way, as seen in the IIO (Industrial I/O) subsystem of Linux, is to have the kernel driver convert your PL logic into something tangible - for example if it was an ADC, then userspace is likely interested in the reading the channels of the ADC. So you might create a /sys filesystem entry for each ADC channel.

 

Hopefully this gives you some ideas...

 

 

0 Kudos
Participant igal_kroyter
Participant
4,776 Views
Registered: ‎09-13-2016

Re: Module installation on 2016.4

Jump to solution

@rfs613,

 

I am sorry for bothering you but I still did not get it. I wrote some Windows device drivers where as a driver writer I provided a GUID with some strings attached to distinguish between the devices. BUT...here in Linux I provided no names to the devices (beside the module name) thinking to find them somewhere under the /dev file system by a miraculous under the hood work of the Linux system. But I cannot find no where the names of the devices. Let's say that I want to write a user application my application does not know the string to access any of the devices.

 

Could you please elaborate where in the driver I register the name of each device and where I can see that they where actually registered?

 

Thanks,

 

Igal

0 Kudos
Scholar rfs613
Scholar
8,724 Views
Registered: ‎05-28-2013

Re: Module installation on 2016.4

Jump to solution

Let's start with a char driver, as shown in chapter 3 of LDD. In this driver, there will be a call to register the character device. There are multiple ways of doing this, here is one of them:

register_chrdev(driver_major, "driver_name", &driver_ops);

where "driver_major" is an integer, "driver_name" is a string, and "driver_ops" is a structure containing pointers to functions for reading, writing, and so on.

 

The key here is the "driver_major" number. This can be a fixed number, managed by you. For best results, use a number that is not already used by some other driver. Let's assume you pick the value 42.

 

When the driver is loaded, the character device will be created, and it will be visible under /proc/devices with the major number and the driver_name. This just confirms that the driver is loaded; but it does not give you a way to access the functions in the driver.

 

To complete this, we need a "device node", which are typically found in /dev/ directory. Again, these can be created manually, so let's make one, with the following shell command:

mknod /dev/mydevice c 42 1

Note that I used a different name "mydevice" rather than "driver_name", although you can use the same name if you like. Typically however the driver will use one name, and the /dev/ nodes will have instance numbers appended. For example the standard serial driver is "ttyS", but the device(s) are /dev/ttyS0, /dev/ttyS1, etc...

 

You userspace code then can open /dev/mydevice and perform operations on it.

 

The process I have just described is the fundamental of how drivers and userspace interact on Unix/Linux. Nowadays, there are methods to automatically create the /dev/ entry, by using different calls in the driver. This involves some additional helpers such as "udev" and/or "devtmpfs". But the end result is the same: a device node gets created, with the major/minor number matching up with the driver.