Learn how to allocate and manage device data dynamically in Linux device drivers to support multiple devices using GPIO on Raspberry Pi.
Key Takeaways
- Global variables are insufficient for drivers handling multiple devices; dynamic allocation is necessary.
- Device data should be allocated per device instance to avoid data overwriting.
- Managed memory allocation (devm_kzalloc) simplifies memory management by tying allocation to device lifecycle.
- The probe function is called for each compatible device, so device-specific data must be handled accordingly.
- Proper freeing of resources in the remove function is essential to avoid memory leaks.
What the video covers
- The video demonstrates how to allocate and use device data within a Linux device driver.
- It builds on a previous tutorial where a device with one LED and one button was controlled via GPIO.
- The goal is to extend the driver to handle multiple devices instead of just one.
- A device tree overlay is modified to add a second device with its own GPIO pins.
- The existing driver uses global pointers which cause issues when multiple devices are present.
- Dynamic allocation of device data is introduced to solve the problem of handling multiple devices.
- The video explains the use of managed memory allocation with devm_kzalloc to bind memory lifetime to the device.
- The probe and remove functions are updated to allocate and free device data properly.
- The tutorial includes compiling and testing the driver on a Raspberry Pi via SSH.
- The approach ensures proper memory management and device handling in Linux kernel drivers.
Chapters
- 00:00Introduction and Review of Previous Lecture
- 00:49Overview of Device and Goal for Multiple Device Support
- 02:11Problem with Existing Driver Handling Single Device
- 03:46Issues with Global Variables and Multiple Devices
- 05:46Need for Dynamic Device Data Allocation
- 05:49Struct Definition for Device Data and Memory Allocation
- 08:26Using Managed Memory Allocation (devm_kzalloc)
- 11:26Updating Probe and Remove Functions
- 15:47Testing and Verifying Driver Functionality
Full Transcript — Download SRT & Markdown
Speaker A
Welcome to an episode of my Linux driver tutorials. Today, I want to show you how you can allocate and use device data within your Linux device driver. But before we start, we have to take a look at our previous lecture and what we have done there.
Speaker A
done there. So as you can see here, I'm connected to my Raspberry Pi over SSH and I'm in my Linux driver tutorials folder. So let me go to 19 DTE def GPIO's which was our last session. So last time we have added a
Speaker A
So, as you can see here, I'm connected to my Raspberry Pi over SSH and I'm in my Linux driver tutorials folder. So let me go to 19 DTE def GPIOs, which was our last session.
Speaker A
GPIO properties. So this device has one LED which we can control and one button we can control. And the goal of today's video is I want to write a driver which is able to handle multiple devices because the driver which I have written
Speaker A
So last time, we have added a device to the device tree with two GPIO properties. So if you're taking a look at my overlay.dts, you can see we have added my device to the root path of our device tree. And this device has two GPIO properties.
Speaker A
write jump into it. So what do we have in here? My def driver C are the C sources of our driver. My overlay dts is our device tree overlay. The make file compiles the driver and the device tree
Speaker A
So this device has one LED which we can control and one button we can control. And the goal of today's video is I want to write a driver which is able to handle multiple devices because the driver which I have written in this lecture can only handle one device and I will show you why just in a second.
Speaker A
So I will copy six lines and I will add a new device which I will name my device 2. It is compatible with the same driver and it uses two um also two GPIOs. LED GPIO will be pin
Speaker A
But first, I will copy, um, yep, lecture 19 and I will create a new one which I will call dtdev data and I will jump into it. So what do we have in here? My def driver C are the C sources of our driver. My overlay dts is our device tree overlay. The makefile compiles the driver and the device tree overlay and the readme gives you some more information when you're viewing this on GitHub, for example.
Speaker A
Okay. And if I would use this overlay with the existing driver I would get a problem and I will show you why when we're taking a look at the driver.
Speaker A
Okay. And the first thing I will do in my overlay dts, I will add a second device. So I will copy six lines and I will add a new device which I will name my device 2. It is compatible with the same driver and it uses two, um, also two GPIOs. LED GPIO will be pin, um, 19 and for the button I will use pin 16 here just for an example.
Speaker A
function we bundle everything in a driver strct and we're registering this at the operating system and the problem now is we the probe function is called for every um compatible able device which is added to our system. So before we only
Speaker A
Okay. And if I would use this overlay with the existing driver, I would get a problem and I will show you why when we're taking a look at the driver.
Speaker A
global variable. And at the end in the remove function I will use this global pointer again to free the GPIOs. And the problem is now we have two compatible devices. So this function will be called once for my
Speaker A
So here we have our platform driver or device tree device driver which is compatible with, um, bright light, which is the same compatible string as we have seen in the device tree overlay and we have a probe function, we have a remove function, we bundle everything in a driver struct and we're registering this at the operating system.
Speaker A
the thing is because we don't know how many devices are available or added to the system, we have to allocate this device data dynamically.
Speaker A
And the problem now is the probe function is called for every, um, compatible device which is added to our system. So before, we only had one device. So my def probe was called for my device. And down here we are reading in this GPIO from the device tree.
Speaker A
And the strct has two fields. Both are pointers from the um type GPIO descriptor. And the first one I will name LED for the LED and the second one I will name button for the button.
Speaker A
And we're saving it in a global pointer which I have declared here as a global variable. And at the end in the remove function, I will use this global pointer again to free the GPIOs. And the problem is now we have two compatible devices. So this function will be called once for my device and a second time for my device 2 and these global pointers will be overwritten.
Speaker A
So let me add a pointer here which I will call PR for private data and down here I will allocate memory for this for the device data. So one thing which I could do I could use k set alloc
Speaker A
And to solve this, we need device data. So device data is the data which is assigned to every device within our driver. So yeah, let's allocate and... The thing is because we don't know how many devices are available or added to the system, we have to allocate this device data dynamically.
Speaker A
So I could allocate the memory like this. But the downside when using case set alloc is here whenever an error occurs I have to free the memory again.
Speaker A
So yeah, let's go. But the first thing I want to do is for the device data, I will use a struct which I will call my def data.
Speaker A
with the managed function the um availability of the allocated memory is binded to the device. So as long as the device is present this memory will be present but when the device disappears from the system the memory will be freed
Speaker A
And the struct has two fields. Both are pointers from the, um, type GPIO descriptor. And the first one I will name LED for the LED and the second one I will name button for the button.
Speaker A
be allocated. So yeah this is how to use or how to allocate um the device data and bind it or yeah and bind it to the lifetime of the device.
Speaker A
And now in the probe function, the first thing we have to do is we have to allocate memory for our device data.
Speaker A
So here let's print out an error um out of memory and then let's return the error no memory here.
Speaker A
So let me add a pointer here which I will call PR for private data and down here I will allocate memory for this, for the device data. So one thing which I could do, I could use kset alloc to dynamically allocate memory and to initialize the memory with zeros.
Speaker A
Okay. And here the same for the button. And down here we are turning the LED on and we are reading in the button. Okay.
Speaker A
So I have to amount or I have to allocate, um, size of struct my def data bytes of memory and the flag will be GFP_KERNEL for normal memory allocation.
Speaker A
device data which we have allocated. And this function is called platform set driver data. The first argument is the platform device to which we want to set the driver data and the next argument is the device data which we
Speaker A
So I could allocate the memory like this. But the downside when using kset alloc is here whenever an error occurs I have to free the memory again.
Speaker A
And here in the remove function, we want to fetch the device data again. So let me also declare a my defaf data pointer here. And I will set this pointer to platform get driver data. And in here we
Speaker A
And of course, in the remove function, I would also have to free the memory. But the cool thing is there is an allocation function available for devices which is managed and this function is called devm_kzalloc. And the big advantage is with the managed function the, um, availability of the allocated memory is bound to the device.
Speaker A
we can free the GPOS for the LED and for the button. Okay, so that should be it. Let me try to compile everything and let's see how much mistakes I've made.
Speaker A
So as long as the device is present, this memory will be present but when the device disappears from the system, the memory will be freed automatically. So we don't have to take care of freeing this memory.
Speaker A
again. Okay, the compilation worked. So then let me fire up T-Max and spawn a second window here where we can follow the Linux kernel lock. And in here, first I will apply the device tree overlay uh my overlay DTPO. So now we have added
Speaker A
And the only thing which is different with this devm_kzalloc function is as a first argument we have to pass a pointer to the device for which the memory should be allocated.
Speaker A
Um okay. Yes, you have to believe me. It's a little bit hard to see, but both LEDs are on. Or the second one. No, the second LED is not on.
Speaker A
So yeah, this is how to use or how to allocate, um, the device data and bind it or yeah and bind it to the lifetime of the device.
Speaker A
Yep. It seems I've chosen the wrong GPIO. So, let's check. Oh, I've connected it to pin 16 and not to pin 19. So, that's the error. So, it's a correctable one. We have to open up our device tree overlay again. Here,
Speaker A
Okay. The next thing we have to do is of course we have to check if an error or if the allocation was successful and the only reason why the allocation can fail is when we ran out of memory.
Speaker A
Then I have to remove the device tree overlay and reapply it. Here we go. And now I can load the driver again.
Speaker A
So here let's print out an error, um, out of memory and then let's return the error no memory here.
Speaker A
Yeah, the connection is not the best, but believe me, this time it's really on. And if I turn it off again, both LEDs are off again.
Speaker A
Okay. And now we have allocated the memory for the device and it's available. So now we can use the device data here and store the GPIO descriptor for our LED in our allocated memory.
Speaker A
thanks for watching and goodbye.
Topics:Linux device driverdevice data allocationGPIORaspberry Pidevice tree overlaykernel programmingdevm_kzallocprobe functionremove functiondynamic memory allocation











