开始编写LED驱动程序

  • 我之前学习了rk3288 的led驱动编写的准备
  • 然后也编写了led驱动的框架。
  • 现在只要把框架适当的填充具体的硬件操作,就可以实现led的电灯了。

1.需要用到的函数ioremap

因为linux内核并不像单片机一样是直接用寄存器地址控制的,操作系统有内存寻址的架构。所以我们需要把物理地址转换成Linux可以操作的地址。这个转换的过程就需要调用ioremap函数,下面的它的函数原型:

#include <asm/io.h>                //需要使用时包含头文件
void __iomen *ioremap(resource_size_t res_cookie, size_t size);
void iounmap(volatile void __iomen *cookie);/* virtual_addr = ioremap(physical_addr, size);* 把physical_addr开始的size映射为虚拟地址,返回值时该段虚拟地址的首地址。* physical_addr和size都会按页取整*/

2.firefly3288 led原理图

WORK_LED使用GPIO8_A1,POWER_LED使用GPIO8_A2。
这两个LED引脚在高电平时熄灭,低电平时点亮。

3.Led初始化步骤

  1. 使能GPIO对应的CRU控制器
    CRU_CLKGATE14_CON的b[8]位为0时使能,这里要注意31:16为时掩码位,必须把b[24]位设置为1。才能避免被屏蔽。
/* rk3288 GPIO8_A1 */
/* a. 使能 GPIO8
* set CRU to enable GPIO8
* CRU_CLKGATE14_CON 0xFF760000 + 0x198
* (1<<(8+16)) | (0<<8)
*/
  1. 设置GPIO可写,并且引脚用作GPIO功能
    设置GRF_GPIO8A_IOMUX的b[3:2]和b[4]为0,把GPIO_A1和GPIO_A2作为GPIO。同时b[19:18]和b[21:20]设置为0b11。
/* b. 设置 GPIO8_A1 用于 GPIO
* set PMU/GRF to configure GPIO8_A1 as GPIO
* GRF_GPIO8A_IOMUX 0xFF770000 + 0x0080
* bit[3:2] = 0b00
* (3<<(2+16)) | (0<<2)
*/
  1. 把对应的GPIO设置为输出
    设置 GPIO_SWPORTA_DDR 寄存器 b[1]为 1 b[2]为1,把 GPIO8_A1 和GPIO8_A2设置为输出引脚。
/* c. 设置 GPIO8_A1 作为 output 引脚
* set GPIO_SWPORTA_DDR to configure GPIO8_A1 as output
* GPIO_SWPORTA_DDR 0xFF7F0000 + 0x0004
* bit[1] = 0b1
*/
  1. 设置GPIO默认的电平为高电平
    设置 GPIO_SWPORTA_DR 寄存器 b[1]为 1,让 GPIO8_A1 输出高电平。
/* d. 设置 GPIO8_A1 输出高电平
* set GPIO_SWPORTA_DR to configure GPIO8_A1 output 1
* GPIO_SWPORTA_DR 0xFF7F0000 + 0x0000
* bit[1] = 0b1
*/
/* e. 设置 GPIO8_A1 输出低电平
* set GPIO_SWPORTA_DR to configure GPIO8_A1 output 0
* GPIO_SWPORTA_DR 0xFF7F0000 + 0x0000
* bit[1] = 0b0
*/

Led操作步骤

和上面第四步时一样的。

源码

Makefile

KERN_DIR = /home/book/Documents/100ask_firefly-rk3288/linux-4.4all:make -C $(KERN_DIR) M=`pwd` modules$(CROSS_COMPILE)gcc -o led_app led_app.c  -Wno-error=unused-but-set-variableclean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderrm -f hello_drv_testmyled_drv-y:=led_drv.o board_demoo.o
obj-m += myled_drv.o

led_drv.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/major.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>#include "led_ops.h"static int major = 0;
static struct class *led_class;
struct led_operations *p_led_ops;static int led_drv_open(struct inode *node, struct file *file)
{int minor = iminor(node);printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);p_led_ops->init(minor); return 0;
}static ssize_t led_drv_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{int err;char status;struct inode *inode = file_inode(file);int minor = iminor(inode);printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);err = copy_from_user(&status, buf, 1);printk("write status:%x \n", status);p_led_ops->ctl(minor, status);return 1;
}static int led_drv_close(struct inode *node, struct file *file)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}static struct file_operations led_drv = {.owner = THIS_MODULE,.open = led_drv_open,.read = led_drv_read,.write = led_drv_write,.release = led_drv_close,
};static int __init led_drv_init(void)
{int err;int i = 0;major = register_chrdev(0, "myled", &led_drv);led_class = class_create(THIS_MODULE, "led_class");err = PTR_ERR(led_class);if(IS_ERR(led_class)) {unregister_chrdev(major, "myled");    printk(KERN_WARNING "class creatge failed %d\n", err);return -1;}p_led_ops = get_board_led_ops();for(i=0;i<p_led_ops->num;i++)device_create(led_class, NULL, MKDEV(major, i), NULL, "myled%d", i);printk("%s %sled_drv_init\n", __FILE__, __FUNCTION__);return 0;
}static void __exit led_drv_exit(void)
{int i;printk("%s %sled_drv_exit\n", __FILE__, __FUNCTION__);for(i=0;i<p_led_ops->num;i++)device_destroy(led_class, MKDEV(major, i));class_destroy(led_class); unregister_chrdev(major, "myled");
}module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("chen");

