当前位置:网站首页>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;
}边栏推荐
- Multi level wavelet CNN for image restoration
- AI platform, AI midrange architecture
- Rongyun real-time community solution
- 今晚7:30 | 连界、将门、百度、碧桂园创投四位大佬眼中的AI世界,是继续高深还是回归商业本质?...
- Reproduce 20 character short domain name bypass and XSS related knowledge points
- How to solve the time zone problem in MySQL timestamp
- Notes on letter symbol marking of papers
- 【C】 Array
- Leetcode 1331 array sequence number conversion [map] the leetcode path of heroding
- 正则表达绕过waf
猜你喜欢

Pp-yoloe details

Multi level wavelet CNN for image restoration

Shardingsphere's level table practice (III)

for_ Example of each usage

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

How to solve the time zone problem in MySQL timestamp

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

最新二开版漫画小说听书三合一完整源码/整合免签接口/搭建教程/带采集接口

Calculation of array serial number of force deduction questions (daily question 7/28)

Score addition and subtraction of force deduction and brushing questions (one question per day 7/27)
随机推荐
深入C语言(2)——结构的定义与使用
(codeforce547)C-Mike and Foam(质因子+容斥原理)
Flask creation process day05-06 creation project
Functions and comparison of repeaters, hubs, bridges, switches and routers
通过递归实现多级联动
暴力递归到动态规划 01 (机器人移动)
How to solve the time zone problem in MySQL timestamp
Environment configuration stepping pit during colab use
JS regular expression finds the number of times a character (string) appears (one line of code)
Notes on letter symbol marking of papers
Does domestic ERP have a chance to beat sap?
Anti vulnerability · benefit from uncertainty --- management?
GJB common confused concepts
Excel拼接数据库语句
Arm architecture and neural network
Build redis environment under windows and Linux
Swing V2: towards a larger model with larger capacity and higher resolution
反脆弱·从不确定性中获益---管理?
Introduction and comparison of unicast, multicast (target broadcast, multicast), broadcast, flooding, flooding
makefile详解