全志H3-nanopi-duo2开发板GPIO驱动开发

这篇具有很好参考价值的文章主要介绍了全志H3-nanopi-duo2开发板GPIO驱动开发。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1:获取对应开发板duo2的内核源码

从官网获取
[friendlyarm的nanopi-duo2](https://wiki.friendlyelec.com/wiki/index.php/NanoPi_Duo2/zh#.E5.AE.9A.E5.88.B6.E5.91.BD.E4.BB.A4.E8.A1.8C.E7.9A.84.E6.AC.A2.E8.BF.8E.E4.BF.A1.E6.81.AF.EF.BC.88.E6.96.87.E5.AD.97LOGO.EF.BC.89)
此网页里面有duo2的很多资料,用户使用,uboot,kernel等等
需要从中下载linux-4.14内核源码,以下是官网维基中的部分内容,
用来作为参考

下载Linux内核源码,并切换分支:
$ git clone https://github.com/friendlyarm/linux.git -b sunxi-4.14.y --depth 1

编译和更新Linux内核:

$ apt-get install u-boot-tools
$ cd linux
$ touch .scmversion
$ make sunxi_defconfig ARCH=arm CROSS_COMPILE=arm-linux-
$ make zImage dtbs ARCH=arm CROSS_COMPILE=arm-linux-

[ 注意: 这里我只需要编译驱动模块,不需要编译内核,上一篇文章有编译驱动模块的步骤]
编译完成后会在arch/arm/boot/目录下生成zImage,并且在arch/arm/boot/dts/目录下生成dtb文件,dtb文件是设备树二进制文件。

假设SD卡的boot分区挂载在/media/SD/boot/,更新SD卡上的zImage和dtb文件:

$ cp arch/arm/boot/zImage /media/SD/boot/
$ cp arch/arm/boot/dts/sun8i-*-nanopi-*.dtb /media/SD/boot/

也可以用scp命令通过网络更新:

$ scp arch/arm/boot/zImage root@192.168.1.230:/boot
$ scp arch/arm/boot/dts/sun8i-*-nanopi-*.dtb root@192.168.1.230:/boot

2:进入源码目录(确保交叉编译工具链和环境变量配置正确)

2.1:源码根目录新建my_make内容为:

#!/bin/sh
export CROSS_COMPILE=$HOME/pan/arm_gcc/bin/arm-cortexa9-linux-gnueabihf-
export ARCH=arm 

然后source ./my_make

2.2:执行一下命令:

apt-get install u-boot-tools
touch .scmversion
make sunxi_defconfig //获取默认配置
make dtbs //编译设备树文件

执行make dtbs没有报错,说明环境变量和交叉编译都没问题

3: 修改设备树文件

duo2板子对应此文件:

arch\arm\boot\dts\sun8i-h3-nanopi-duo2.dts

设备树文件怎么修改,取决于要使用什么硬件或者说哪个引脚;
这里我要使用PA11引脚用来控制继电器,输出高低电平即可

全志H3-nanopi-duo2开发板GPIO驱动开发
在官方的设备树文件里面,此引脚被用作I2C引脚,被占用了
需要让占用的节点 status = “disabled”;

//这是pinctrl子节点,可以看到使用了引脚PA11
	...
	i2c0_pins: i2c0 {
					pins = "PA11", "PA12";
					function = "i2c0";
				};
	...
/*----------------------*/	
//这是client节点	
...	
&i2c0 {
	status = "okay"; //这里修改为disabled,禁用此节点I2C
	rtc@68 {
		compatible = "dallas,ds1307";
		reg = <0x68>;
	};
};
...

3.1: 添加自己的GPIO节点

在sun8i-h3-nanopi-duo2.dts中添加pinctrl子节点PA11引脚的复用功能

/{ //根节点
	...
}
//此内容书写位置平行于根节点
&pio {
	gpio_pin: gpio { //在pinctrl追加复用功能,设置gpio复用
		pins = "PA11";
		function = "gpio_out";
	};
};

在sun8i-h3-nanopi-duo2.dts中,在根节点内部添加client节点

/{ //根节点
	...
	...
	my_gpio{
		compatible = "gin,gpio";
		pinctrl-names = "default";
		pinctrl-0 = <&gpio_pin>; //选择复用功能
		mydvc-gpios = <&pio 0 11 GPIO_ACTIVE_HIGH>; /* PA11 第0组第11个引脚*/
		status = "okay";
	};
}
...
...
&pio {
	gpio_pin: gpio { //在pinctrl追加复用功能,设置gpio复用
		pins = "PA11";
		function = "gpio_out";
	};
};

3.2: make dtbs 编译设备树

make dtbs
//得到:sun8i-h3-nanopi-duo2.dtb

把dtb文件放入开发板目录下
挂载SD卡的boot分区

//挂载
sudo mount /dev/mmcblk0p1 /media/SD/boot/
//拷贝
sudo cp ./sun8i-h3-nanopi-duo2.dtb /media/SD/boot/
//取消挂载
sudo umount /media/SD/boot/
//重启
sudo reboot
//查看自己的节点信息,成功之后就会看到my_gpio节点,如下图效果
ls /sys/devices/platform/

全志H3-nanopi-duo2开发板GPIO驱动开发

4:编写驱动程序

4.1: 驱动代码内容

直接使用韦东山老师的课程led驱动源码,简单修改了一下下

驱动代码的编译步骤记录与我的上一篇文章

#include <linux/module.h>
#include <linux/platform_device.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>


/* 1. 确定主设备号                                                                 */
static int major = 0;
static struct class *led_class;
static struct gpio_desc *led_gpio;


/* 3. 实现对应的open/read/write等函数,填入file_operations结构体                   */
static ssize_t led_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}