board_demoo.c

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/io.h>#include "led_ops.h"#define CRU_BASE_PHY_ADDRESS   ((unsigned long)(0xff760000))
#define GRF_BASE_PHY_ADDRESS   ((unsigned long)(0xff770000))
#define GPIO8_BASE_PHY_ADDRESS ((unsigned long)(0xff7f0000))#define CRU_CLKGATE14_PHY_CON (0x0198)
#define GRF_GPIO8A_PHY_IOMUX  (0x0080)
#define GPIO_SWPORTA_PHY_DR   (0x0000)
#define GPIO_SWPORTA_PHY_DDR  (0x0004)static volatile unsigned int *CRU_CLKGATE14_CON;
static volatile unsigned int *GRF_GPIO8A_IOMUX;
static volatile unsigned int *GPIO8_SWPORTA_DDR;
static volatile unsigned int *GPIO8_SWPORTA_DR;static int board_demoo_led_init(int which)
{printk("%s %s line %d, led %d\n", __FILE__, __FUNCTION__, __LINE__, which);if(!CRU_CLKGATE14_CON) {CRU_CLKGATE14_CON = ioremap(CRU_BASE_PHY_ADDRESS + CRU_CLKGATE14_PHY_CON, 4);GRF_GPIO8A_IOMUX  = ioremap(GRF_BASE_PHY_ADDRESS + GRF_GPIO8A_PHY_IOMUX, 4);GPIO8_SWPORTA_DDR = ioremap(GPIO8_BASE_PHY_ADDRESS + GPIO_SWPORTA_PHY_DDR, 4);GPIO8_SWPORTA_DR  = ioremap(GPIO8_BASE_PHY_ADDRESS + GPIO_SWPORTA_PHY_DR, 4);}if(which == 0) {*CRU_CLKGATE14_CON = (1<<(8+16)) | (0<<8);*GRF_GPIO8A_IOMUX  |= (3<<(2+16)) | (0<<2);*GPIO8_SWPORTA_DDR |= (1<<1);} else if(which == 1) {*CRU_CLKGATE14_CON = (1<<(8+16)) | (0<<8);*GRF_GPIO8A_IOMUX  |= (3<<(4+16)) | (0<<4);*GPIO8_SWPORTA_DDR |= (1<<2);}return 0;
}static int board_demoo_led_ctl(int which, char status)
{printk("%s %s line %d, led %d, %s\n", __FILE__, __FUNCTION__, __LINE__, which, status?"on":"off");if(which == 0) {if(status) {     /* on: output 0 */*GPIO8_SWPORTA_DR &= ~(1<<1);} else {          /* off: output 1 */*GPIO8_SWPORTA_DR |= (1<<1);}} else if(which == 1) {if(status) {*GPIO8_SWPORTA_DR &= ~(1<<2);} else {*GPIO8_SWPORTA_DR |= (1<<2);}}return 0;
}static struct led_operations board_demoo_led_ops = {.num = 2,.init = board_demoo_led_init,.ctl  = board_demoo_led_ctl,
};struct led_operations *get_board_led_ops(void)
{return &board_demoo_led_ops;
}

led_ops.h

#ifndef __LED_OPS_H_
#define __LED_OPS_H_struct led_operations {int num;int (*init)(int which);          /* init led, which:led num  */int (*ctl)(int which, char status);       /* control led, whic:led num,status:0-On 1-Off */
};struct led_operations *get_board_led_ops(void);#endif

led_app.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>void showUsage(void)
{printf("app [dev_path] [on,off]\n");
}int main(int argc, char *argv[])
{char status;if(argc < 3) {showUsage();return -1;}int fd = open(argv[1], O_RDWR);if(fd < 0) {printf("app open device failed path:%s", argv[1]);return -1;}if(0 == strcmp(argv[2], "on")) {status = 1;int ret = write(fd, &status, 1);if(ret <= 0) {printf("app write device fialed %s",argv[2]);return -1;} else {printf("app write device %x", status);}} else if(0 == strcmp(argv[2], "off")) {status = 0;int ret = write(fd, &status, 1);if(ret <= 0) {printf("app write device fialed %s",argv[2]);return -1;} else {printf("app write device %x", status);}}return 0;
}

