当前位置:网站首页>I.MX6U-驱动开发-2-LED驱动
I.MX6U-驱动开发-2-LED驱动
2022-07-29 03:32:00 【重邮研究森】
1.地址映射
Linux驱动开发可以操作寄存器,但不能直接对寄存器物理地址进行读写(裸机可以),因为linux会使能MMU。
Linux下操作的是虚拟地址,需要先把物理地址转为虚拟地址,使用方法为:
ioremap:从物理地址转为虚拟地址 虚拟地址=ioremap(物理地址,大小)

iounmap:iounmap(虚拟地址)

2.led驱动框架搭建
包括注册函数,注销函数,file_operations结构体(owner,open,release,write)
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#define LED_MAJOR 200
#define LED_NAME "led"
static int led_open(struct inode *inode, struct file *filp)
{
return 0;
}
static int led_release(struct inode *inode,struct file *filp)
{
return 0;
}
static ssize_t led_write(struct file *filp, const char __user *buf,size_t count, loff_t *ppos)
{
return 0;
}
static const struct file_operations led_fops={
.owner=THIS_MODULE,
.write=led_write,
.open=led_open,
.release=led_release,
};
//注册
static int __init led_init(void)
{
int ret=0;
/*1.注册字符设备*/
ret=register_chrdev(LED_MAJOR,LED_NAME,&led_fops);
if(ret<0)
{
printk("register fail\r\n");
return -EIO;
}
printk("led_init\r\n");
return 0;
}
//卸载
static void __exit led_exit(void)
{
/*注销字符设备*/
unregister_chrdev(LED_MAJOR,LED_NAME);
printk("led_exit\r\n");
}
/*注册驱动和卸载驱动*/
module_init(led_init);
module_exit(led_exit);
//license
MODULE_LICENSE("GPL");
MODULE_AUTHOR("liujiasen");3.驱动程序编写
1.初始化led的IO(使能时钟,IO复用,电气属性,输入输出设置)
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#define LED_MAJOR 200
#define LED_NAME "led"
//寄存器物理地址
#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;
#define LEDOFF 0
#define LEDON 1
//led 打开和关闭
void led_switch(u8 sta)
{
u32 val=0;
if(sta==LEDON)
{
val=readl(GPIO1_DR);//读取寄存器的值
val &=~(1<<3);//把bit3值为0 打开led
writel(val,GPIO1_DR);
}
else
{
//close led
val=readl(GPIO1_DR);//读取寄存器的值
val |=(1<<3);//把bit3值为0 close led
writel(val,GPIO1_DR);
}
}
static int led_open(struct inode *inode, struct file *filp)
{
return 0;
}
static int led_release(struct inode *inode,struct file *filp)
{
return 0;
}
static ssize_t led_write(struct file *filp, const char __user *buf,size_t count, loff_t *ppos)
{
int retvalue;
unsigned char databuf[1];
retvalue=copy_from_user(databuf,buf,count);
if(retvalue<0)
{
printk("kernel write fail\r\n");
return -EFAULT;
}
//判断开灯还是关灯
led_switch(databuf[0]);
return 0;
}
static const struct file_operations led_fops={
.owner=THIS_MODULE,
.write=led_write,
.open=led_open,
.release=led_release,
};
//注册
static int __init led_init(void)
{
int ret=0;
unsigned int val=0;
/*1.初始化LED灯 地址映射*/
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.初始化LED灯 时钟*/
val=readl(IMX6U_CCM_CCGR1);//读取寄存器的值
val &=~(3<<26);//把26,27值为0
val |=3<<26;//把26,27值为1
writel(val,IMX6U_CCM_CCGR1);//把值写入寄存器
/*复用*/
writel(5, SW_MUX_GPIO1_IO03);
/*电器属性*/
writel(0x10B0, SW_PAD_GPIO1_IO03);
/*GPIO输入输出*/
val = readl(GPIO1_GDIR);
val &= ~(1 << 3); /* 清除以前的设置 */
val |= (1 << 3); /* 设置为输出 */
writel(val, GPIO1_GDIR);
/*莫认为高点平输出点亮led*/
val=readl(GPIO1_DR);//读取寄存器的值
val &=~(1<<3);//把bit3值为0 打开led
writel(val,GPIO1_DR);
/*1.注册字符设备*/
ret=register_chrdev(LED_MAJOR,LED_NAME,&led_fops);
if(ret<0)
{
printk("register fail\r\n");
return -EIO;
}
printk("led_init\r\n");
return 0;
}
//卸载
static void __exit led_exit(void)
{
unsigned int val=0;
//close led
val=readl(GPIO1_DR);//读取寄存器的值
val |=(1<<3);//把bit3值为0 close led
writel(val,GPIO1_DR);
/*取消地址映射*/
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);
printk("led_exit\r\n");
}
/*注册驱动和卸载驱动*/
module_init(led_init);
module_exit(led_exit);
//license
MODULE_LICENSE("GPL");
MODULE_AUTHOR("liujiasen");2.进行测试
通过注册和注销点亮和关闭led
4.应用程序编写
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
/*
ledAPP <filename> <0:1> 1:open 2close
*/
//应用程序参数个数,传入的具体参数内容,格式为字符串
int main(int argc,char *argv[])
{
int ret=0;
int fd=0;
unsigned char databuf[1];
char *filename;
char readbuf[100],writebuf[100];
static char usrdata[]={"usr data!"};
if(argc!=3)
{
printf("Eroor usage\r\n");
return -1;
}
filename=argv[1];
//RDWR具有读写
fd=open(filename,O_RDWR);
if(fd<0){
printf("can't open file %s\r\n",filename);
return -1;
}
databuf[0]=atoi(argv[2]);
ret=write(fd,databuf,sizeof(databuf));
if(ret<0)
{
printf("write fail\r\n");
close(fd);
return -1;
}
close(fd);
return 0;
}边栏推荐
- Shardingsphere's level table practice (III)
- Simple code implementation of decision tree
- ROS - create workspace
- Easy to use remote sensing data set download website~~~
- Ten thousand words detailed Google play online application standard package format AAB
- Asynchronous callback future mode of concurrent mode
- Photo scale correction tool: DxO viewpoint 3 direct mount version
- KNN method predicts pregnancy, KNN principle simple code
- Microcomputer principle operation
- The difference between /g /m /i of JS regular expressions
猜你喜欢

