博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux驱动:[1]LED驱动/dev/led
阅读量:4193 次
发布时间:2019-05-26

本文共 3434 字,大约阅读时间需要 11 分钟。

linux驱动:[1]LED驱动/dev/led

LED Linux驱动程序

测试平台:

代码一览(解析见下方)

驱动程序以及Makefile如下:

  • sun8i_opizero_led.c:
#include 
#include
#include
#include
#include
#include
static struct class *sun8i_opizero_led_class;//STATUS-LED:PA17#define PIO_BASE 0x1C20800volatile unsigned long *pacfg[4] = {NULL};volatile unsigned long *padat = NULL;static int sun8i_opizero_led_open(struct inode *inode, struct file *file){ //configure pa17 to output mode *pacfg[2] &= ~(3 << 5); return 0;}static ssize_t sun8i_opizero_led_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos){ int val; copy_from_user(&val, buf, count); if (val == 1) *padat |= (1 << 17); else *padat &= ~(1 << 17); return 0;}static struct file_operations sun8i_opizero_led_fops = { .owner = THIS_MODULE, .open = sun8i_opizero_led_open, .write = sun8i_opizero_led_write,};int major;int sun8i_opizero_led_init(void){ major = register_chrdev(0, "led", &sun8i_opizero_led_fops); sun8i_opizero_led_class = class_create(THIS_MODULE, "led"); device_create(sun8i_opizero_led_class, NULL, MKDEV(major, 0), NULL, "led"); pacfg[0] = (volatile unsigned long *)ioremap(PIO_BASE, 0x20); pacfg[1] = pacfg[0] + 1; pacfg[2] = pacfg[1] + 1; pacfg[3] = pacfg[2] + 1; padat = pacfg[3] + 1; return 0;}static void sun8i_opizero_led_exit(void){ unregister_chrdev(major, "led"); device_destroy(sun8i_opizero_led_class, MKDEV(major, 0)); class_destroy(sun8i_opizero_led_class); iounmap(pacfg[0]);}module_init(sun8i_opizero_led_init);module_exit(sun8i_opizero_led_exit);MODULE_DESCRIPTION("LED driver for Xunlong Orange Pi Zero");MODULE_AUTHOR("Techping Chan
");MODULE_LICENSE("GPL");MODULE_ALIAS("platform:orange-pi-zero-led");
  • Makefile:
obj-m := sun8i_opizero_led.o #编译进模块KERNELDIR := /lib/modules/3.4.113-sun8i/build #此处为linux内核库目录PWD := $(shell pwd) #获取当前目录OUTPUT := $(obj-m) $(obj-m:.o=.ko) $(obj-m:.o=.mod.o) $(obj-m:.o=.mod.c) modules.order Module.symversmodules:    $(MAKE) -C $(KERNELDIR) M=$(PWD) modulesclean:    rm -rf $(OUTPUT)

在shell中使用以下命令装载驱动程序:

$ make$ insmod sun8i_opizero_led.ko

使用linux c进行测试:

  • led_test.c:
#include 
#include
#include
#include
int main(int argc, char **argv){ int fd, val = 1; fd = open("/dev/led", O_RDWR); if (fd < 0) printf("can't open led device"); if (argc != 2) { printf("Usage:\n"); printf("%s
\n", argv[0]); return 1; } if (strcmp(argv[1], "on") == 0) val = 1; else val = 0; write(fd, &val, 4); return 0;}

进行编译、测试:

$ gcc -o led_test led_test.c$ ./led_test on$ ./led_test off

没问题,成功操作LED!


代码解析:

写Linux驱动程序的步骤无非是:

  1. 驱动框架

  2. 硬件操作

    • 看原理图
    • 看数据手册
    • 编写代码

这里编写的程序和单片机程序的区别就是:

单片机一般不具备MMU(内存管理单元),使用的是物理地址,而现在的SoC一般都带有MMU,使用虚拟地址。这时候我们就需要用Linux C库提供的 ioremap 函数去将物理地址映射为虚拟地址。

led_schematic

通过查看原理图,我们得知LED(STATUS-LED)接在PA17处。

pio_datasheet_0

Port Controller Register 的物理基地址为0x01C20800,在 sun8i_opizero_led.c 中使用:

pacfg[0] = (volatile unsigned long *)ioremap(PIO_BASE, 0x20);

把PA_CFG0、PA_CFG1、……PA_PUL1这0x20字节物理地址映射到pacfg[0]~(paccfg[0] + 8)。

之后的操作也是就跟操作单片机一样的位操作了。

pio_datasheet_1

static int sun8i_opizero_led_open(struct inode *inode, struct file *file){    //configure pa17 to output    *pacfg[2] &= ~(3 << 5);    return 0;}

pio_datasheet_2

if (val == 1)    *padat |= (1 << 17);else    *padat &= ~(1 << 17);

对硬件操作封装成固定的驱动程序框架格式,经过编译之后就可以注册到内核以待使用了。


  • 我的个人主页:
  • 我的个人站点博客:
  • 我的CSDN博客:
  • 我的简书:
  • 我的GitHub:
    欢迎相互follow~
你可能感兴趣的文章
仿基因编程原理导论(里面的几个重要的概念正在做修正,所以这只能算是一个原理的初稿。)
查看>>
node的 http-server 启动以后 浏览器访问有问题
查看>>
解决VS+QT无法自动生成moc文件的问题
查看>>
wpf image资源释放问题
查看>>
apache tomcat 安装配置
查看>>
eclipse maven创建一个普通java项目
查看>>
java 发送https post请求
查看>>
java 显示顶层提示窗口
查看>>
java PrintWriter输出中文乱码的解决
查看>>
eclipse maven项目生成war包
查看>>
XML Schema和DTD的区别
查看>>
java web 配置文件
查看>>
xml详解
查看>>
vue前端UI框架
查看>>
windows 使用bat增加环境变量
查看>>
idea 创建第一个web项目
查看>>
java中xml的解析
查看>>
http watch工具的使用
查看>>
验证码VerifyCode
查看>>
登录+验证码
查看>>