/* write(fd, &val, 1); */
static ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
	int err;
	char status;
	
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	err = copy_from_user(&status, buf, 1);

	/* 根据次设备号和status控制LED */
	gpiod_set_value(led_gpio, status);
	
	return 1;
}

static int led_drv_open (struct inode *node, struct file *file)
{	
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	/* 根据次设备号初始化LED,输出模式,初始低电平 */
	gpiod_direction_output(led_gpio, 0);
	
	return 0;
}

static int led_drv_close (struct inode *node, struct file *file)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}

/* 定义自己的file_operations结构体                                              */
static struct file_operations led_drv = {
	.owner	 = THIS_MODULE,
	.open    = led_drv_open,
	.read    = led_drv_read,
	.write   = led_drv_write,
	.release = led_drv_close,
};

/* 4. 从platform_device获得GPIO
 *    把file_operations结构体告诉内核:注册驱动程序
 */
static int chip_demo_gpio_probe(struct platform_device *pdev)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

	/* 4.1 设备树中定义有: led-gpios=<...>;	*/
    led_gpio = gpiod_get(&pdev->dev, "mydvc", 0);
	if (IS_ERR(led_gpio)) {
		dev_err(&pdev->dev, "Failed to get GPIO for led\n");
		return PTR_ERR(led_gpio);
	}else{
        printk("get GPIO ");
    }
    
	/* 4.2 注册file_operations 	*/
	major = register_chrdev(0, "Gin_gpio", &led_drv);  /* /dev/led */

	led_class = class_create(THIS_MODULE, "Gin_gpio_class");
	if (IS_ERR(led_class)) {
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
		unregister_chrdev(major, "led");
		gpiod_put(led_gpio);
		return PTR_ERR(led_class);
	}

	device_create(led_class, NULL, MKDEV(major, 0), NULL, "Gin_gpio%d", 0); /* /dev/Gin_gpio */
        
    return 0;
    
}

static int chip_demo_gpio_remove(struct platform_device *pdev)
{
	device_destroy(led_class, MKDEV(major, 0));
	class_destroy(led_class);
	unregister_chrdev(major, "Gin_gpio");
	gpiod_put(led_gpio);
    
    return 0;
}


static const struct of_device_id Gin_gpio_dvc_id[] = {
    { .compatible = "gin,gpio" },
    { },
};

/* 1. 定义platform_driver */
static struct platform_driver chip_demo_gpio_driver = {
    .probe      = chip_demo_gpio_probe,
    .remove     = chip_demo_gpio_remove,
    .driver     = {
        .name   = "Gin_gpio",
        .of_match_table = Gin_gpio_dvc_id,
    },
};

/* 2. 在入口函数注册platform_driver */
static int __init led_init(void)
{
    int err;
    
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	
    err = platform_driver_register(&chip_demo_gpio_driver); 
	
	return err;
}

/* 3. 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函数
 *     卸载platform_driver
 */
static void __exit led_exit(void)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

    platform_driver_unregister(&chip_demo_gpio_driver);
}


/* 7. 其他完善:提供设备信息,自动创建设备节点*/

module_init(led_init);
module_exit(led_exit);

MODULE_LICENSE("GPL")

4.2:编译驱动模块

进入menuconfig ,找到自己的驱动,设置成M,模块方式编译
保存退出
make -j8 models
得到my_driver.ko
拷贝到开发板,安装驱动
sudo insmod my_driver.ko
安装成功之后,在/dev/下有Gin_gpio0设备

全志H3-nanopi-duo2开发板GPIO驱动开发

5: 应用测试程序

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>


void ctrl_gpio(int fd,int state){
    char status;
        /* 3. 写文件 */
    if (state)
    {
        status = 1;
        write(fd, &status, 1);
    }
    else
    {
        status = 0;
        write(fd, &status, 1);
    }
}

/*
 * ./ledtest /dev/100ask_led0 on
 * ./ledtest /dev/100ask_led0 off
 */