04 | background login: login method based on account and password (Part 1)

Rongyun real-time community solution

Summary of basic knowledge points of C language

【C】 Array

(2022杭电多校三)1002-Boss Rush(状压DP+二分)
![LeetCode 1331 数组序号转换[Map] HERODING的LeetCode之路](/img/be/d429d0c437dc5ed7cb4448e223a83a.png)
LeetCode 1331 数组序号转换[Map] HERODING的LeetCode之路

2022-07-28 study notes of group 4 self-cultivation class (every day)

Use of leak scanning (vulnerability scanning) tool burpsuite or burp Suite (with installation and installation package download of burpsuite+1.7.26)

Practical guidance for interface automation testing (Part I): what preparations should be made for interface automation

Mathematical modeling -- analytic hierarchy process model
随机推荐
Self study notes on Apache file management -- mapping folders and configuring Apache virtual machines based on single IP and multi domain names
Tencent cloud logs in with PEM
Matlab learning - accumulation of small knowledge points
Sleuth+Zipkin 来进行分布式服务链路的追踪
Summary of basic knowledge points of C language
Does domestic ERP have a chance to beat sap?
Tonight at 7:30 | is the AI world in the eyes of Lianjie, Jiangmen, Baidu and country garden venture capital continue to be advanced or return to the essence of business
How does DataGrid export and recover the entire database data, using a single SQL file
Instance setup flask service (simple version)
Mathematical modeling -- analytic hierarchy process model
Multi level wavelet CNN for image restoration
Machine learning [numpy]
Exness: dove resolution helped gold rebound, and the focus turned to U.S. GDP
1.6 example: cifar-10 classification
Score addition and subtraction of force deduction and brushing questions (one question per day 7/27)
How to judge stun protocol
Pp-yoloe details
How close can QA be to business code Direct exposure of defects through codediff
The Federal Reserve raised interest rates again, Powell "let go of doves" at 75 basis points, and US stocks reveled
Anaconda offline installation environment