KEMBAR78
Device Driver Programming Lab Manual | PDF | Linux | Microcontroller
0% found this document useful (0 votes)
16 views43 pages

Device Driver Programming Lab Manual

Fanatic story

Uploaded by

sparkzvk151
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views43 pages

Device Driver Programming Lab Manual

Fanatic story

Uploaded by

sparkzvk151
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 43

M.

E (Embedded Systems and IoT)

SCHOOL OF ELECTRICAL AND ELCTRONICS


DEPARTMENT OF ELECTRONICS AND COMMUNICATION
ENGINEERING

Lab Experiment Manual

Name of the Course: DEVICE DRIVER PROGRAMMING LAB


Subject Code: SECB6302 Semester: III
Course Co-ordinator: Dr.M. Sugadev
ECE Department Year: 2025-2026

1
M.E (Embedded Systems and IoT)

INDEX

Exp. DATE Page


Name of Experiment
No No.
1. 13/06/2025 Embedded Linux Development Environment Set-Up 1
2. 20/06/2025 Linux Kernel Configuration 5
3. 27/06/2025 Building Embedded Linux Device Trees. 8
4. 04/07/2025 Building s Cross-Compilation Toolchain for 12
Embedded Target
5. 11/07/2025 Building a Cross-Compilation Toolchain For 15
Embedded Target
Implementing GPIO Driver Initialization Function
6. 20
18/07/2025 and Entry Point Function
Implementing GPIO Driver Exit Function and
7. 23
25/07/2025 Interrupt Function
01/08/2025 Implementation of GPIO Device Driver for Cortex-M
8. 26
Based Microcontroller
9. 08/08/2025 Implementation of a Simple Character Device Driver 28
in Linux
Implementation of I²C Driver for Cortex-M Based
10. 32
13/08/2025 Microcontroller

Exp. No: 1
DATE: EMBEDDED LINUX DEVELOPMENT ENVIRONMENT SET-UP
13/06/2025

2
M.E (Embedded Systems and IoT)

Aim of the Experiment

To configure a complete development environment for Embedded Linux, including


crosscompilation tools, target communication, and application deployment.

Software and Hardware Requirements

Software

• Ubuntu Linux (20.04 or later)


• Cross-compilation toolchain (e.g., arm-linux-gnueabihf-gcc)
• Build tools: make, gcc, g++, cmake
• Serial communication tools: minicom, screen, or picocom
• File transfer tools: scp, rsync
• Optional: Eclipse IDE or VS Code with remote SSH plugin

Hardware:

• ARM-based development board


• SD card (with Embedded Linux image)
• Host PC (x86_64)

ALGORITHM

 Install required packages on the host system.


 Set up the cross-compilation toolchain.
 Configure serial or SSH communication with the target.
 Write and cross-compile a test application.
 Transfer the binary to the target board.
 Execute and verify the output on the target.

3
M.E (Embedded Systems and IoT)

PROGRAM

Basic Linux Commands: File

and Directory Operations

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 sudo apt update # Update package


list sudo apt install vim # Install a package
sudo apt remove nano # Remove a package
Networking

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

bash gcc hello.c -o hello # Compile a C


program ./hello # Run the compiled
program make # Build using
Makefile Useful Utilities

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

Install Required Packages:

bash sudo apt


update
sudo apt install build-essential gcc g++ make cmake \
minicom screen rsync openssh-client \ gcc-arm-linux-
gnueabihf gdb-multiarch

Cross-Compile the Program:

bash
arm-linux-gnueabihf-gcc hello_embedded.c -o hello_embedded

Transfer to Target Board:


bash
scp hello_embedded user@<target_ip>:/home/user/

Run on Target: SSH into the board:

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

Aim of the Experiment

To understand and perform Linux kernel configuration using menu-driven tools, enabling or
disabling features and modules as per system requirements.

Software and Hardware 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:

• Desktop PC or ARM based Board

ALGORITHM

 Download and extract the Linux kernel source.


 Install required dependencies.
 Use make menuconfig or make nconfig to configure the kernel.
 Enable/disable features, modules, and drivers.
 Save the configuration to .config.
 Compile the kernel and install it.
 Reboot and verify the new kernel.

PROGRAM FOR KERNEL FEATURE TEST

// 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).

PROGRAM TO CHECK KERNEL FEATURES AND VERSION

#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

Aim of the Experiment

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 and Hardware Requirements

Software:

• Linux host system (Ubuntu recommended)


