Menu Close

Device Tree Driver of Function Test Code Template

This article provides the template for testing the device tree driver of functions.

For related subjects, please refer to the SOC Table of Contents.

 

Note that before doing the following, you will want to create a new PetaLinux project first. You may choose to follow the steps in developing Linux Device Tree Drivers, as we will be making code changes based on its code.

There are two files that we will need to edit: the driver file written in .c (fii-dt-driver.c if you followed the tutorial), and the device tree file system-user.dtsi.

We will first edit our device tree first by opening system-user.dtsi and including our test nodes under the root node. We will name our nodes accordingly for simplicity.

Download code here.

/include/ "system-conf.dtsi"
/ {
        fii-dt-driver{
               #address-cells = <1>;
               #size-cells = <1>;
               compatible = "fii,fii-dt-driver";
               reg = <0x43c00000 8>;
        };

//Test nodes
        test_node1{
               compatible = "fii,fii-dt-driver";
               status = "okay";
               default-state = "off";
               device_type = "test_device_type1";
               test_array = [12345678 aabbccdd 1234 abcd1234];
              
               test_node2{
                       compatible = "fii,fii-dt-driver";
                       status = "okay";
                       default-state = "on";
                       device_type = "test_device_type2";
                       u8_test_array = /bits/ 8 <0x10 0x20 0x30 0x40 0x50>;
                       u16_test_array = /bits/ 16 <0x1000 0x2000 0x3000 0x4000 0x5000>;
                       u32_test_array = /bits/ 32 <0x100000 0x200000 0x300000 0x400000 0x500000>;
                       u64_test_array = /bits/ 64 <0x10000000 0x20000000 0x30000000 0x400000000x50000000>;

                       u8_test = /bits/ 8 <0x99>;
                       u16_test = /bits/ 16 <0x9999>;
                       u32_test = /bits/ 32 <0x999999>;
                       u64_test = /bits/ 64 <0x99999999>;
               };
        };
};

Note that the first fii-dt-driver node was written in the Device Tree Driver Development tutorial. We simply added another node named test_node1 and a child node within test_node1 named test_node2.

Next, we will modify the system-user.dtsi file from device tree driver development for the of function tests. The changes will only be made in the device registration function at the end: static int fii_dt_driver_init(void){}, where the test code will be added. The comments are placeholders for the test code.

Download code here.

/*  fii-dt-driver.c - The simplest kernel module.
* Copyright (C) 2013 - 2016 Xilinx, Inc
*
*   This program is free software; you can redistribute it and/or modify
*   it unde r the terms of the GNU General Public License as published by
*   the Free Software Foundation; either version 2 of the License, or
*   (at your option) any later version.

*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License along
*   with this program. If not, see <http://www.gnu.org/licenses/>.

*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/uaccess.h>  /* for put_user */

#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>

/* Standard module information, edit as appropriate */
MODULE_LICENSE("GPL");
MODULE_AUTHOR
    ("FII inc.");
MODULE_DESCRIPTION
    ("fii-dt-driver - loadable module template generated by petalinux-create -t modules");

#define DRIVER_NAME "fii-dt-driver"

static const struct of_device_id  of_match_fii_dt_driver[] = {
//    {.compatible = "fii,fii-dt-driver", .data = NULL},
    {.compatible = "fii,fii-dt-driver", },
    {/*sentinel*/},
};

static struct class  *fii_dt_driver_class;

static unsigned int major;
static unsigned int * gpio_base;
static unsigned int * gpio_data;
static unsigned int * gpio_dir;

static int fii_dt_driver_init(void);

static int fii_dt_driver_open(struct inode* node,struct file* filp){

    gpio_data = ioremap(gpio_base, 8);
    if(gpio_data){
        printk("kernel: ioremap(0x%08x)=0x%08x \n", gpio_base, gpio_data);
    }
    else{
        return -EINVAL;
    }

    gpio_dir = gpio_data + 1;

    return 0;
}

static int fii_dt_driver_release(struct platform_device * dev)
{
    iounmap(gpio_data);

    unregister_chrdev(major, "fii-dt-driver");
    device_destroy(fii_dt_driver_class,MKDEV(major,0));
    class_destroy(fii_dt_driver_class);   

    return 0;
}

static ssize_t fii_dt_driver_read(struct file *filp, char *buf, size_t size, loff_t *offset)
{
    unsigned char val[32];
    unsigned int temp;
    unsigned int *addr_p;
    int i,cnt;
    printk("kernel: fii-dt-driver read start.... size = %d\n", size);
    cnt = size;

    addr_p = gpio_data;
    temp = *addr_p ;
    for(i = 0; i < cnt/4; i++ )
    {
        val[i*4 + 3] = temp & 0xff;
        val[i*4 + 2] = (temp >> 8) & 0xff;
        val[i*4 + 1] = (temp >> 16) & 0xff;
        val[i*4 + 0] = (temp >> 24) & 0xff;
        addr_p ++;
        temp = *addr_p;
    }

    if(i % 4 == 1)
    {
        val[i*4 + 0] = temp & 0xff;
    }
    if(i % 4 == 2)
    {
        val[i*4 + 1] = temp & 0xff;
        val[i*4 + 0] = (temp >> 8) & 0xff;
    }
    if(i % 4 == 3)
    {
        val[i*4 + 2] = temp & 0xff;
        val[i*4 + 1] = (temp >> 8) & 0xff;
        val[i*4 + 0] = (temp >> 16) & 0xff;
    }

    copy_to_user(buf, val, cnt);

    return cnt;
}

