目录

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属于 GPCLR​​​​​​​0 这个寄存器 所以需要把 GPCLR​​​​​​​0 寄存器的第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芯片手册进行简单的树莓派引脚驱动相关推荐

  1. 树莓派学习笔记(十五)博通BCM2835芯片手册导读

    树莓派3b的CPU型号为:BCM2835(ARM-cotexA53架构) CPU型号为2440.2410(ARM9架构) 编写驱动需要电路图(作用通过电路图找到寄存器).芯片手册 树莓派官网:http ...

  2. 树莓派 博通BCM2835芯片手册

    手册提取链接 链接:https://pan.baidu.com/s/1fdmIBNn1Pr1j3-ercNhKJg 提取码:8y1b 驱动的两大利器: 1.电路图:通过电路图找到寄存器 2.芯片手册 ...

  3. 树莓派高级开发之树莓派博通BCM2835芯片手册导读与及“相关IO口驱动代码的编写”

    首先我们要知道,驱动的两大利器:电路图(通过电路图去寻找寄存器)和芯片手册 一.寄存器的介绍 芯片手册第六章的89页,GPIO有41个寄存器,所有访问都是32位的.Description是寄存器的功能 ...

  4. 树莓派学习——博通BCM2835芯片手册导读、IO口驱动代码调试和测试学习

    一.树莓派寄存器介绍: GPFSEL0 GPIO Function Select 0: 功能选择 输入/输出 GPSET0 GPIO Pin Output Set 0 : 输出0 GPSET1 GPI ...

  5. 树莓派——8、树莓派博通BCM2835芯片手册导读

    (122条消息) 树莓派高阶课程7:树莓派博通BCM2835芯片手册导读_哒宰的自我修养的博客-CSDN博客 博通BCM2835芯片手册导读 驱动的两大利器: 电路图:通过电路图找到寄存器 芯片手册: ...

  6. 树莓派高阶课程7:树莓派博通BCM2835芯片手册导读

    树莓派博通BCM2835芯片手册导读 驱动的两大利器: 电路图:通过电路图找到寄存器 芯片手册:进行编写 1.树莓派寄存器的介绍: GPFSEL0 GPIO Function Select 0: // ...

  7. 树莓派博通BCM2835芯片手册导读及io口驱动代码的实现

    树莓派博通BCM2835芯片手册导读及io口驱动代码的实现 树莓派寄存器的介绍 寄存器地址问题 驱动代码的实现 在linux中生成树莓派所需要的的程序及实现现象 一.树莓派寄存器的介绍 GPFSEL0 ...

  8. 11.树莓派博通BCM2835芯片手册导读与IO口驱动代码调试和测试

    11.树莓派博通BCM2835芯片手册导读与IO口驱动代码调试和测试 硬件地址的相关概念 总线地址 32位的操作系统 ,cpu最多只能访问2^32bit,即只能访问4G的内存 64位的操作系统 ,cp ...

  9. 树莓派博通BCM2835芯片手册导读

    驱动两大利器︰电路图(通过电路图找寄存器)和芯片手册. 寄存器 芯片手册第六章P89∶ 字段名 描述 用法 GPFSEL0 GPIO Function select 0,功能选择输出/输入 以引脚9举 ...

最新文章

  1. Uva 10177 - (2/3/4)-D Sqr/Rects/Cubes/Boxes?
  2. 【知识星球】分组卷积最新进展,全自动学习的分组有哪些经典模型?
  3. AcWing 1402. 星空之夜 1月28
  4. Java|达梦工作笔记-达梦数据库同步工具(JDBC)
  5. ASP.NET自定义控件组件开发
  6. 让程序员崩溃的一句话。。。
  7. 一万小时定律的数学解释
  8. 【四阶龙格库塔法求解二元常微分方程组】
  9. 计算机的acpi高级电源选项配置,ACPI电源管理模式详解
  10. codeforces——962
  11. 自己的小程序修修补补
  12. 语音验证码接口PYTHO语言
  13. 最强计算机游戏,这可能是市面上体积最小性能最强的游戏主机了
  14. 应用性能管理APM巅峰对决:skywalking P.K. Pinpoint
  15. Essential Google Cloud Infrastructure: Foundation
  16. 3D音频理论研究(二)---3D全介绍(转)
  17. 软件测试工程师面试如何做好自我介绍?
  18. 微软开源人工智能工具和深度学习框架
  19. android studio 的 Gradle build finished with 1 error(s) 问题
  20. javaone_Java SE 9在JavaOne 2017上达到了Atari般的性能

热门文章

  1. 基于用户乘车行为大数据的客流分析及预测模型
  2. 李翊 先吞噬后反刍,擒贼擒王--java之我注六经之二
  3. 完美解决:Python3.10报错 No module named ‘_ssl‘
  4. vue打包出来的dist如何查看js的占比,report生成分析图
  5. 流媒体技术基础-流媒体服务与框架
  6. Idea插件开发(二)——插件的创建打包及发布
  7. c语言 txt文件数据,怎样用C语言从txt文件中读入数据?
  8. Java多线程编程:Callable、Future和FutureTask浅析(多线程编程之四)
  9. windows 注册表解析
  10. 仰望星空 ecnu