Write and Load Drivers
The driver code is as follows:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/of_irq.h>
struct device_node *SR04_device_node;
struct property *SR04_node_property;
int Trig_gpio_index=0;
int Echo_gpio_index=0;
unsigned long distance =0;
#define GET_DISTANCE _IOR('R',int)
unsigned long GetDistance(void)
{
int time_us = 0;
int timeout = 1000000;
unsigned long flags;
unsigned long distance =0;
local_irq_save(flags);
gpio_set_value(Trig_gpio_index,0);
udelay(5);
gpio_set_value(Trig_gpio_index,1);
udelay(40);
gpio_set_value(Trig_gpio_index,0);
while ((gpio_get_value(Echo_gpio_index) == 0) && timeout)
{
udelay(1);
timeout--;
}
if (timeout == 0)
{
printk("timeout 1..\n");
return -1;
}
timeout = 1000000;
while ((gpio_get_value(Echo_gpio_index) == 1 ) && timeout) {
udelay(1);
time_us++;
timeout--;
}
if (timeout == 0) {
printk("timeout 2..\n");
return -1;
}
printk("echo time: %dus..\n",time_us);
distance = time_us * 170 / 10000;
local_irq_restore(flags);
return distance;
}
int misc_open (struct inode *inode, struct file *file){
printk("misc_open..\n");
return 0;
}
int misc_release (struct inode *inode, struct file *file){
printk("misc_release..\n");
return 0;
}
long misc_ioctl (struct file *file, unsigned int cmd, unsigned long val){
switch(cmd){
case GET_DISTANCE:
distance = GetDistance();
if(distance > 400)
distance = 0xfffffffful;
if(put_user(distance,(int *)val)!=0){
printk("put_user err..\n");
}
break;
default:break;
}
return 0;
}
static const struct file_operations misc_fops={
.owner = THIS_MODULE,
.open = misc_open,
.release = misc_release,
.unlocked_ioctl = misc_ioctl,
};
static struct miscdevice misc_dev={
.minor = MISC_DYNAMIC_MINOR,
.name = "HC_SR04",
.fops = &misc_fops
};
int HC_SR04_probe(struct platform_device *pd){
int ret;
SR04_device_node = of_find_node_by_path("/hc_sr04");
if(SR04_device_node == NULL){
printk("of_find_node_by_path err..\n");
return -1;
}
// MX8MP_IOMUXC_SPDIF_RX__GPIO5_IO04 echo
// MX8MP_IOMUXC_SPDIF_TX__GPIO5_IO03 trig
Trig_gpio_index = of_get_named_gpio(SR04_device_node,"trig-gpios",0);
if(Trig_gpio_index<0){
printk("of_get_name_gpio trig err..\n");
return -1;
}
Echo_gpio_index = of_get_named_gpio(SR04_device_node,"echo-gpios",0);
if(Echo_gpio_index<0){
printk("of_get_name_gpio echo err..\n");
return -1;
}
ret = gpio_request(Trig_gpio_index, "trig");
if (ret<0){
printk("gpio_request trig is error \n");
return -1;
}
ret = gpio_request(Echo_gpio_index, "echo");
if (ret<0){
printk("gpio_request echo is error \n");
return -1;
}
gpio_direction_output(Trig_gpio_index, 0);
gpio_direction_input(Echo_gpio_index);
ret = misc_register(&misc_dev);
if(ret<0){
printk("misc_register err..\n");
return -1;
}
printk("HC_SR04_probe..\n");
return 0;
}
int HC_SR04_remove(struct platform_device *pd){
misc_deregister(&misc_dev);
gpio_free(Trig_gpio_index);
gpio_free(Echo_gpio_index);
printk("HC_SR04_remove..\n");
return 0;
}
static const struct platform_device_id HC_SR04_idtable[] = {
{.name = "HC_SR04",},
{}
};
static const struct of_device_id HC_SR04_data_dt_ids[] = {
{ .compatible = "HC_SR04"},
{ /* sentinel */ }
};
static struct platform_driver HC_SR04_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "HC_SR04",
.of_match_table = of_match_ptr(HC_SR04_data_dt_ids),
},
.probe = HC_SR04_probe,
.remove = HC_SR04_remove,
.id_table = HC_SR04_idtable,
};
module_platform_driver(HC_SR04_driver);
MODULE_LICENSE("GPL");
1. Run the above command to compile the driver make will get the .ko file
2. Copy the .ko file to DEBIX, run the command sudo insmod sr04.ko
3. Run the command sudo dmesg | tail -1 , check the driver print information:
4. You can see that the probe function matches the device tree successfully.