-
Notifications
You must be signed in to change notification settings - Fork 0
Bala-Vignesh-Reddy/rpi-drivers
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
#Linux Drivers with RaspberryPi5
This repo contains code and documentation of my journey into
Linux Driver Development on the Raspberry Pi 5.
1. Embedded linux system basics
- components: pi5, bootloader, linux kernel, root filesystem, various peripherals
(LEDs, Keypad, I2C and USB devices), a host machine for development
- Cross-compilation: setting up a toolchain and compiling kernel modules for ARM arch
# Major Commands/Tools
- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- (for kernel/module compiliation)
- scp (for transferring compiled modules remotely)
- insmod, rmmod, dmesg (module management and debugging)
2. Linux Device and Driver Model
- explored the linux device model and how devices, drivers and buses are represented
and managed in the kernel.
- device: physical or virtual object which attaches to bus.
- driver: software entity which may probe for and be bound to devices and which can perform
certain mangement functions.
- bus: device which serves as an attachment point for other devices.
# Three main data structures:
- bus_type: represents one type of bus (eg. USB, PCI, I2C)
- device_driver: represents one driver capabale of handling certain devices on a certain bus
- device: represents one device connected to a bus
# sysfs filesystem
- sysfs is a virtual filesystem that exports information about devices and drivers from the kernel
device model to user space
- /sys/bus/ - contains one subdirectory for each of bus type in kernel
- /sys/devices/ - contains list of devices ( this contains the device tree )
- /sys/bus/<bus>/devices - devices on given bus
- /sys/bus/<bus>/drivers - drivers on given bus
- /sys/class - subdirectory contains single layer subdirectories for each device class
# Device tree
- A devicetree is a tree data structure with nodes that describe the devices in a system. Each
node has property/value pairs that describe the characteristics of the device being represented.
Each node has exactly one parent except for the root node, which has no parent.
- bindings: defined for how data should appear in the DT to describe typical hardware characteristics
of a new device
- DT represent as a set of text files in linux kernel source tree, located under arch/arm/boot/dts/
*.dtsi files are Device Tree source include files. describes hardware that is common to several
platforms which include these files on their *.dts files.
*.dts files are Device Tree source files
- Linux uses DT data for three major purposes:
1. platform indentification: kernel use data in DT to identiy the specific machine.
2. runtime configuration: in most cases, a DT will be only method to communicating data from u-boot
to kernel, so DT can be used to pass in runtime configuration data
3. Device population: after board has been identified, after early config data has been parsed,
then kernel initialization can proceed in normal way.
- Device tree complier (dtc) compiles the DT source into a binary form (.dtb)
## The simplest drivers
- User space applications are not allowed to access peripheral register, storage media or even RAM
memory directly, the hardware is accessed via kernel drivers, and RAM memory is managed by MMU,
with application operating on virtual address.
- Device drivers can be kernel module or statically build into kernel image.
- A kernel module is not necessarily a device driver; it is an extension of kernel. The kernel
module are loaded in virtual memory of kernel.
- LKM(linux loadable kernel modules) have parameters that we can set at load time, boot time or runtime.
- Linux supports three types of devices: character devices, block devices and network devices
## Character drivers
- linux requires a mechanism to transder data from kernel to user space, this transfer of data is
handled via device nodes, also known as virtual files, exist within root fs, they are not true files
- Character Device are most common device, which are read and written directly without buffering. eg. keyboards, monitors, printers etc.
Block devices can only be written to and read from multiples of block size, typically 512 or 1024 bytes.
Network devices are accessed via the BSD socket and interface and networking subsystems.
- In Linux, every device is identified by two numbers: a major number and a minor number. These
numbers can be seen by invoking ls -l /dev on the host PC
- MKDEV macro will combine a mjor number and monior number to a dev_t data type used to hold first device identifier
- unregister_chrdev_region() - function used to return the devices when module is removed
- file_operations structure - defines functions pointer for opening, reading from, writing to the device..
- struct cdev - used to represent character device internally,
- cdev_init() function call will initialize
- cdev_add() - add the details to kernel space
- cdev_del() - function to delete the cdev structure
- mknod - utility provided by the linux to create a device node to reference the driver
- mknod has 4 parameters
first is name of device node
second indicates whether the driver to which device node interfaces is block driver or character driver
last two param are major and minor numbers.
- using the devtmpfs to create device node instead of doing it manually as done in helloworld_rpi5_char_driver.
- A linux driver creates/destroy the class by using following kernel APIs.
- class_create() - creates a class for the device visible in /sys/class
- class_destroy() - removes the class
Linux driver creates the device node by using following kernel APIs.
device_create() - creates a device node in the /dev directory
device_destroy() - removes a device node in the /dev directory
driver will have a class name and a device name; hello_class as a class name and mydev as the device name.
this results in creation of device that appears on fs at /sys/class/hello_class/mydev
alloc_chrdev_region() - automatically allocates a major number to device, registering the device class anc creating the device node.
- Misc Framework is an interface that allows modules to register their individual minor numbers
Device driver implemented as miscellaneous characters uses the major number allocated by the kernel for miscellaneous devices.
this eliminates the need to define a unique major no. for driver.
## Platform Drivers
- A platform driver in Linux is a type of driver used for devices that are directly addressed from a CPU bus.
- two static methods to describe the device
- by direct instantiation of platform_device structres, definition is done in board-specific or SoC specific code.
- in device tree, a hardware description file used on some arch, device driver matches with physical devices describes in .dts file
- Amongst the non-discoverable devices, a huge family is directly part of a system-on-chip: UART
controllers, Ethernet controllers, SPI controllers, graphic or audio devices, etc. In the Linux
kernel, a special bus, called the platform bus, has been created to handle such devices.
# Major Functions/Macro used
- init(): function called once when driver is loaded.
- exit(): function called when driver is removed, it must free all the resouces that were requested
by the init() function
- pr_info(): used to print log messages in kernel space
- bus_register(): function registers the bus with the kobject infra and creates a /sys/bus/platform
directory that consists of two directories devices and drivers.
- device_register(): when new device is plugged into system, the bus controlled driver detects the
calls this function.
- bus: member is pointer to bus_type structure to which device driver is registered
- probe: member is a callback function that is called for each device detected.
- remove: member is callback function that is called to unbind the driver
- module_param(name, type, perm); perm argument specifies permissions of corresponding file in sysfs ideally (S_IRUG0)
- probe(): function is called when bus driver pairs the device to device driver, responsible for initializing the device and registering in kernel
- suspend() and resume(): functions are used by devices that support low power management features
- platform_driver_register(): function responsible for platform device should be registered to platform core
- module_platform_driver(): helper macro for drivers, helps eliminates a lot of boilerplate
- platform_driver_register(): function when kernel module is loaded, the platform device driver registers itself with the platform bus driver
About
Linux Drivers with Raspberry Pi 5
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published