当前位置: 首页 > wzjs >正文

网站头部导航在家有电脑怎么做网站

网站头部导航,在家有电脑怎么做网站,长沙网站制作公司怎么做,官方网站下载免费appLinux LED驱动(设备树) 之前的LED驱动直接在驱动文件中定义有关寄存器物理地址,然后使用io_remap函数进行内存映射,得到对应的虚拟地址,最后操作寄存器对应的虚拟地址完成对GPIO的初始化。 但也可以先在设备树文件中创…

Linux LED驱动(设备树)

之前的LED驱动直接在驱动文件中定义有关寄存器物理地址,然后使用io_remap函数进行内存映射,得到对应的虚拟地址,最后操作寄存器对应的虚拟地址完成对GPIO的初始化。
但也可以先在设备树文件中创建相应的设备节点,再使用设备树向Linux内核传递相关的寄存器物理地址,再使用OF函数从设备树中获取所需的属性值,完成驱动程序的编写。

0. 设备树

	led{compatible = "alientek,led";status = "okay";default-state = "on";reg = < 0xE000A040 0x40xE000A204 0x40xE000A208 0x40xE000A214 0x40xF800012C 0x4>;}

1. 根据设备树编写驱动

  1. 定义设备结构体
    设备结构体包含cdev、类、设备、设备号等。
  2. 实现开关读写4个系统调用函数
    在文件打开函数中使用filp->private_data设置私有数据;使用copy_from_user()实现用户空间和内存空间数据交互,并使用readl()函数读取寄存器映射后的虚拟地址的数据,使用writel()函数根据寄存器映射后的虚拟地址将数据写入寄存器,从而实现文件写函数(LED的亮灭)。
  3. 初始化设备操作函数结构体
  4. 实现设备注册和注销函数
    使用of_find_node_by_path(“/led”)函数led设备节点,使用of_property_read_string()函数读取status属性,使用of_property_read_string()函数获取compatible属性值并进行匹配,与直接使用ioremap()根据物理地址映射虚拟地址不同,这里使用of_iomap()函数获取从设备树节点获取寄存器地址进行内存映射,然后使能GPIO、关闭中断、设置方向,使用register_chrdev_region()函数、alloc_chrdev_region()函数创建设备号,并使用module_init()函数指定设别注册函数实现insmod,使用cdev_init()初始化cdev,使用cdev_add()添加cdev,使用class_create()创建类,使用device_create()创建设备;使用device_destroy()注销设备,使用class_destroy()注销类,使用cdev_del()删除cdev,使用unregister_chrdev_region()注销设备号,使用led_iounmap()取消地址映射,并使用module_exit()函数指定设备注销函数实现rmmod。
  5. 添加LICENSE和作者
    使用MODULE_LICENSE()函数和MODULE_AUTHOR()函数添加LICENSE和作者。
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/of.h>
#include <linux/of_address.h>#define DTSLED_CNT		1				/* 设备号个数 */
#define DTSLED_NAME		"dtsled"		/* 名字 *//* 映射后的寄存器虚拟地址指针 */
static void __iomem *data_addr;
static void __iomem *dirm_addr;
static void __iomem *outen_addr;
static void __iomem *intdis_addr;
static void __iomem *aper_clk_ctrl_addr;// 0. **定义设备结构体**
/* dtsled设备结构体 */
struct dtsled_dev {dev_t devid;			/* 设备号 */struct cdev cdev;		/* cdev */struct class *class;	/* 类 */struct device *device;	/* 设备 */int major;				/* 主设备号 */int minor;				/* 次设备号 */struct device_node *nd;	/* 设备节点 */
};static struct dtsled_dev dtsled;	/* led设备 */// 1. **实现开关读写4个系统调用函数**
static int led_open(struct inode *inode, struct file *filp)
{filp->private_data = &dtsled;	/* 设置私有数据 */return 0;
}static ssize_t led_read(struct file *filp, char __user *buf,size_t cnt, loff_t *offt)
{return 0;
}static ssize_t led_write(struct file *filp, const char __user *buf,size_t cnt, loff_t *offt)
{int ret;int val;char kern_buf[1];ret = copy_from_user(kern_buf, buf, cnt);	// 得到应用层传递过来的数据if(0 > ret) {printk(KERN_ERR "kernel write failed!\r\n");return -EFAULT;}val = readl(data_addr);if (0 == kern_buf[0])val &= ~(0x1U << 7);		// 如果传递过来的数据是0则关闭ledelse if (1 == kern_buf[0])val |= (0x1U << 7);			// 如果传递过来的数据是1则点亮ledwritel(val, data_addr);return 0;
}static int led_release(struct inode *inode, struct file *filp)
{return 0;
}// 2. **初始化设备操作函数结构体**
static struct file_operations dtsled_fops = {.owner		= THIS_MODULE,.open		= led_open,.read		= led_read,.write		= led_write,.release	= led_release,
};// 3. **实现设备注册和注销函数**
static inline void led_ioremap(void)
{data_addr = of_iomap(dtsled.nd, 0);dirm_addr = of_iomap(dtsled.nd, 1);outen_addr = of_iomap(dtsled.nd, 2);intdis_addr = of_iomap(dtsled.nd, 3);aper_clk_ctrl_addr = of_iomap(dtsled.nd, 4);
}static inline void led_iounmap(void)
{iounmap(data_addr);iounmap(dirm_addr);iounmap(outen_addr);iounmap(intdis_addr);iounmap(aper_clk_ctrl_addr);
}static int __init led_init(void)
{const char *str;u32 val;int ret;/* 1.获取led设备节点 */dtsled.nd = of_find_node_by_path("/led");if(NULL == dtsled.nd) {printk(KERN_ERR "led node can not found!\r\n");return -EINVAL;}/* 2.读取status属性 */ret = of_property_read_string(dtsled.nd, "status", &str);if(!ret) {if (strcmp(str, "okay"))return -EINVAL;}/* 2、获取compatible属性值并进行匹配 */ret = of_property_read_string(dtsled.nd, "compatible", &str);if(0 > ret)return -EINVAL;if (strcmp(str, "alientek,led"))return -EINVAL;printk(KERN_ERR "led device matching successful!\r\n");/* 4.寄存器地址映射 */led_ioremap();/* 5.使能GPIO时钟 */val = readl(aper_clk_ctrl_addr);val |= (0x1U << 22);writel(val, aper_clk_ctrl_addr);/* 6.关闭中断功能 */val |= (0x1U << 7);writel(val, intdis_addr);/* 7.设置GPIO为输出功能 */val = readl(dirm_addr);val |= (0x1U << 7);writel(val, dirm_addr);/* 8.使能GPIO输出功能 */val = readl(outen_addr);val |= (0x1U << 7);writel(val, outen_addr);/* 9.初始化LED的默认状态 */val = readl(data_addr);ret = of_property_read_string(dtsled.nd, "default-state", &str);if(!ret) {if (!strcmp(str, "on"))val |= (0x1U << 7);elseval &= ~(0x1U << 7);} elseval &= ~(0x1U << 7);writel(val, data_addr);/* 10.注册字符设备驱动 *//* 创建设备号 */if (dtsled.major) {dtsled.devid = MKDEV(dtsled.major, 0);ret = register_chrdev_region(dtsled.devid, DTSLED_CNT, DTSLED_NAME);if (ret)goto out1;} else {ret = alloc_chrdev_region(&dtsled.devid, 0, DTSLED_CNT, DTSLED_NAME);if (ret)goto out1;dtsled.major = MAJOR(dtsled.devid);dtsled.minor = MINOR(dtsled.devid);}printk("dtsled major=%d,minor=%d\r\n",dtsled.major, dtsled.minor); /* 初始化cdev */dtsled.cdev.owner = THIS_MODULE;cdev_init(&dtsled.cdev, &dtsled_fops);/* 添加一个cdev */ret = cdev_add(&dtsled.cdev, dtsled.devid, DTSLED_CNT);if (ret)goto out2;/* 创建类 */dtsled.class = class_create(THIS_MODULE, DTSLED_NAME);if (IS_ERR(dtsled.class)) {ret = PTR_ERR(dtsled.class);goto out3;}/* 创建设备 */dtsled.device = device_create(dtsled.class, NULL,dtsled.devid, NULL, DTSLED_NAME);if (IS_ERR(dtsled.device)) {ret = PTR_ERR(dtsled.device);goto out4;}return 0;out4:class_destroy(dtsled.class);out3:cdev_del(&dtsled.cdev);out2:unregister_chrdev_region(dtsled.devid, DTSLED_CNT);out1:led_iounmap();return ret;
}static void __exit led_exit(void)
{/* 注销设备 */device_destroy(dtsled.class, dtsled.devid);/* 注销类 */class_destroy(dtsled.class);/* 删除cdev */cdev_del(&dtsled.cdev);/* 注销设备号 */unregister_chrdev_region(dtsled.devid, DTSLED_CNT);/* 取消地址映射 */led_iounmap();
}/* 驱动模块入口和出口函数注册 */
module_init(led_init);
module_exit(led_exit);MODULE_AUTHOR("DengTao <773904075@qq.com>");
MODULE_DESCRIPTION("Alientek ZYNQ GPIO LED Driver");
MODULE_LICENSE("GPL");

