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

橙色 网站app推广注册招代理

橙色 网站,app推广注册招代理,天津建设工程评标专家信息网,网站上线准备工作目录 一、Linux下LED灯驱动原理 1.地址映射 二、硬件原理图分析 三、实验程序编写 1.LED 灯驱动程序编写 2.编写测试APP 四、运行测试 1.编译驱动程序和测试APP (1)编译驱动程序 (2)编译测试APP 2.运行测试 一、Linux下…

目录

一、Linux下LED灯驱动原理

1.地址映射

二、硬件原理图分析

三、实验程序编写

1.LED 灯驱动程序编写

2.编写测试APP

四、运行测试

1.编译驱动程序和测试APP

(1)编译驱动程序

(2)编译测试APP

2.运行测试


一、Linux下LED灯驱动原理

        Linux 下的任何外设驱动,最终都是要配置相应的硬件寄存器。所以本章的LED 灯驱动最终也是对I.MX6ULL 的IO口进行配置,与裸机实验不同的是,在Linux 下编写驱动要符合Linux的驱动框架。I.MX6U-ALPHA 开发板上的LED 连接到I.MX6ULL 的GPIO1_IO03 这个引脚上,因此本章实验的重点就是编写Linux 下I.MX6UL引脚控制驱动。

1.地址映射

        MMU 全称叫做Memory Manage Unit,也就是内存管理单元。在老版本的Linux 中要求处理器必须有MMU,但是现在Linux 内核已经支持无MMU的处理器了。MMU主要完成的功能如下:

(1)完成虚拟空间到物理空间的映射

(2)内存保护,设置存储器的访问权限,设置虚拟存储空间的缓冲特性

        我们重点来看一下第(1)点,也就是虚拟空间到物理空间的映射,也叫做地址映射。首先了解两个地址概念:虚拟地址(VA,Virtual Address)、物理地址(PA,Physcical Address)。对于32 位的处理器来说,虚拟地址范围是2^32=4GB,我们的开发板上有512MB 的DDR3,这512MB 的内存就是物理内存,经过MMU 可以将其映射到整个4GB 的虚拟空间,如下图所示: 

        物理内存只有512MB,虚拟内存有4GB,那么肯定存在多个虚拟地址映射到同一个物理地址上去,虚拟地址范围比物理地址范围大的问题处理器自会处理。

        Linux 内核启动的时候会初始化MMU,设置好内存映射,设置好以后CPU 访问的都是虚拟地址。比如I.MX6ULL 的GPIO1_IO03 引脚的复用寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 的地址为0X020E0068。如果没有开启MMU 的话直接向0X020E0068 这个寄存器地址写入数据就可以配置GPIO1_IO03 的复用功能。现在开启了MMU,并且设置了内存映射,因此就不能直接向0X020E0068 这个地址写入数据了。我们必须得到0X020E0068 这个物理地址在Linux 系统里面对应的虚拟地址,这里就涉及到了物理内存和虚拟内存之间的转换,需要用到两个函数:ioremap 和iounmap

二、硬件原理图分析

        从上图可以看出,LED0 接到了GPIO_3 上,GPIO_3 就是GPIO1_IO03,当GPIO1_IO03输出低电平(0)的时候发光二极管LED0 就会导通点亮,当GPIO1_IO03 输出高电平(1)的时候发光二极管LED0 不会导通,因此LED0也就不会点亮。所以LED0 的亮灭取决于GPIO1_IO03的输出电平,输出0 就亮,输出1 就灭

三、实验程序编写

1.LED 灯驱动程序编写

        新建名为“2_led”文件夹,然后在2_led 文件夹里面创建VSCode 工程,工作区命名为“led”。工程创建好以后新建led.c 文件,此文件就是led 的驱动文件,在led.c 里面输入如下内容:

