前言
本文记录的是基于S3C2440 的JZ2440 arm开发板所写的LED驱动
提示:以下是本篇文章正文内容,下面案例可供参考
一、前期工作
前面我已经发布了《第一个驱动程序》文章,已经把驱动的框架搭建好了,现在我在框架的基础上添加LED的硬件操作代码就可以了。
①看原理图——引脚
②看2440手册
③写代码
二、硬件
1.原理图
代码如下(示例):
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
2.S3C2440手册
先设置GPFCON寄存器为输出模式
然后根据原理图,将GPFDAT对应的位设置为0
三、驱动程序
1.LED驱动程序
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
static struct calss* leddrv_class;
static struct class_device *leddrv_class_dev;
volatile unsigned long *GPFCON = NULL;
volatile unsigned long *GPFDAT = NULL;
//open函数
static int led_drv_open(struct inode *inode, struct file *file) {
//printk("led_drv_open"); //打印信息
/* 配置GPF4,5,6为输出引脚 01 */
*GPFCON &= ~( (3 << 8) | (3 << 10) | (3 << 12) ); //先置0
*GPFCON |= ( (1 << 8) | (1 << 10) | (1 << 12) ); //后置1
return 0;
}
//write函数
static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {
int val;
copy_from_user(&val, buf, count); //从用户空间拷贝数据到内核空间
if(1 == val){
//点灯
*GPFDAT &= ~( (1<<4) | (1<<5) | (1<<6) );//置0
} else {
//灭灯
*GPFDAT |= (7 << 4);//置1
}
return 0;
}
//定义一个file_operations,里面成员放的是函数,对应起来
static const struct file_operations led_drv_fops = {
.owner = THIS_MODULE,
.open = led_drv_open,
.write = led_drv_write,
};
//系统自动帮我分配主设备号
int major;
//驱动程序的入口函数
static int led_drv_init(void) {
major = register_chrdev(0, "led_drv", &led_drv_fops); //注册驱动程序,告诉内核。
//先创建一个类
leddrv_class = class_create(THIS_MODULE, "leddrv");
//在类的里面建立设备
leddrv_class_dev = class_device_create(leddrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */ //参数:(主设备号是111,驱动程序名字为led_drv,file_operations的名字)
GPFCON = (volatile unsigned long *)ioremap(0x56000050, 16);
GPFDAT = GPFCON + 1;
return 0;
}
//驱动程序出口函数
static int led_drv_exit(void) {
unregister_chrdev(major, "led_drv"); //卸载驱动程序
class_device_unregister(leddrv_class_dev);
class_destroy(leddrv_class);
iounmap(GPFCON);
return 0;
}
//修饰入口函数
module_init(led_drv_init);
//修饰出口函数
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");
2.LED测试程序
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
int val;
int fd = open("/dev/xyz", O_RDWR);
if( fd < 0 ) {
printf("open xyz fail!\n");
}
if(argc != 2) {
printf("Usage :\n");
printf("%s <on|off>\n", argv[0]);
}
if(strcmp(argv[1], "on") == 0) {
val = 1;
} else {
val = 0;
}
write(fd, &val, sizeof(int));
return 0;
}
四、结果显示