• Device Tree Compiler (dtc)
• Cross-compiler toolchain (e.g., arm-none-eabi-gcc or aarch64-linux-gnu-gcc)  Text
editor (VS Code, Vim)

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

 Identify the hardware components and their memory-mapped addresses.


 Write a Device Tree Source (.dts) file describing the hardware.
 Compile the .dts file into a Device Tree Blob (.dtb) using dtc.
 Deploy the .dtb to the boot partition of the embedded system.
 Boot the system and verify hardware enumeration via /proc/device-tree or dmesg.

PROGRAM FOR DEVICE TREE SOURCE EXAMPLE

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";
};
}; };

Note: Save this as myboard.dts.

PROGRAM FOR UART DEVICE NODE IN DEVICE TREE

{
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

i. Install Device Tree Compiler:


a. bash
b. sudo apt install device-tree-compiler ii. Write
the Device Tree Source:
a. Use a text editor to create myboard.dts as shown above. iii.
Compile the Device Tree:
a. bash
b. dtc -I dts -O dtb -o myboard.dtb myboard.dts
iv. Deploy the DTB:
a. Copy myboard.dtb to the boot partition of your embedded system (e.g., /boot or
/boot/dtbs/).
v. Configure Bootloader (if needed):
a. For U-Boot:
i. bash
ii. setenv fdtfile myboard.dtb iii. saveenv
vi. Boot and Verify:
a. Boot the board and check:
i. bash
ii. dmesg | grep -i dtb
iii. ls /proc/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)

Exp. No: 4 BUILDING A CROSS-COMPILATION TOOLCHAIN


DATE:04/07/2025 FOR EMBEDDED TARGET

Aim of the Experiment

To develop a simple Linux kernel module, load it into the kernel, and understand how device
models represent hardware in the Linux kernel.

Software and Hardware Requirements

Software:

• Linux OS (Ubuntu or similar)


• GCC (for kernel module compilation)
• Kernel headers (linux-headers-$(uname -r))
• Make utility
• Text editor (e.g., VS Code, Vim)

Hardware:

• x86_64-based PC or virtual machine


• Root access to load/unload kernel modules

ALGORITHM

1. Write a basic kernel module with init and exit functions.


2. Create a Makefile to compile the module.
3. Use insmod to insert the module and rmmod to remove it.
4. Use dmesg to observe kernel logs.
5. Explore /sys/class, /sys/devices, and /proc/devices to understand device models.

PROGRAM

// simple_module.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

static int __init simple_init(void) {

18
M.E (Embedded Systems and IoT)

printk(KERN_INFO "Simple Module Loaded\n");


return 0;
}

static void __exit simple_exit(void) {


printk(KERN_INFO "Simple Module Unloaded\n");
} module_init(simple_init);
module_exit(simple_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sugadev");
MODULE_DESCRIPTION("A Simple Linux Kernel Module");

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

vi. Remove Module:

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)

Exp. No: 5 BUILDING A CROSS-COMPILATION TOOLCHAIN FOR


DATE:11/07/2025 EMBEDDED TARGET

Aim of the Experiment

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 and Hardware Requirements

Software:

• Linux-based host system (e.g., Ubuntu)


• GCC (GNU Compiler Collection)
• Binutils
• Make
• Newlib or glibc (C standard library)
• Crosstool-NG or Buildroot (optional but recommended)
• Target board emulator or actual embedded board (e.g., Raspberry Pi, STM32)

Hardware:

• Host PC (x86, 64 bit)


• Target board (ARM Cortex-A or Cortex-M based)

ALGORITHM

 Install required development tools on the host.


 Download and configure Binutils for the target architecture.
 Build and install Binutils.
 Download and configure GCC for the target.  Build and install GCC (stage 1).
 Build and install the C library (e.g., Newlib).
 Rebuild GCC with C library support (stage 2).
 Test the toolchain by compiling a sample program for the target.

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.

LED Blink (for bare-metal ARM target)


#define RCC_AHB1ENR (*(volatile unsigned int*)0x40023830)
#define GPIOA_MODER (*(volatile unsigned int*)0x40020000)
#define GPIOA_ODR (*(volatile unsigned int*)0x40020014) void
delay() {
for (volatile int i = 0; i < 100000; i++);
} int main()
{
RCC_AHB1ENR |= 0x1; // Enable GPIOA clock
GPIOA_MODER |= (1 << 10); // Set PA5 as output while
(1) {
GPIOA_ODR ^= (1 << 5); // Toggle PA5
delay();
}}
Note: A bare-metal program for STM32F4 that toggles the onboard LED on PA5.

22
M.E (Embedded Systems and IoT)

Integer Math Test #include


