Device Driver Programming Lab Manual
Device Driver Programming Lab Manual
1
M.E (Embedded Systems and IoT)
INDEX
Exp. No: 1
DATE: EMBEDDED LINUX DEVELOPMENT ENVIRONMENT SET-UP
13/06/2025
2
M.E (Embedded Systems and IoT)
Software
Hardware:
ALGORITHM
3
M.E (Embedded Systems and IoT)
PROGRAM
bash
ls -l # List files with details cd /home
# Change directory mkdir test # Create a
new directory rm file.txt # Delete a file
cp a.txt b.txt # Copy file mv old.txt
new.txt # Rename or move file System
Information
bash
uname -a # Show kernel version and system info
top # Display running processes df -h
# Show disk usage free -m # Show memory
usage uptime # Show system uptime Package
Management
bash
ifconfig # Show network interfaces (older systems)
ip addr # Show IP addresses (modern systems)
ping google.com # Test network connectivity scp file
user@ip:/path # Secure copy to remote system ssh
user@ip # Connect to remote system via SSH
Development & Compilation
4
M.E (Embedded Systems and IoT)
bash
cat file.txt # View file contents echo "Hi"
> file # Write to a file grep "main" *.c #
Search for 'main' in C files chmod +x script.sh
# Make script executable
Test program
// hello_embedded.c
#include <stdio.h> int
main() {
printf("Hello from Embedded Linux!\n");
return 0;
}
5
M.E (Embedded Systems and IoT)
PROCEDURE
bash
arm-linux-gnueabihf-gcc hello_embedded.c -o hello_embedded
bash ssh
user@<target_ip>
./hello_embedded
6
M.E (Embedded Systems and IoT)
OUTPUT
RESULT
The Embedded Linux development environment was successfully set up. A test application was
cross-compiled on the host, transferred to the target board, and executed, confirming the
environment is ready for further development.
7
M.E (Embedded Systems and IoT)
Exp. No: 2
LINUX KERNEL CONFIGURATION
DATE:20/06/2025
To understand and perform Linux kernel configuration using menu-driven tools, enabling or
disabling features and modules as per system requirements.
Software:
• Linux OS (Ubuntu/Debian/Fedora)
• Kernel source code (from kernel.org)
• GNU make, gcc, ncurses-dev, libssl-dev, bc, flex, bison
• Text editor (e.g., Vim, VS Code)
Hardware:
ALGORITHM
// test_syscall.c
#include <stdio.h>
#include <unistd.h>
8
M.E (Embedded Systems and IoT)
int main() {
long pages = sysconf(_SC_PHYS_PAGES);
long page_size = sysconf(_SC_PAGE_SIZE);
printf("Total RAM: %ld MB\n", (pages *
page_size) / (1024 * 1024)); return 0; }
This program uses system calls that depend on kernel configuration (e.g., memory
reporting).
#include <stdio.h>
#include <stdlib.h> #include
<string.h> int main()
{ FILE *fp; char
buffer[256]; // Print kernel
version printf("Kernel
Version: ");
system("uname -r");
// Check if /proc/config.gz exists (kernel config exposed)
if (access("/proc/config.gz", F_OK) != -1) {
printf("/proc/config.gz is available. You can check kernel config using zgrep.\n");
printf("Example: zgrep CONFIG_PREEMPT /proc/config.gz\n");
} else {
printf("/proc/config.gz not available. Try enabling CONFIG_IKCONFIG and
CONFIG_IKCONFIG_PROC in your kernel.\n");
}
// Check if a specific feature is enabled (e.g., PREEMPT)
fp = popen("zgrep CONFIG_PREEMPT /proc/config.gz 2>/dev/null", "r");
if (fp) {
while (fgets(buffer, sizeof(buffer), fp)) {
printf("Feature Check: %s", buffer);
}
pclose(fp);
} else {
printf("Unable to check kernel config. Is zgrep installed?\n");
}
return 0;
9
M.E (Embedded Systems and IoT)
PROCEDURE
i. Install Dependencies:
bash sudo apt
update
sudo apt install build-essential libncurses-dev bison flex libssl-dev libelf-dev
ii. Download Kernel Source: bash
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.1.tar.xz
tar -xvf linux-6.1.1.tar.xz cd linux-6.1.1 iii. Configure the Kernel:
bash make menuconfig
Navigate through menus to enable/disable features.
Save the configuration when done.
iv. Build the Kernel:
bash make -j$(nproc) sudo
make modules_install
sudo make install
v. Update Bootloader and Reboot:
bash sudo
update-grub sudo reboot
vi. Verify New Kernel:
bash
uname -r
10
M.E (Embedded Systems and IoT)
11
M.E (Embedded Systems and IoT)
12
M.E (Embedded Systems and IoT)
OUTPUT
RESULT
The Linux kernel was successfully configured, compiled, and booted. The system now
runs with a custom kernel tailored to specific requirements, and the configuration changes were
verified using system tools and test programs
13
M.E (Embedded Systems and IoT)
Exp. No: 3
BUILDING EMBEDDED LINUX DEVICE TREES.
DATE:27/06/2025
To understand, build, and deploy a Device Tree for an embedded Linux system, enabling the
kernel to recognize and interface with hardware components on a custom board.
Software:
Hardware:
• ARM-based embedded board (e.g., BeagleBone Black, Raspberry Pi, or custom board)
• USB cable or serial console
• SD card (if booting from removable media)
ALGORITHM
dts
/dts-v1/;
/{
14
M.E (Embedded Systems and IoT)
compatible = "myboard,custom";
model = "Custom Embedded Board";
memory@80000000 { device_type =
"memory";
reg = <0x80000000 0x10000000>; // 256MB RAM
};
leds {
compatible = "gpio-leds";
led0 { label =
"status"; gpios =
<&gpio1 17 0>;
default-state = "on";
};
}; };
{
compatible = "myboard,custom";
model = "Custom Embedded Board";
chosen {
bootargs = "console=ttyS0,115200";
};
aliases {
serial0 = &uart0;
};
uart0: serial@101f1000
{ compatible = "ns16550a";
reg = <0x101f1000 0x1000>;
clock-frequency = <24000000>;
current-speed = <115200>;
interrupt-parent = <&intc>;
interrupts = <5>;
15
M.E (Embedded Systems and IoT)
status = "okay";
};
};
PROCEDURE FOR DEVICE TREE
16
M.E (Embedded Systems and IoT)
OUTPUT
RESULT
The custom Device Tree was successfully compiled and deployed. Upon booting, the
Linux kernel recognized the hardware as described in the .dts file, confirming correct integration
of the Device Tree into the embedded Linux system.
17
M.E (Embedded Systems and IoT)
To develop a simple Linux kernel module, load it into the kernel, and understand how device
models represent hardware in the Linux kernel.
Software:
Hardware:
ALGORITHM
PROGRAM
// simple_module.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
18
M.E (Embedded Systems and IoT)
Makefile makefile
obj-m += simple_module.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
PROCEDURE
i. Set Up Environment:
Install kernel headers: sudo apt install build-essential linux-headers-$(uname -r)
ii. Write Code:
Save the C program as simple_module.c and the Makefile in the same directory.
iii. Compile Module:
bash make
iv. Insert Module:
bash
sudo insmod simple_module.ko dmesg
| tail
v. Explore Device Model:
Check /sys/module/simple_module/
View /proc/modules and /proc/devices
19
M.E (Embedded Systems and IoT)
bash
sudo rmmod simple_module dmesg
| tail
OUTPUT
RESULT
The kernel module was successfully compiled, inserted, and removed. Kernel logs
confirmed the execution of initialization and cleanup functions. The /sys and /proc interfaces
provided insight into how Linux represents and manages devic
20
M.E (Embedded Systems and IoT)
To build and configure a cross-compilation toolchain that runs on a host system and generates
executable code for a different target architecture (e.g., ARM CORE).
Software:
Hardware:
ALGORITHM
21
M.E (Embedded Systems and IoT)
PROGRAM
Hello World Code
#include <stdio.h> int
main() {
printf("Hello from cross-compiled world!\n");
return 0;
}
This verifies that stdio.h and the C library are working correctly.
22
M.E (Embedded Systems and IoT)
PROCEDURE
i. Install Dependencies:
23
M.E (Embedded Systems and IoT)
Binutils: https://ftp.gnu.org/gnu/binutils/
GCC: https://ftp.gnu.org/gnu/gcc/
Newlib: https://sourceware.org/newlib/
bash
tar -xjf binutils-<version>.tar.bz2 mkdir
build-binutils && cd build-binutils
../binutils-<version>/configure --target=arm-none-eabi --prefix=$HOME/x-tools
make -j$(nproc) make install
24
M.E (Embedded Systems and IoT)
bash cd build-gcc
make all -j$
(nproc) make
install
bash
$HOME/x-tools/bin/arm-none-eabi-gcc hello.c -o hello.elf
OUTPUT
RESULT
A working cross-compilation toolchain was successfully built. The test program was
compiled into a target-specific binary using the new toolchain, confirming its functionality.
25
M.E (Embedded Systems and IoT)
To develop and test a GPIO driver that initializes a GPIO pin and toggles an LED using the entry
point (main) function in an STM32 microcontroller.
Software:
• STM32CubeIDE
• STM32CubeMX
• ST-Link Utility
ALGORITHM
PROGRAM
26
M.E (Embedded Systems and IoT)
while (1) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Toggle LED
HAL_Delay(500); // Delay 500 ms
}
}
PROCEDURE
27
M.E (Embedded Systems and IoT)
OUTPUT
RESULT
The GPIO pin was successfully initialized using a custom function, and the LED toggled
continuously from the main() entry point, confirming correct implementation of the GPIO driver.
28
M.E (Embedded Systems and IoT)
To develop and test a GPIO driver that configures a pin as an external interrupt input and toggles
an LED when the interrupt is triggered. Software and Hardware Requirements Hardware:
Software:
• STM32CubeIDE
• STM32CubeMX (integrated)
• ST-Link Utility (optional)
ALGORITHM
PROGRAM
#include "main.h" void
SystemClock_Config(void);
static void MX_GPIO_Init(void);
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while (1) {
29
M.E (Embedded Systems and IoT)
// Interrupt handler
void EXTI15_10_IRQHandler(void)
{ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
}
30
M.E (Embedded Systems and IoT)
PROCEDURE
i. Create Project:
a. Open STM32CubeIDE and create a new STM32 project.
b. Select your MCU (e.g., STM32F103C8 or STM32F401RE).
ii. Configure GPIO:
a. Set PA5 as GPIO_Output.
b. Set PC13 as GPIO_EXTI with falling edge trigger.
c. Enable internal pull-up for PC13. iii. Generate Code:
a. Click “Generate Code” to create the project files. iv.
Write Code:
a. Implement the EXTI callback and IRQ handler as shown above.
v. Build and Flash:
a. Compile and flash the firmware to the STM32 board. vi.
Test:
a. Press the button connected to PC13.
b. Observe the LED on PA5 toggling with each press.
OUTPUT
RESULT
31
M.E (Embedded Systems and IoT)
To develop and test a GPIO device driver that configures a pin as output and toggles an LED
using STM32 microcontroller. Software and Hardware Requirements
Hardware:
• STM32F4XXX board
• LED Resistor (220Ω)
• Breadboard and wires
Software:
• STM32CubeIDE
• ST-Link Utility
ALGORITHM
PROGRAM
#include "main.h" void
SystemClock_Config(void);
static void MX_GPIO_Init(void);
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
32
M.E (Embedded Systems and IoT)
while (1) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Toggle PA5
HAL_Delay(500); // 500 ms delay
}}
static void MX_GPIO_Init(void) {
__HAL_RCC_GPIOA_CLK_ENABLE(); // Enable GPIOA clock
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
PROCEDURE
33
M.E (Embedded Systems and IoT)
OUTPUT
RESULT
The GPIO pin was successfully configured as output, and the LED connected to PA5
blinked at a regular interval, confirming correct implementation of the GPIO driver.
34
M.E (Embedded Systems and IoT)
ALGORITHM
PROGRAM
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
35
M.E (Embedded Systems and IoT)
#include <linux/cdev.h>
#include <linux/device.h>
static ssize_t my_read(struct file *f, char __user *buf, size_t len, loff_t *off) {
return simple_read_from_buffer(buf, len, off, kbuf, BUF_SIZE); }
static ssize_t my_write(struct file *f, const char __user *buf, size_t len, loff_t *off) {
return simple_write_to_buffer(kbuf, BUF_SIZE, off, buf, len); }
36
M.E (Embedded Systems and IoT)
cdev_init(&c_dev, &pugs_fops);
cdev_add(&c_dev, dev_num, 1); cl =
class_create(THIS_MODULE, "chardev_class");
device_create(cl, NULL, dev_num, NULL,
DEVICE_NAME);
printk(KERN_INFO "Char device registered\n");
return 0;
}
module_init(chardev_init); module_exit(chardev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sugadev");
MODULE_DESCRIPTION("Simple Character Device Driver");
PROCEDURE
i. Create a directory
bash
mkdir char_driver && cd char_driver
ii. Write the driver code in a file called chardev.c.
iii. Write a Makefile:
makefile obj-m +=
chardev.o all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
iv. Build the module
bash make
v. Insert the module
bash
sudo insmod chardev.ko
37
M.E (Embedded Systems and IoT)
OUTPUT
38
M.E (Embedded Systems and IoT)
RESULT
39
M.E (Embedded Systems and IoT)
To implement and validate a register-level I²C driver for Cortex-M microcontrollers, facilitating
data communication with an I²C-compatible peripheral device such as an EEPROM.
Hardware:
Software:
ALGORITHM
Initialize system clock and enable GPIO and I²C peripheral clocks.
Configure I²C GPIO pins (SCL and SDA) in alternate function mode.
Set up I²C timing registers for standard mode (100kHz). Create functions for:
40
M.E (Embedded Systems and IoT)
PROGRAM
#include <stdint.h>
#define I2C1_BASE 0x40005400
#define I2C1_CR1 (*(volatile uint32_t *)(I2C1_BASE + 0x00))
#define I2C1_CR2 (*(volatile uint32_t *)(I2C1_BASE + 0x04))
#define I2C1_ISR (*(volatile uint32_t *)(I2C1_BASE + 0x18))
#define I2C1_TXDR (*(volatile uint32_t *)(I2C1_BASE + 0x28))
#define I2C1_RXDR (*(volatile uint32_t *)(I2C1_BASE + 0x24))
#define EEPROM_ADDR 0xA0
void I2C_Init(void) {
// Clock enable, GPIO configuration and I2C1_TIMINGR setup assumed
I2C1_CR1 |= (1 << 0); // Enable I2C
}
void I2C_Write(uint8_t mem_addr, uint8_t data) {
I2C1_CR2 = (EEPROM_ADDR & 0xFE) | (2 << 16) | (1 << 13);
I2C1_CR2 |= (1 << 31); // START while (!(I2C1_ISR & (1 <<
1))); I2C1_TXDR = mem_addr; while (!(I2C1_ISR & (1 << 1)));
I2C1_TXDR = data; while (!(I2C1_ISR & (1 << 6))); I2C1_CR2
|= (1 << 14); // STOP
}
uint8_t I2C_Read(uint8_t mem_addr) {
I2C1_CR2 = (EEPROM_ADDR & 0xFE) | (1 << 16) | (1 << 13);
I2C1_CR2 |= (1 << 31); // START
while (!(I2C1_ISR & (1 << 1))); I2C1_TXDR = mem_addr;
while (!(I2C1_ISR & (1 << 6)));
I2C1_CR2 = (EEPROM_ADDR | 0x01) | (1 << 16) | (1 << 10) | (1 << 13);
I2C1_CR2 |= (1 << 31); // RESTART
while (!(I2C1_ISR & (1 << 2))); uint8_t data = I2C1_RXDR;
while (!(I2C1_ISR & (1 << 6))); I2C1_CR2 |= (1 << 14); // STOP
return data;
} int main(void)
{
I2C_Init();
I2C_Write(0x10, 0x55); // Write byte 0x55 to memory address 0x10
41
M.E (Embedded Systems and IoT)
PROCEDURE
i. Connect SDA and SCL lines between MCU and EEPROM. Use 4.7kΩ pull-ups.
ii. Flash the firmware using ST-Link or another compatible programmer.
iii. Observe logic lines using a scope or logic analyzer (optional). iv. Set breakpoints after
write and read operations to observe register values.
v. Verify written and read values match as expected.
OUTPUT
RESULT
The I²C driver was successfully implemented, allowing reliable communication with the
EEPROM peripheral. The byte written to a memory address was accurately read back, validating
functional I²C protocol integration
42
M.E (Embedded Systems and IoT)
43