基于STM32MP1的简单LED驱动程序
注意参考内核例程。
字符设备驱动程序框架。
1.确定主设备号;
2.定义自己的file_operations结构体;
3.实现对应的open、read、write等函数,填入file_operations结构体;
4.把file_operations告诉(注册)内核;register_chrdev;
5.入口函数,用来注册驱动程序,安装驱动程序时,会调用这个函数;
6.有入口函数就有出口函数;卸载驱动时,出口函数调用unregister_chrdev;
7.其他完善,提供设备信息,自动创建设备节点:class_create,device_create;
一、驱动
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/mutex.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <linux/device.h>static int major;
static struct class *led_class;/* 寄存器 */
//RCC PLL4 Control Register (RCC_PLL4CR) 0x50000000+0x894 //使能PLL4时钟
static volatile unsigned int *RCC_PLL4CR; //RCC_MP_AHB4ENSETR地址:0x50000000 + 0xA28 //使能GPIO
static volatile unsigned int *RCC_MP_AHB4ENSETR;//GPIOA_MODER地址:0x50002000 + 0x00,设置bit[21:20]=0b01, //PA10输出
static volatile unsigned int *GPIOA_MODER;//GPIOA_ODR地址: 0x50002000 + 0x14 //读寄存、修改值、写回去(低效)
static volatile unsigned int *GPIOA_ODR;//GPIOA_BSRR地址: 0x50002000 + 0x18 // 直接写寄存器,一次操作即可,高效
static volatile unsigned int *GPIOA_BSRR;static ssize_t led_write(struct file *filp, const char __user *buf,size_t count, loff_t *ppos)
{printk("%s %s %d\n",__FILE__, __FUNCTION__,__LINE__);char val;/* copy_from_user: 从应用程序中获取数据*/copy_from_user(&val, buf, 1);/* 设置数据,设置gpio输出,0/1 */if(val){ //灯亮*GPIOA_BSRR = (1<<26); //输出低电平 GPIOA10}else{//灯灭*GPIOA_BSRR = (1<<10); //输出高电平}return 1;
}static int led_open(struct inode *inode, struct file *filp)
{/* 配置gpio,使能、配置为gpio,配置输入输出 *///配置时钟*RCC_PLL4CR |= (1<<0);while((*RCC_PLL4CR & (1<<1)) == 0);//使能GPIOA*RCC_MP_AHB4ENSETR |= (1<<0);//设置PA10用作输出,先清零,在设置为输出*GPIOA_MODER &= ~(3<<20);*GPIOA_MODER |= (0x01<<20);return 0;
}static const struct file_operations led_fops = {.owner = THIS_MODULE,//.read = led_read,.write = led_write,.open = led_open,//.release = led_close,//.poll = led_poll,//.llseek = no_llseek,
};/* 入口函数 */
static int __init led_init(void)
{major = register_chrdev(0, "tanzhenwen_led", &led_fops); //在/proc/devices会显示if (major < 0) {printk("could not get major number\n");class_destroy(led_class);return major;}led_class = class_create(THIS_MODULE, "led_calss");//if (IS_ERR(led_class))// return PTR_ERR(led_class);device_create(led_class, NULL, MKDEV(major, 0), NULL, "led_drv"); // /dev/led_drv/* ioremap :使用虚拟地址,后期可以用虚拟地址来访问寄存器 *///ioremap(mem_addr, mem_len);//RCC PLL4 Control Register (RCC_PLL4CR) 0x50000000+0x894 //使能PLL4时钟RCC_PLL4CR = ioremap(0x50000000+0x894, 4); //RCC_MP_AHB4ENSETR地址:0x50000000 + 0xA28 //使能GPIORCC_MP_AHB4ENSETR = ioremap(0x50000000 + 0xA28, 4);//GPIOA_MODER地址:0x50002000 + 0x00,设置bit[21:20]=0b01, //PA10输出GPIOA_MODER = ioremap(0x50002000 + 0x00, 4);//GPIOA_ODR地址: 0x50002000 + 0x14 //读寄存、修改值、写回去(低效)GPIOA_ODR = ioremap(0x50002000 + 0x14, 4);;//GPIOA_BSRR地址: 0x50002000 + 0x18 // 直接写寄存器,一次操作即可,高效GPIOA_BSRR = ioremap(0x50002000 + 0x18, 4);return 0;
}static void __exit led_exit(void)
{iounmap(RCC_PLL4CR);iounmap(RCC_MP_AHB4ENSETR);iounmap(GPIOA_MODER);iounmap(GPIOA_ODR);iounmap(GPIOA_BSRR);unregister_chrdev(major, "tanzhenwen_led");device_destroy(led_class, MKDEV(major, 0));class_destroy(led_class);
}module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
二、测试程序
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>//ledtest /dev/led_drv on
//ledtest /dev/led_drv off
int main(int argc, char *argv[])
{int fd;char status = 0;if(argc != 3 ){printf("Usage: %s <dev> <on|off>\n",argv[0]);printf(" eg: %s /dev/led_drv on\n");printf(" eg: %s /dev/led_drv off\n");}//openfd = open(argv[1],O_RDWR);if(fd < 0){printf("can not open %s\n",argv[1]);return -1;}//writeif(strcmp(argv[2],"on") == 0){status = 1;}else{status = 0;}write(fd,&status,1);return 0;
}
三、测试
让心跳灯不闪烁
echo none > /sys/class/leds/heartbeat/trigger
cat /proc/devices可以看见tanzhenwen_led字符设备节点
执行ls /dev/led_drv -al,可以看见具有led_drv的设备。
执行./led_test /dev/led_drv off以及./led_test /dev/led_drv on可以观察到LED灯的亮灭。
基于STM32MP1的简单LED驱动程序相关推荐
- jz2440_基于平台设备的LED驱动程序
平台设备驱动程序是基于总线系统实现的,由三个部分组成: 总线,这里的总线使用的是内核自带的 platform_bus_type 总线,无需我们进行实现: 设备,这个驱动主要是对 LED 灯的操作,因此 ...
- 基于HDF的LED驱动程序开发(2)
引言 本文以小熊派BearPi-HM_Micro_small开发板上的一个LED灯为例,介绍如何基于HDF框架开发一个外设的驱动程序. 在阅读本文之前,建议大家先阅读:<OpenHarmony驱 ...
- 基于HDF的LED驱动程序开发(1)
引言 本文以小熊派BearPi-HM_Micro_small开发板上的一个LED灯为例,介绍如何基于HDF框架开发一个外设的驱动程序. 在阅读本文之前,建议大家先阅读:<OpenHarmony驱 ...
- Microwindows及基于Nano-X的简单程序开发
http://www.rdxx.com 05年09月13日 22:26 Blog.ChinaUnix.net Nano-X是一种图形编程接口,和Win32一样,在上面我们可以编写自己的应用程序,下面转 ...
- 【Linux笔记】LED驱动程序
前言 上一篇我们分享了字符设备驱动框架:[Linux笔记]驱动基础篇,当时分享的是hello驱动程序. 学STM32我们从点灯开始,学Linux驱动我们自然也要点个灯来玩玩,尽量在从这些基础例程中榨取 ...
- 基于74LS148的简单四路抢答器 Multisim
基于74LS148的简单四路有优先报警器 Multisim 上数电课的作业:假如有四个病房,四个病人的病情情况不同,分别对应优先级:最高.高.中.低.优先级低的会被优先级高得中断,此处用LED灯的亮灭 ...
- Yocto创建自己的分区(基于STM32MP1)
Yocto创建自己的分区(基于STM32MP1) 前几章节我们分析了machine class里面几篇关键的class,还有machine conf里面的inc文件,大致的创建分区的流程都比较清晰了, ...
- ARM开发(9)基于STM32的简单四则运算计算器
基于STM32的简单四则运算计算器 一 计算器原理: 1.1 本实验实现基于STM32的简单四则运算计算器 1.2 实验思路:理解计算器原理(按键扫描,字符实时显示,运算表达式计算,浮点数转字符串,字 ...
- 基于sys文件系统的LED驱动的移植【原创】
基于RK3188平台LED驱动程序的移植的移植.如有不正确之处,欢迎大家指点. 本文的LED驱动程序不是通过打开设备节点来访问和控制LED的,是通过sys文件系统来控制LED. 板子上有四盏灯以及对应 ...
最新文章
- 嵌入式程序员应知道的基本问题-C语言(zz)
- Java控制台如何输入一行、多行?
- Scala集合:List修改及删除数据
- java jni helloword_JNI学习一:编写HelloWorld程序
- Asp: 解决脚本输出网页出现乱码情况
- c# asp.net 2.0 tableadapter 动态 dynamic sql语句
- js三大系列之二scroll
- input美化上传按钮美化
- VS遍历windows文件夹的代码
- jq 如何获取和当然元素相同类名的标签_JS/JQ基于localStorage的本地数据储存指南...
- 虚幻airsim1:下载安装
- 基于RFM模型的Kmeans聚类算法实现
- rabbitmq版本升级
- 实例理解月末结账任务中,重估未结外币余额的原理
- Android程序的目录结构分析——manifests目录、Java目录、res目录
- 局域网-无法访问网上邻居解决方法
- 《考博英语词汇重难点20天冲刺》
- ant-design在 vue 抽屉(drawer)里面嵌套弹出框(modal)出现蒙层遮挡弹框问题
- SSL1232雷达覆盖(normal)
- rtx android,RTX 腾讯通 | im.qq.com
热门文章
- 四个高逼格技术简历制作技巧啦~
- 猎杀对决计算机丢失进不去,猎杀对决错误代码解决方法汇总 进不去游戏解决方法...
- 广告-信息流跨域ctr预估
- 东莞农商行再度申请港股上市:财务数据打架,多项业务违规曾被罚
- 【java】生成【PDF】后端接口-- java生成PDF的第二步
- Python中的递归【建议收藏】
- 50天50个前端小项目(纯html+css+js)第八天(形成波浪动画结合登录表单)
- 黑鲨游戏手机Helio在各大平台开启促销
- 手机c语言编辑emoji,Emojicode | 基于表情编程?
- 税控盘查看服务器设置的网站,税控盘系统参数设置服务器设置