int main(int argc, char **argv)
{
    int fd;
    int count = 0;

    /* 1. 判断参数 */
    if (argc != 2)
    {
        printf("Usage: %s <dev> <on | off>\n", argv[0]);
        return -1;
    }

    /* 2. 打开文件 */
    fd = open(argv[1], O_RDWR);
    if (fd == -1)
    {
        printf("can not open file %s\n", argv[1]);
        return -1;
    }
    while (count++ < 10)
    {
        if((count % 2) == 0){
            ctrl_gpio(fd,1);
        }else{
            ctrl_gpio(fd,0);
        }
        sleep(2);
    }

    close(fd);

    return 0;
}

编译之后执行 ./test /dev/Gin_gpio0
效果就是PA11引脚拉高拉低文章来源地址https://www.toymoban.com/news/detail-446180.html

到了这里,关于全志H3-nanopi-duo2开发板GPIO驱动开发的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 全志V3S嵌入式驱动开发(触摸屏驱动)

    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】         所谓的触摸屏,其实就是在普通的lcd屏幕之上,再加一层屏而已。这个屏是透明的,这样客户就可以看到下面lcd屏幕的内容,另外一方面,通过触摸信号,还可以实现人和机器的自然

    2024年02月08日
    浏览(41)
  • 全志V3S嵌入式驱动开发(准备)

    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】         要学好嵌入式,其实最好自己可以画板子、调试板子、写软件、调试软件这样来学习。简单的51单片机、stm32这样的mcu或许画起来不是很复杂,但是如果是运行linux系统的soc芯片,那么

    2024年02月12日
    浏览(45)
  • 全志V3S嵌入式驱动开发(开发环境再升级)

    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】         前面我们陆陆续续开发了差不多有10个驱动,涉及到网口、串口、音频和视频等几个方面。但是整个开发的效率还是比较低的。每次开发调试的时候都很麻烦,譬如说,如果是驱动代码

    2024年02月08日
    浏览(59)
  • 全志F1C200S嵌入式驱动开发(串口驱动)

    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】         对于uboot、kernel和rootfs来说,他们的串口输出一般都是uart0。一般这么做,是没有问题的。只不过我们自己买的这块f1c200s电路板,设计者把uart转ttl的接口,改接到了uart1上面。不过这样

    2024年02月16日
    浏览(78)
  • 全志V3S嵌入式驱动开发(spi-nand驱动)

    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】         nand flash相信大家并不陌生,现在很多的固态硬盘上面,其实有很多的nand flash。只不过根据存储单元,分成slc、mlc和tlc三种。早在差不多20年前,那个时候大家还都是学习s3c2440,标准的

    2024年02月09日
    浏览(57)
  • 全志F1C200S嵌入式驱动开发(lcd屏幕驱动)

    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】         lcd RGB屏幕作为比较经济、实用的显示工具,在实际场景中使用较多。它的信号来说,一般也比较简单,除了常规的数据信号,剩下来就是行同步、场同步、数据使能和时钟信号了。数

    2024年02月14日
    浏览(46)
  • 荔枝派Zero(全志V3S)驱动开发之串口

    修改设备树打开 uart1 和 uart2,在 buildroot 移植 minicom 用来测试 uart1 和 uart2。 ①、查看 V3S 原理图,查看 uart1 和 uart2 对应的引脚 PE21 - UART1_TX PE22 - UART_RX PB0 - UART2_TX PB1 - UART2_RX ②、修改 sun8i-v3s.dtsi 在 linux 目录下 在 sun8i-v3s.dtsi 中添加 ③、修改 sun8i-v3s-licheepi-zero-dock.dts 在 lin

    2024年02月11日
    浏览(43)
  • 全志V3S嵌入式驱动开发(看原理图)

    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】         对于嵌入式软件开发的同学来说,你可能不一定要会自己画原理图、做pcb板。但是,别人已经设计好的原理图,自己还是要看得懂、读的明白的。此外,原理图无非就是各种符号放在

    2024年02月06日
    浏览(51)
  • 【全志V3s】SPI NAND Flash 驱动开发

    芯片:W25N01GVZEIG datasheet上的描述: SLC工艺 2KB*65536页 10万次擦写次数 焊好以后用CH341A读了一下 上面这张图描述了soc启动的四个顺序,分别是usb启动、sd卡启动、spi norflash启动、spi nandflash启动四种方式。前面的测试中一直走的是sd卡启动,但是从成本和稳定性上说,spi nandfla

    2024年02月07日
    浏览(49)
  • 全志V3S嵌入式驱动开发(u盘写读)

    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】         对于现在的soc来说,基本上usb是标配的。它一般需要支持usb host、device和otg三种模式。 简单解释下,host模式,就是v3s把自己当成了主机,其他设备都是从设备;device模式,相当于别人

    2024年02月09日
    浏览(61)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包