Building a Custom GPIO Serial Communication Device Driver

Building a Custom GPIO Serial Communication Device Driver

This project is an improved version based on the final assignment, I've completed as part of the Advanced Embedded Linux Development Specialization.


Project background

This project involves developing a character device driver that facilitates the transfer of byte-sized data through a GPIO pin using a custom communication protocol, similar to the bit-banging technique. It supports only transmission of the data (uni-directional), we will work on the bi-directional data transfer in the upcoming articles.


Data transfer protocol

The data transfer involves to two GPIO pins strobe and data. The data is transmitted in a serial manner, with each bit being read on the strobe's rising edge. The data is transmitted in the order of the least significant bit (LSB) to the most significant bit (MSB) in the below example. we will work on the MSB to LSB through configurable module parameter in the upcoming articles.

custom gpio serial data transfer protocol

Initialization the driver

The below code snippet shows the driver initialization, which includes the

  • GPIO pin initialization
  • Device file creation
  • Device file registration.

you can check the gpioserdev_pinsetup() function here.

// Driver initialization and device creation
static int __init gpioserdev_init(void)
{
	if(alloc_chrdev_region(&gpioserdev.devnum, 0, 1, "gpioserdev") < 0) {
		printk("Device number could not be allocated!\n");
		return -1;
	}

	if((gpioserdev.class = class_create("gpioserdev_class")) == NULL) {
		printk("Device class can not be created!\n");
		goto class_cleanup;
	}

	if(device_create(gpioserdev.class, NULL, gpioserdev.devnum, NULL, "gpioserdev") == NULL) {
		printk("Can not create device file!\n");
		goto device_cleanup;
	}

	cdev_init(&gpioserdev.cdev, &gpioserdev_fops);

	if(cdev_add(&gpioserdev.cdev, gpioserdev.devnum, 1) == -1) {
		printk("Registering of device to kernel failed!\n");
		goto cdevadd_cleanup;
	}

	if (gpioserdev_pinsetup() != 0)
		goto gpiopin_cleanup;

    printk("gpioserdev module loaded\n");
    return 0;
    gpiopin_cleanup:
	cdev_del(&gpioserdev.cdev);
cdevadd_cleanup:
	device_destroy(gpioserdev.class, gpioserdev.devnum);
device_cleanup:
	class_destroy(gpioserdev.class);
class_cleanup:
	unregister_chrdev_region(gpioserdev.devnum, 1);
	return -1;
}        

File operation of the driver

Since our initial requirement is to transmit the data, So we implemented only the write operation. The below code snippet shows the write operation. you can check the gpioserdev_write_byte() function.

// File operations
static struct file_operations gpioserdev_fops = {
	.owner = THIS_MODULE,
	.open = gpioserdev_open,
	.release = gpioserdev_close,
	.write = gpioserdev_write,
};

// Write operation
ssize_t gpioserdev_write(struct file *File, const char *user_buffer, size_t count, loff_t *offs) {
	int to_copy, not_copied, delta;
	char value;
	
    to_copy = min(count, sizeof(value));
	not_copied = copy_from_user(&value, user_buffer, to_copy);
	gpioserdev_write_byte(value);
	delta = to_copy - not_copied;
	return delta;
}        

Building & Loading the driver

The drivers is built and loaded, using the provided Makefile commands,

$ make build  # uses the aarch64-linux-gnu-gcc (64bit) compiler to build the driver
$ make load   # insmod command to load the driver        

Testing the driver

Testing this GPIO serial device driver requires a user-space application that communicates with the driver. Both sending and receiving are performed in the same Raspberry PI 3B+ device.

Simple hardware setup is required to test the driver. Using two jumper to connect strobe and data pins to other two free pin,

Test GPIO pin table

Hence I choose to use echo shell command to send data to the driver and custom python script test/recv.py to read data from the driver. This script is based on simple state machine logic drive to read the data from the driver.

Below is the screenshot of the output,

Test run for article-1

Summary

you can find the project in the github repository, will focus more concepts implementation using the same project on the upcoming articles.

Let me know your thoughts in the comment section...!


N. Viswanathan, PMP? (Vis)

Passionate Project Manager @GEA | Servant Leader, Critical Thinker & Problem Solver | A Proud Father

3 个月

I don’t get it exactly what it means but sounds like a great thing. Congratulations ??

要查看或添加评论,请登录

Pravin Raghul的更多文章

社区洞察

其他会员也浏览了