基于博通bcm2835芯片手册进行简单的树莓派引脚驱动
目录
1.配置寄存器
2.设置寄存器的地址
3.编写驱动代码
4.编写应用层代码
5.编译
6.测试
1.配置寄存器
我们要进行树莓派引脚的驱动就要对树莓派的引脚进行一些配置,比如我想把树莓派的某个 I/O 引脚置为高电平,那么我就需要对该引脚相关的寄存器进行配置:
- 这里以pin4为例,要把树莓派pin4 引脚配置成输出引脚需要配置 GPFSEL 这个寄存器(每个寄存器都是32位)
而pin4属于 GPFSEL0 这个寄存器 ,所以需要把 GPFSEL0 寄存器的14-12 位配置成 001
*GPFSEL0 &=~(0x6<<12); 把bit 13 -14 配置成0
*GPFSEL0 |=(0x1<<12); 把第12位配置成1
- 配置好输出引脚后,把输出引脚置为高电平需要配置 GPSET 这个寄存器
而pin4属于 GPSET0 这个寄存器 ,所以需要把 GPSET0 寄存器的第4位配置成 1
*GPSET0 |=0x1<<4;
- 把输出引脚置为低电平需要配置 GPCLR 这个寄存器
而pin4属于 GPCLR0 这个寄存器 ,所以需要把 GPCLR0 寄存器的第4位配置成 1
*GPSET0 |=0x1<<4;
2.设置寄存器的地址
由于bcm2835芯片手册给的地址是总线地址,但是上层并不能对这个地址进行访问
而我们在编写树莓派驱动程序的时候,IO空间的起始地址是0x3f000000,加上GPIO的偏移量0x2000000,所以GPIO的物理地址应该是从0x3f200000开始的。参考图中寄存器的偏移量得出我们选用的寄存器的物理地址是:
GPFSEL0 0x3f200000
GPSET0 0x3f20001c
GPCLR0 0x3f200028
然后在这个基础上进行Linux系统的MMU内存虚拟化管理,映射到虚拟地址上,这里用到了一个ioremap 的
函数将物理地址转成虚拟地址,这样上层就能访问的到了。
GPFSEL0=(volatile unsigned int *)ioremap(0x3f200000,4);
GPSET0 =(volatile unsigned int *)ioremap(0x3f20001C,4);
GPCLR0 =(volatile unsigned int *)ioremap(0x3f200028,4);
3.编写驱动代码
#include <linux/fs.h> //file_operations声明
#include <linux/module.h> //module_init module_exit声明
#include <linux/init.h> //__init __exit 宏定义声明
#include <linux/device.h> //class devise声明
#include <linux/uaccess.h> //copy_from_user 的头文件
#include <linux/types.h> //设备号 dev_t 类型声明
#include <asm/io.h> //ioremap iounmap的头文件static struct class *pin4_class;
static struct device *pin4_class_dev;static dev_t devno; //设备号
static int major =231; //主设备号
static int minor =0; //次设备号
static char *module_name="pin4"; //模块名volatile unsigned int* GPFSEL0=NULL; //volatile不会因编译器的优化而省略,每次直接读值
volatile unsigned int* GPSET0=NULL;
volatile unsigned int* GPCLR0=NULL;//led_open函数
static int pin4_open(struct inode *inode,struct file *file)
{printk("pin4_open\n"); //内核的打印函数和printf类似*GPFSEL0 &=~(0x6<<12); //0x6 0110左移12位 取反后1001与上 结果为把bit13-14配置成0*GPFSEL0 |=(0x1<<12); //由于不确定bit 12一定是1,所以还需把bit 12 配置成1return 0;
}//led_write函数
static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos)
{int userCmd;printk("pin4_write\n"); //内核的打印函数和printf类似copy_from_user(&userCmd,buf,count); //从上层获取函数的值第一个参数是一个char类型的指针const char __user *buf,用int也行if(userCmd==1){printk("set 1\n");*GPSET0 |=0x1<<4; //把第四引脚置一}else if(userCmd==0){printk("set 0\n");*GPCLR0 |=0x1<<4; //把第四引脚清零}else{printk("undo\n");}return 0;
}static struct file_operations pin4_fops = {.owner = THIS_MODULE,.open = pin4_open,.write = pin4_write,
};int __init pin4_drv_init(void)
{int ret;devno = MKDEV(major,minor); //创建设备号ret = register_chrdev(major, module_name,&pin4_fops); //注册驱动 告诉内核,把这个驱动加入到内核驱动的链表中pin4_class=class_create(THIS_MODULE,"myfirstdemo"); //让代码在dev下自动生成设备pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name); //创建设备文件GPFSEL0=(volatile unsigned int *)ioremap(0x3f200000,4); //第一个参数真正的物理地址,第二个参数映射的大小 一个寄存器4个字节 4*8=32 bitGPSET0=(volatile unsigned int*)ioremap(0x3f20001c,4); GPCLR0=(volatile unsigned int*)ioremap(0x3f200028,4);return 0;
}void __exit pin4_drv_exit(void)
{iounmap(GPFSEL0); //取消 ioremap 的映射iounmap(GPSET0);iounmap(GPCLR0);device_destroy(pin4_class,devno);class_destroy(pin4_class);unregister_chrdev(major, module_name); //卸载驱动}module_init(pin4_drv_init); //入口
module_exit(pin4_drv_exit);
MODULE_LICENSE("GPL v2");
4.编写应用层代码
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>int main()
{int fd;int cmd;fd=open("/dev/pin4",O_RDWR);if(fd < 0){printf("open failed\n");perror("reason:");}else{printf("succeed\n");}printf("输入 1/0 控制 pin4 输出");scnaf("%d",cmd);printf("%d\n",cmd);if(cmd==1){write(fd,&cmd,1);}else if(cmd == 0){write(fd,&cmd,1);}return 0;
}
5.编译
- 把写好的驱动代码(pin4_driver.c)放到源码树目录的 /drivers/char 目录下
- 修改Makefile (放在那个目录就在那个目录修改Makefile)
参考:树莓派驱动编译
6.测试
运行应用层代码,按下1时pin4引脚输出高电平
按下0时pin4引脚输出低电平
基于博通bcm2835芯片手册进行简单的树莓派引脚驱动相关推荐
- 树莓派学习笔记(十五)博通BCM2835芯片手册导读
树莓派3b的CPU型号为:BCM2835(ARM-cotexA53架构) CPU型号为2440.2410(ARM9架构) 编写驱动需要电路图(作用通过电路图找到寄存器).芯片手册 树莓派官网:http ...
- 树莓派 博通BCM2835芯片手册
手册提取链接 链接:https://pan.baidu.com/s/1fdmIBNn1Pr1j3-ercNhKJg 提取码:8y1b 驱动的两大利器: 1.电路图:通过电路图找到寄存器 2.芯片手册 ...
- 树莓派高级开发之树莓派博通BCM2835芯片手册导读与及“相关IO口驱动代码的编写”
首先我们要知道,驱动的两大利器:电路图(通过电路图去寻找寄存器)和芯片手册 一.寄存器的介绍 芯片手册第六章的89页,GPIO有41个寄存器,所有访问都是32位的.Description是寄存器的功能 ...
- 树莓派学习——博通BCM2835芯片手册导读、IO口驱动代码调试和测试学习
一.树莓派寄存器介绍: GPFSEL0 GPIO Function Select 0: 功能选择 输入/输出 GPSET0 GPIO Pin Output Set 0 : 输出0 GPSET1 GPI ...
- 树莓派——8、树莓派博通BCM2835芯片手册导读
(122条消息) 树莓派高阶课程7:树莓派博通BCM2835芯片手册导读_哒宰的自我修养的博客-CSDN博客 博通BCM2835芯片手册导读 驱动的两大利器: 电路图:通过电路图找到寄存器 芯片手册: ...
- 树莓派高阶课程7:树莓派博通BCM2835芯片手册导读
树莓派博通BCM2835芯片手册导读 驱动的两大利器: 电路图:通过电路图找到寄存器 芯片手册:进行编写 1.树莓派寄存器的介绍: GPFSEL0 GPIO Function Select 0: // ...
- 树莓派博通BCM2835芯片手册导读及io口驱动代码的实现
树莓派博通BCM2835芯片手册导读及io口驱动代码的实现 树莓派寄存器的介绍 寄存器地址问题 驱动代码的实现 在linux中生成树莓派所需要的的程序及实现现象 一.树莓派寄存器的介绍 GPFSEL0 ...
- 11.树莓派博通BCM2835芯片手册导读与IO口驱动代码调试和测试
11.树莓派博通BCM2835芯片手册导读与IO口驱动代码调试和测试 硬件地址的相关概念 总线地址 32位的操作系统 ,cpu最多只能访问2^32bit,即只能访问4G的内存 64位的操作系统 ,cp ...
- 树莓派博通BCM2835芯片手册导读
驱动两大利器︰电路图(通过电路图找寄存器)和芯片手册. 寄存器 芯片手册第六章P89∶ 字段名 描述 用法 GPFSEL0 GPIO Function select 0,功能选择输出/输入 以引脚9举 ...
最新文章
- Uva 10177 - (2/3/4)-D Sqr/Rects/Cubes/Boxes?
- 【知识星球】分组卷积最新进展,全自动学习的分组有哪些经典模型?
- AcWing 1402. 星空之夜 1月28
- Java|达梦工作笔记-达梦数据库同步工具(JDBC)
- ASP.NET自定义控件组件开发
- 让程序员崩溃的一句话。。。
- 一万小时定律的数学解释
- 【四阶龙格库塔法求解二元常微分方程组】
- 计算机的acpi高级电源选项配置,ACPI电源管理模式详解
- codeforces——962
- 自己的小程序修修补补
- 语音验证码接口PYTHO语言
- 最强计算机游戏,这可能是市面上体积最小性能最强的游戏主机了
- 应用性能管理APM巅峰对决:skywalking P.K. Pinpoint
- Essential Google Cloud Infrastructure: Foundation
- 3D音频理论研究(二)---3D全介绍(转)
- 软件测试工程师面试如何做好自我介绍?
- 微软开源人工智能工具和深度学习框架
- android studio 的 Gradle build finished with 1 error(s) 问题
- javaone_Java SE 9在JavaOne 2017上达到了Atari般的性能
热门文章
- 基于用户乘车行为大数据的客流分析及预测模型
- 李翊 先吞噬后反刍,擒贼擒王--java之我注六经之二
- 完美解决:Python3.10报错 No module named ‘_ssl‘
- vue打包出来的dist如何查看js的占比,report生成分析图
- 流媒体技术基础-流媒体服务与框架
- Idea插件开发(二)——插件的创建打包及发布
- c语言 txt文件数据,怎样用C语言从txt文件中读入数据?
- Java多线程编程:Callable、Future和FutureTask浅析(多线程编程之四)
- windows 注册表解析
- 仰望星空 ecnu