芯片手册下载:
百度网盘:https://pan.baidu.com/s/1hESG0ECH5xk-rv1V-1qM7g
提取码:a9iy
1.树莓派博通BCM2835芯片手册介绍
说明:
-
GPFSEL0 GPIO Function Select 0: 功能选择:输入/输出
-
GPSET0 GPIO Pin Output Set 0 : 输出0
GPSET1 GPIO Pin Output Set 1 : 输出 -
GPCLR0 GPIO Pin Output Clear 0: 清零(设置低电平)
GPCLR1 GPIO Pin Output Clear 1 :清1 (设置高电平)
说明:
-
每个寄存器都是32位的
-
FSEL4 代表的是引脚4
-
我们把引脚4配置为输出引脚
FSEL4 14-12 001 我们把4引脚的14-12配置成001 GPIO Pin 4 is an output
说明:
- 0 = No effect(无效)
1 = Set GPIO pin n(设置GPIO引脚)
2.寄存器的地址问题
我们在编写驱动程序时,IO空间的起始地址是 0x3f000000,加上GPIO的偏移量0x2000000,所以GPIO的物理地址应该是从0x3f200000开始的,然后在这个基础上进行Linux系统的MMU内存虚拟化管理,映射到虚拟地址上。
该图的尾部偏移是对的根据GPIO的物理地址0x3f200000可以知道:
GPFSEL0 0x3f200000
GPSET0 0x3f20001c
GPCLR0 0x3f200028
上面写的地址是物理地址,需要转化成虚拟地址,通过函数:ioremap();
void __iomem * __ioremap(unsigned long phys_addr, size_t size, unsigned long flags);
参数说明:
- phys_addr:要映射的起始的IO地址
- size:要映射的空间的大小
- flags:要映射的IO空间和权限有关的标志
3.驱动代码的编写
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/types.h>
#include <asm/io.h>
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是一个特征修饰符,作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值
volatile unsigned