<stdio.h> int main() { int a =
10, b = 3; printf("a + b =
%d\n", a + b); printf("a * b =
%d\n", a * b); printf("a / b =
%d\n", a / b); return 0; }
Memory Test
#include <stdio.h>
#include <stdlib.h> int
main() {
int *arr = malloc(5 * sizeof(int));
if (!arr) {

printf("Memory allocation failed\n");


return 1; }
for (int i = 0; i < 5; i++)
{ arr[i] = i * i;
printf("arr[%d] = %d\n", i, arr[i]);
}
free(arr);
return 0;
}.

PROCEDURE

i. Install Dependencies:

bash sudo apt


update
sudo apt install build-essential libgmp-dev libmpfr-dev libmpc-dev texinfo

23
M.E (Embedded Systems and IoT)

ii. Create Directories:

bash mkdir -p $HOME/x-


tools/src cd $HOME/x-
tools/src

iii. Download Sources:

Binutils: https://ftp.gnu.org/gnu/binutils/
GCC: https://ftp.gnu.org/gnu/gcc/
Newlib: https://sourceware.org/newlib/

iv. Build Binutils:

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

v. Build GCC (Stage 1):

bash tar -xjf gcc-


<version>.tar.bz2 mkdir build-
gcc && cd build-gcc
../gcc-<version>/configure --target=arm-none-eabi --prefix=$HOME/x-tools --
enablelanguages=c --without-headers make all-gcc -j$(nproc)
make install-gcc

vi. Build Newlib:

bash tar -xjf newlib-<version>.tar.bz2


mkdir build-newlib && cd build-
newlib
../newlib-<version>/configure --target=arm-none-eabi --prefix=$HOME/x-tools
make -j$(nproc) make install

vii. Build GCC (Stage 2):

24
M.E (Embedded Systems and IoT)

bash cd build-gcc
make all -j$
(nproc) make
install

viii. Test Toolchain:

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)

Exp. No: 6 IMPLEMENTING GPIO DRIVER INITIALIZATION FUNCTION


DATE:18/07/2025 AND ENTRY POINT FUNCTION

Aim of the Experiment

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 and Hardware Requirements Hardware:

• STM32F4 Discovery or Nucleo board


• Onboard or external LED
• USB cable for programming and power

Software:

• STM32CubeIDE
• STM32CubeMX
• ST-Link Utility

ALGORITHM

1. Start the system and initialize the HAL library.


2. Configure the system clock.
3. Initialize the GPIO peripheral using a custom initialization function.
4. In the main() function (entry point), toggle the GPIO pin in a loop.
5. Add a delay to observe LED blinking.

PROGRAM

#include "main.h" // Function


Prototypes void
SystemClock_Config(void);
void GPIO_Init(void); // Initialization function int
main(void) {
HAL_Init(); // Initialize HAL
SystemClock_Config(); // Configure system clock
GPIO_Init(); // Call GPIO initialization

26
M.E (Embedded Systems and IoT)

while (1) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Toggle LED
HAL_Delay(500); // Delay 500 ms
}
}

// GPIO Initialization Function


void 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); // Initialize GPIOA Pin 5 }

PROCEDURE

i. Create a New Project:


Open STM32CubeIDE and create a new STM32 project.
Select your MCU (e.g., STM32F401RE).
ii. Configure GPIO:
In the .ioc file, set PA5 as GPIO_Output.
Generate the code.
iii. Write Initialization Function:
Implement GPIO_Init() as shown above.
iv. Use Entry Point:
In main(), call GPIO_Init() and toggle the pin.
v. Build and Flash:
Compile the project and flash it to the board.
vi. Test:
Observe the LED blinking at 1 Hz (500 ms ON/OFF).

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)

Exp. No: 7 IMPLEMENTING GPIO DRIVER EXIT FUNCTION AND


DATE:25/07/2025 INTERRUPT FUNCTION

Aim of the Experiment

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:

• STM32F4 Discovery or Nucleo board


• Push-button (if not onboard)
• LED (if not onboard)
• Breadboard and jumper wires

Software:

• STM32CubeIDE
• STM32CubeMX (integrated)
• ST-Link Utility (optional)

ALGORITHM

• Initialize system clock and GPIO peripherals.


• Configure one GPIO pin as output (for LED).
• Configure another GPIO pin as input with EXTI (for button).
• Enable interrupt in NVIC.
• In the EXTI callback, toggle the LED.  Loop forever in main().

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)

// Main loop does nothing; interrupt handles LED toggle


}
}

// GPIO Initialization static void


MX_GPIO_Init(void) {
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();

GPIO_InitTypeDef GPIO_InitStruct = {0};


// Configure PA5 as output (LED)
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);

// Configure PC13 as input with EXTI


GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

// Enable EXTI line interrupt


HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}
// Interrupt callback
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{ if (GPIO_Pin == GPIO_PIN_13) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Toggle LED
}
}

// 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

The GPIO pin configured as an external interrupt successfully triggered an interrupt on


button press, and the LED toggled accordingly. This confirms the correct implementation of the
GPIO driver with EXTI functionality.

31
M.E (Embedded Systems and IoT)

Exp. No: 8 IMPLEMENTATION OF GPIO DEVICE DRIVER FOR


DATE:01/08/2025 CORTEX-M BASED MICROCONTROLLER

Aim of the Experiment

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

 Initialize system clock and GPIO peripheral.


 Configure the desired GPIO pin as output.
 Toggle the pin state in a loop with delay.  Observe LED blinking.

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

i. Open STM32CubeIDE and create a new STM32 project.


ii. Select your MCU (e.g., STM32F401RE). iii. In
the .ioc file, set PA5 as GPIO_Output. iv. Enable the GPIOA
clock if not already enabled.
v. Click “Generate Code” to create the project files.
vi. Implement the LED toggle logic in main.c.
vii. Compile the project and flash it to the STM32 board. viii. Observe the
LED blinking at 1 Hz (500 ms ON/OFF).

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)

Exp. No: 9 IMPLEMENTATION OF A CHARACTER


DATE:08/08/2025 DEVICE DRIVER IN LINUX

Aim of the Experiment


To develop, compile, and load a basic character device driver module in the Linux kernel
space that allows user space applications to read from and write to a virtual device.

Hardware and Software Requirements

Hardware x86 or ARM-based


system USB keyboard and
console
Software Tools
Ubuntu/Debian or any Linux distro
GCC (Cross-compiler if embedded)
Linux kernel headers (linux-headers-$(uname -r))
Make utility, insmod/rmmod, dmesg, mknod
A text editor (e.g., Vim, VS Code)

ALGORITHM

 Initialize a character device using alloc_chrdev_region.


 Define and register file_operations structure (open, read, write, release).
 Allocate memory in kernel space for the device buffer.
 Implement read() and write() handlers for communication with user space.
 Create a device class and device file in /dev/.
 Compile and insert the module using insmod.
 Use echo and cat from the user space to interact with the device.
 Remove the module and cleanup on exit.

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>

#define DEVICE_NAME "chardev"


#define BUF_SIZE 1024

static dev_t dev_num; static


struct cdev c_dev; static
struct class *cl; static char
kbuf[BUF_SIZE];

static int my_open(struct inode *i, struct file *f) {


printk(KERN_INFO "Device opened\n");
return 0;
}

static int my_close(struct inode *i, struct file *f) {


printk(KERN_INFO "Device closed\n"); return
0;
}

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); }

static struct file_operations pugs_fops =


{
.owner = THIS_MODULE,
.open = my_open,
.release = my_close,
.read = my_read,
.write = my_write
};

static int __init chardev_init(void) {


alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME);

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;
}

static void __exit chardev_exit(void)


{ device_destroy(cl, dev_num);
class_destroy(cl); cdev_del(&c_dev);
unregister_chrdev_region(dev_num, 1);
printk(KERN_INFO "Char device removed\n");
}

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)

vi. Create a device file:


bash sudo mknod /dev/chardev c
<major> 0 sudo chmod 666
/dev/chardev
Replace <major> with the major number from dmesg.
vii. Test with echo and cat:
bash
echo "Hello Kernel" > /dev/chardev cat
/dev/chardev
viii. Remove the module:
bash
sudo rmmod chardev

OUTPUT

38
M.E (Embedded Systems and IoT)

RESULT

A character device driver has been successfully written and compiled.

39
M.E (Embedded Systems and IoT)

Exp. No: 10 IMPLEMENTATION OF I²C DRIVER FOR


DATE:13/08/2025 CORTEX-M BASED MICROCONTROLLER
Aim of the Experiment

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.

Software and Hardware Tools Required

Hardware:

• STM32 (or similar Cortex-M) development board


• EEPROM or I²C peripheral (e.g., AT24C02)  Breadboard and jumper wires
• Pull-up resistors (4.7kΩ for SDA & SCL)
• ST-Link/J-Link programmer/debugger
• Power source (typically USB)

Software:

• STM32CubeIDE, Keil uVision, or IAR Embedded Workbench


• STM32 standard peripheral or CMSIS header files
• Flash loader/debugger utility

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:

i. I²C start condition


ii. Transmit slave address
iii. Write or read data iv. Stop condition

 Write data to EEPROM at a specified memory location.


 Read back the same location and verify the data.

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)

uint8_t result = I2C_Read(0x10); // Read it back


while (1);
}

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

You might also like