应用程序:

  1. 打开文件
  2. 将字符串转为数据,并将数据写入文件(开关LED)
  3. 关闭文件
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>/** @description		: main主程序* @param - argc	: argv数组元素个数* @param - argv	: 具体参数* @return			: 0 成功;其他 失败*/
int main(int argc, char *argv[])
{int fd, ret;unsigned char buf[1];if(3 != argc) {printf("Usage:\n""\t./ledApp /dev/led 1		@ close LED\n""\t./ledApp /dev/led 0		@ open LED\n");return -1;}/* 打开设备 */fd = open(argv[1], O_RDWR);if(0 > fd) {printf("file %s open failed!\r\n", argv[1]);return -1;}/* 将字符串转换为int型数据 */buf[0] = atoi(argv[2]);/* 向驱动写入数据 */ret = write(fd, buf, sizeof(buf));if(0 > ret){printf("LED Control Failed!\r\n");close(fd);return -1;}/* 关闭设备 */close(fd);return 0;
}
http://www.dtcms.com/wzjs/795136.html

相关文章:

  • 可视化网站制作软件大学生个人简历电子版模板
  • 新乡网站建设-中国互联工业设计出来做什么
  • 好享购物官方网站购物竞价推广外包托管
  • 建网站卖饮料做网站编程
  • 服装生产厂商网站建设方案南宁网站建设设计
  • 给网站写文章怎么做贵阳seo网站推广
  • 网站定位分析是什么wordpress如何添加注册登录界面
  • 一个网站一年多少钱江西网站开发方案
  • 广西桂林建设局网站前端网页代码
  • 浙江高端网站建设网站建设兼职挣多少钱
  • 什么网站专做宠物物品wordpress+软件+入门
  • 长沙做公司网站大概多少钱网站如何做免费推广
  • 如何判断一个网站的价值毕业设计做音乐网站可以吗
  • 深圳团购网站建设PS做网站报价
  • 用墨刀做视频网站家装品牌排行榜前十名
  • 效果图哪个网站好页面设计时最好
  • 阳泉网站开发天津建设银行招聘网站
  • 网站建设后台程序用什么语言wordpress 升级提示
  • 静态网站模板中英文环翠区网站建设
  • 漳州城乡建设局网站首页图片如何连接到wordpress
  • 国家对网站建设政策网站制作的总结与体会
  • 网站不被收录了wordpress发布站点
  • 网站建设广告语郑州seo询搜点网络效果佳
  • 免费教做面食的网站烟台企业自助建站系统
  • 设计师做单页的网站中英企业网站系统
  • 天津南开做网站做公司网站要钱吗
  • 做电脑网站用什么软件有哪些方面优化设计的答案
  • 优秀网站大全网站首页快照应该怎么
  • 网站建设一般用什么编程wordpress站点标题添加
  • 国外做连接器平台网站如何把物流做免费网站