RK3288 LED驱动编写相关推荐

  1. RK3288 LED驱动编写准备

    3288LED驱动编写 1.LED硬件知识 2.GPIO的一般结构 3.普通的GPIO设置方法 4.GPIO寄存器的操作方法 5.3288的GPIO操作方法 5.1 怎么写LED驱动程序? 5.2 3 ...

  2. 树莓派LED驱动编写

    编写LED驱动前需要移植树莓派内核,以获得内核源码,内核移植相关方法请参照上一篇<树莓派3B内核移植>. 我们在编写驱动程序的时候,IO空间的起始地址是0x3f000000,加上GPIO的 ...

  3. Linux驱动_设备树下LED驱动

    前言 学习完设备树基础知识后,完成设备树下LED驱动实验 一.修改设备树文件 在设备书根/节点下添加子节点led信息: alphaled {status = "okay";comp ...

  4. linux驱动:二、LED灯驱动编写

    一.地址映射 在正式编写驱动前需要先简单了解一下 MMU 这个神器,MMU 全称叫做 Memory Manage Unit,也就是内存管理单元.在老版本的 Linux 中要求处理器必须有 MMU,但是 ...

  5. Linux驱动——LED驱动的编写与实验

    文章目录 1. LED驱动的原理分析 1.1 地址映射 1.1.1 ioremap函数 1.1.2 iounmap函数 1.2 I/O内存访问函数 1.3 读操作函数 1.4写操作函数 2. 硬件原理 ...

  6. 嵌入式驱动编写-点亮LED驱动程序

    在开发板上,有三个LED灯.如何通过应用程序点亮这三个灯如何编写驱动程序 操作硬件的时候,我们需要准备开发板的原理图和开发手册,,根据这两个文档来进行配置 在source insight 编写代码 1 ...

  7. ARM(IMX6U)裸机汇编LED驱动实验——驱动编写、编译链接起始地址、烧写bin文件到SD卡中并运行

    参考:Linux之ARM(IMX6U)裸机汇编LED驱动实验–驱动编写 作者:一只青木呀 发布时间: 2020-08-07 09:13:48 网址:https://blog.csdn.net/weix ...

  8. linux驱动编写--2--应用程序控制led闪烁

    本系列教程的上一篇:  linux驱动编写--1--点亮led 目标:编写一个驱动程序,实现上一篇没写的 "接口".并编写一个测试程序,透过驱动来控制led闪烁. 硬件:micro ...

  9. firefly-rk3288开发板Linux驱动——LED驱动

    本文主要介绍三个部分的内容:一.准备SDK源码 二.如何操作GPIO 三.LED设备驱动的实现.由于firefly官方一直在对源码进行更新,所以本文只以我正在用的版本介绍.此外,官方提供的下载工具版本 ...

最新文章

  1. 科技日报头版显要位置报道国内多家企业投融资给力永中软件
  2. 为什么焊锡老是粘在烙铁头上_自动焊锡机常见问题及解决方案「由力自动化」...
  3. 阿里云mysql 日志_mysql日志-阿里云开发者社区
  4. osx php7 imagick,[PHP] MacOS 自带php环境安装imagick扩展踩坑记录 | 码农部落
  5. Oracle 常用的一些函数
  6. ajax+lazyload时lazyload失效问题及解决
  7. python人像精细分割_人像抠图 - 发丝级人像分割 - 照片人物特效 - 极链科技
  8. Leetcod每日一题:151.reverse-words-in-a-string(翻转字符串里的单词)
  9. 加密芯片在汽车无钥匙启动行业的应用
  10. 协同过滤工具源码下载
  11. Faster R-CNN理论
  12. nodejs 下载url文件
  13. 阿里云域名注册及域名解析
  14. python实践周总结_Python 一周总结
  15. 后门防御阅读笔记,Black-box Detection of Backdoor Attacks with Limited Information and Data
  16. matlab trapz二重积分函数_「matlab 积分」使用Matlab求解定积分/不定积分 - seo实验室...
  17. matlab含未知数矩阵方程组,solve函数求解含有未知数的矩阵方程问题
  18. java自动生成word,java动态生成word解决方案
  19. 数据采集的方法有哪些
  20. 计算机考研【干货满满】:2021武汉理工计算机考研经验分享

热门文章

  1. 立法保护关键信息基础设施意义重大
  2. 衡水二中2021年高考成绩查询,2020衡水二中高考喜报
  3. 弱酸阳离子树脂去除硫酸锂溶液中的钙镁离子技术
  4. Android 插件化学习
  5. 未启用远程计算机的访问,技术员解决win10系统连接远程提示未启用对服务器的远程访问的技巧...
  6. SOC、SOPC、MPSOC、RFSOC、SDSOC的概念及区别
  7. Centos 7 系统修改终端背景为黑底白字
  8. 云计算架构自己的理解
  9. Zhong__Go随机密码生成器
  10. 【WLAN】【测试】如何使用MacBook进行WiFi无线空口抓包