static ssize_t fii_dt_driver_write(struct file * filp, const char __user *buf, size_t size, loff_t* offset) {
    unsigned char val[32];
    unsigned int temp = 0;
    unsigned int * addr_p;
    int i,cnt;

    memset(val,0,32);
    addr_p = gpio_data;

    printk("kernel: fii-dt-driver write start.... size = %d\n", size);
    copy_from_user(&val, buf, size);
    cnt = size - 1;

    printk("kernel: val[0] = 0x%08x \n", val[0]);

    if(val[0] == 'w')
    {
        temp = val[2];
        temp = temp << 8 | val[3];
        temp = temp << 8 | val[4];
        temp = temp << 8 | val[5];
        *addr_p = temp;
        printk("kernel: gpio_data = 0x%08x \n", temp);
    }

    else if(val[0] == 'd')
    {
        addr_p ++;
        temp = val[2];
        temp = temp << 8 | val[3];
        temp = temp << 8 | val[4];
        temp = temp << 8 | val[5];

        *addr_p = temp;
        printk("kernel: gpio_dir = 0x%08x \n", temp);
    }
    else
    {
        printk("kernel: invalid parameter \n");
    }
    return size;
}

static struct file_operations fii_dt_driver_oprs = {

    .owner      = THIS_MODULE,
    .open       = fii_dt_driver_open,
    .write      = fii_dt_driver_write,
    .read       = fii_dt_driver_read,
};

static int fii_dt_driver_probe(struct platform_device *pdev)
{
    struct resource *res;
    printk ("kernel: enter fii_dt_driver probe ...... \n");
    printk ("kernel: enter fii_dt_driver probe ...... \n");
    printk ("kernel: enter fii_dt_driver probe ...... \n");
    printk ("kernel: enter fii_dt_driver probe ...... \n");
    printk ("kernel: enter fii_dt_driver probe ...... \n");
    printk ("kernel: enter fii_dt_driver probe ...... \n");
   
    res = platform_get_resource(pdev, IORESOURCE_MEM,0);

    if(res){
        gpio_base = res->start;
    }

    major=register_chrdev(0, "fii-dt-driver", &fii_dt_driver_oprs);
    if (major < 0) {
         printk ("Registering the character device failed with %d\n", major);
        return major;
    }

    fii_dt_driver_class = class_create(THIS_MODULE, "fii-dt-driver_class");
    device_create(fii_dt_driver_class,NULL,MKDEV(major,0),NULL,"fii-dt-driver");

    return 0;
}

MODULE_DEVICE_TABLE(of, of_match_fii_dt_driver);

static struct platform_driver fii_dt_driver_drv = {
    .driver     = {
        .name   = "fii-dt-driver",
        .owner  = THIS_MODULE,
        .of_match_table = of_match_fii_dt_driver,
    },
    .probe      = fii_dt_driver_probe,
    .remove     = fii_dt_driver_release,
};

static int fii_dt_driver_init(void){       /* register device  */
    printk(KERN_ERR "|||||||||||||||||||||||||||||||||||||||||||||||| \r\n");
    printk(KERN_ERR "|||||||||||||||||||||||||||||||||||||||||||||||| \r\n");
    printk(KERN_ERR "|||||||||||||||||||||||||||||||||||||||||||||||| \r\n");
    printk(KERN_ERR "\r\n");

    // #############################################
    // OF FUNCTIONS THAT FIND NODES TEST CODE INSERT
    // #############################################

    printk(KERN_ERR "\r\n");
    printk(KERN_ERR "################################################ \r\n");
    printk(KERN_ERR "\r\n");

    // ##########################################################
    // OF FUNCTIONS THAT FIND PARENT/CHILD NODES TEST CODE INSERT
    // ##########################################################

    printk(KERN_ERR "\r\n");
    printk(KERN_ERR "################################################ \r\n");
    printk(KERN_ERR "\r\n");

    // ##########################################################
    // OF FUNCTIONS THAT EXTRACT PROPERTY VALUES TEST CODE INSERT
    // ##########################################################

    printk(KERN_ERR "\r\n");
    printk(KERN_ERR "################################################ \r\n");
    printk(KERN_ERR "\r\n");

    // ##########################################
    // OTHER COMMON OF FUNCTIONS TEST CODE INSERT
    // ##########################################

    printk(KERN_ERR "\r\n");
    printk(KERN_ERR "||||||||||||||||||||||||||||||||||||||||||||| \r\n");
    printk(KERN_ERR "||||||||||||||||||||||||||||||||||||||||||||| \r\n");
    printk(KERN_ERR "||||||||||||||||||||||||||||||||||||||||||||| \r\n");

    return platform_driver_register(&fii_dt_driver_drv);
}

static void fii_dt_driver_exit(void){
    platform_driver_unregister(&fii_dt_driver_drv);
    return;
};

module_init(fii_dt_driver_init);
module_exit(fii_dt_driver_exit);

MODULE_ALIAS("platform:fii-dt-driver");
Posted in Textbook and Training Project

Related Articles

Leave a Reply

Your email address will not be published.

Leave the field below empty!