#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/io.h>#define LED_MAJOR 200 //主设备号
#define LED_NAME "led" //设备名字#define LEDOFF 0 //关灯
#define LEDON 1 //开灯//寄存器物理地址
#define CCM_CCGR1_BASE (0X020C406C)
#define SW_MUX_GPIO1_IO03_BASE (0X020E0068)
#define SW_PAD_GPIO1_IO03_BASE (0X020E02F4)
#define GPIO1_DR_BASE (0X0209C000)
#define GPIO1_GDIR_BASE (0X0209C004)//映射后的寄存器虚拟地址指针
static void __iomem *IMX6U_CCM_CCGR1;
static void __iomem *SW_MUX_GPIO1_IO03;
static void __iomem *SW_PAD_GPIO1_IO03;
static void __iomem *GPIO1_DR;
static void __iomem *GPIO1_GDIR;//LED打开/关闭
void led_switch(u8 sta)
{u32 val = 0;if(sta == LEDON){val = readl(GPIO1_DR);val &= ~(1 << 3);writel(val, GPIO1_DR);}else if(sta == LEDOFF){val = readl(GPIO1_DR);val |= (1 << 3);writel(val, GPIO1_DR);}
}
//打开设备
static int led_open(struct inode *inode, struct file *filp)
{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 retvalue;unsigned char databuf[1];unsigned char ledstat;retvalue = copy_from_user(databuf,buf,cnt);if(retvalue < 0){printk("kernel write failed!\r\n");return -EFAULT;}ledstat = databuf[0];//获取状态值if(ledstat == LEDON){led_switch(LEDON); //开灯}else if(ledstat == LEDOFF){led_switch(LEDOFF);//关灯}return 0;
}
//关闭/释放设备
static int led_release(struct inode *inode, struct file *filp)
{return 0;
}
//设备操作函数
static struct file_operations led_fops = {.owner = THIS_MODULE,.open = led_open,.read = led_read,.write = led_write,.release = led_release,
};
//驱动入口函数
static int __init led_init(void)
{int retvalue = 0;u32 val = 0;//初始化LED//1.寄存器地址映射IMX6U_CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4);GPIO1_DR = ioremap(GPIO1_DR_BASE, 4);GPIO1_GDIR = ioremap(GPIO1_GDIR_BASE, 4);//2.使能GPIO1时钟val = readl(IMX6U_CCM_CCGR1);val &= ~(3 << 26); //清楚以前的设置bit26, 27val |= (3 << 26); //设置新值bit26,27置1writel(val, IMX6U_CCM_CCGR1);//3.设置GPIO1_IO03的复用功能,将其复用为GPIO1_IO03,最后设置IO属性writel(5, SW_MUX_GPIO1_IO03);//寄存器SW_PAD_GPIO1_IO03 设置电气属性writel(0x10B0, SW_PAD_GPIO1_IO03);//4.设置GPIO_IO03为输出功能,因为用的IO03,所以左移3位val = readl(GPIO1_GDIR);val &= ~(1 << 3); //清楚以前的设置val |= (1 << 3); //bit3置1,设置为输出writel(val, GPIO1_GDIR);//5.默认关闭LED,设置第三位为1就是高点平关闭LEDval = readl(GPIO1_DR);val |= (1 << 3);      writel(val, GPIO1_DR);//6.注册字符设备驱动retvalue = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);if(retvalue < 0){printk("register chrdev failed!\r\n");return -EIO;}return 0;
}
//驱动出口函数
static int __exit led_exit(void)
{//取消映射iounmap(IMX6U_CCM_CCGR1);iounmap(SW_MUX_GPIO1_IO03);iounmap(SW_PAD_GPIO1_IO03);iounmap(GPIO1_DR);iounmap(GPIO1_GDIR);//注销设备驱动unregister_chrdev(LED_MAJOR, LED_NAME);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ssz");

2.编写测试APP

        编写测试APP,led 驱动加载成功以后手动创建/dev/led 节点,应用APP 通过操作/dev/led文件来完成对LED 设备的控制。向/dev/led 文件写0 表示关闭LED 灯,写1 表示打开LED 灯。新建ledApp.c 文件,在里面输入如下内容:

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"#define LEDOFF 0
#define LEDON 1int main(int argc, char *argv[])
{int fd, retvalue;char *filename;unsigned char databuf[1];if(argc != 3){printf("Error Usage!\r\n");return -1;}filename = argv[1];//打开led驱动fd = open(filename, O_RDWR);if(fd < 0){printf("filr %s open failed!\r\n", argv[1]);return -1;}databuf[0] = atoi(argv[2]);//向/dev/led文件写入数据retvalue = write(fd, databuf, sizeof(databuf));if(retvalue < 0){printf("LED Control Failed!\r\n");close(fd);return -1;}retvalue = close(fd); //关闭文件if(retvalue < 0){printf("fail %s close failed!\r\n",argv[1]);return -1;}return 0;
}

四、运行测试

1.编译驱动程序和测试APP

(1)编译驱动程序

编写Makefile 文件如下:

KERNELDIR := /home/ssz/linux/IMX6ULL/linux/temp/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
CURRENT_PATH := $(shell pwd)
obj-m := led.obuild : kernel_moduleskernel_modules:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

输入如下命令编译出驱动模块文件:

(2)编译测试APP
arm-linux-gnueabihf-gcc ledApp.c -o ledApp

2.运行测试

        将上一小节编译出来的led.ko 和ledApp 这两个文件拷贝到rootfs/lib/modules/4.1.15 目录中,重启开发板,进入到目录lib/modules/4.1.15 中,输入如下命令加载led.ko 驱动模块:

        驱动加载成功以后创建“/dev/led”设备节点,命令如下:

        驱动节点创建成功以后就可以使用ledApp 软件来测试驱动是否工作正常,输入如下命令打开LED 灯:

        输入上述命令以后观察I.MX6U-ALPHA 开发板上的红色LED 灯是否点亮,如果点亮的话说明驱动工作正常。在输入如下命令关闭LED 灯:

        如果要卸载驱动的话输入如下命令即可:

http://www.hkea.cn/news/801278/

相关文章:

  • 上海网站seo公司网页推广平台
  • 网站服务器租用价格表百度怎么发布自己的广告
  • 经纪人做网站技巧搜索引擎入口yandex
  • 教育网站制作哪家服务好全球外贸采购网
  • 响应式网络网站源码百度关键词查询网站
  • 南京网站制作设计公司网络运营团队
  • 阿里巴巴上怎样做自己的网站seo网站优化网站编辑招聘
  • 网站做付费推广都需要问什么网络热词2022
  • 给男票做网站表白的软件产品市场推广计划书
  • 西安网站制作定制怎么制作自己的个人网站
  • wordpress 如何移动端盐城seo优化
  • asp.net 制作网站开发百度竞价排名软件
  • 百度爱采购推广平台天津网络推广seo
  • 福州市闽侯县建设局网站推广引流吸引人的文案
  • wordpress目录 读写权限泰安短视频seo
  • 东莞建设网站流程澎湃新闻
  • 萧县住房和城乡建设局网站seo排名推广工具
  • 企业网站php模板下载百度百科官网首页
  • 做愛視頻网站在线网页制作网站
  • 织梦pc怎么做手机网站搜索引擎优化的基础是什么
  • 课程建设网站设计源码爱站网反链查询
  • 安徽省建设业协会网站个人网页制作教程
  • 好的摄影网站推荐福州seo顾问
  • html做的好看的网站如何宣传推广产品
  • 微信手机网站制作怎么引流客源最好的方法
  • 宿州建设网站公司前端seo搜索引擎优化
  • 做王境泽表情的网站百度seo关键词优化排名
  • 怎么选择无锡网站建设虚拟主机搭建网站
  • 做原油期货关注什么网站搜索引擎优化是做什么
  • 微信小程序怎么制作游戏安卓优化清理大师