实现自己的RPi.GPIO(二)-mmap 直接访问硬件

通过驱动访问硬件是很方便简洁的事,但是我想直接操作硬件外设的寄存器。好在Linux提供了mmap函数,可以绕过驱动,直接操作外设的寄存器。

mmap可以实现外设的物理地址到Linux虚拟地址的映射,这样就可以通过操作虚拟地址来操作物理地址。

file = open("/dev/mem", O_RDWR|O_SYNC);

mem_viraddr = mmap(NULL, GPIO_REG_ADDR_4KB, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, file, TI81XX_GPIO_BASE);
mem_viraddr:物理地址映射后的虚拟地址。
GPIO_REG_ADDR_4KB:映射的地址块大小。
TI81XX_GPIO_BASE:DM8148的GPIO模块的物理地址。

下面是通过mmap实现直接操作GPIO,点亮LED的DEMO:

  1 /*
  2  * PyGPIO.h
  3  *
  4  *  Created on: 2015年5月19日
  5  *      Author: jugg
  6  */
  7
  8 #ifndef SRC_PYGPIO_H_
  9 #define SRC_PYGPIO_H_
 10
 11 #include <errno.h>
 12 #include <string.h>
 13 #include <stdio.h>
 14 #include <stdlib.h>
 15 #include <unistd.h>
 16 #include <fcntl.h>
 17 #include <sys/mman.h>
 18 #include <sys/ioctl.h>
 19 #include <sys/stat.h>
 20
 21 // Ti DM8168/DM8148 GPIO Reg base addr
 22 #define TI81XX_GPIO0_BASE    0x48032000
 23 #define TI81XX_GPIO1_BASE    0x4804C000
 24
 25 // Pin mux reg base addr
 26 #define PIN_CTRL_AE28        0x481409A8
 27
 28 #define GPIO_SYSCONFIG        0x10
 29 #define GPIO_SYSSTATUS        0x114
 30 #define GPIO_CTRL        0x130
 31 #define GPIO_OE            0x134
 32 #define GPIO_DATAIN        0x138
 33 #define GPIO_DATAOUT        0x13C
 34
 35 // GPIO Reg size
 36 #define GPIO_REG_ADDR_4KB    0x1000
 37
 38 #define GPIO_P0            0x00000001
 39 #define GPIO_P1            0x00000002
 40 #define GPIO_P2            0x00000004
 41 #define GPIO_P3            0x00000008
 42 #define GPIO_P4            0x00000010
 43 #define GPIO_P5            0x00000020
 44 #define GPIO_P6            0x00000040
 45 #define GPIO_P7            0x00000080
 46 #define GPIO_P8            0x00000100
 47 #define GPIO_P9            0x00000200
 48 #define GPIO_P10        0x00000400
 49 #define GPIO_P11        0x00000800
 50 #define GPIO_P12        0x00001000
 51 #define GPIO_P13        0x00002000
 52 #define GPIO_P14        0x00004000
 53 #define GPIO_P15        0x00008000
 54 #define GPIO_P16        0x00010000
 55 #define GPIO_P17        0x00020000
 56 #define GPIO_P18        0x00040000
 57 #define GPIO_P19        0x00080000
 58 #define GPIO_P20        0x00100000
 59 #define GPIO_P21        0x00200000
 60 #define GPIO_P22        0x00400000
 61 #define GPIO_P23        0x00800000
 62 #define GPIO_P24        0x01000000
 63 #define GPIO_P25        0x02000000
 64 #define GPIO_P26        0x04000000
 65 #define GPIO_P27        0x08000000
 66 #define GPIO_P28        0x10000000
 67 #define GPIO_P29        0x20000000
 68 #define GPIO_P30        0x40000000
 69 #define GPIO_P31        0x80000000
 70
 71
 72 typedef union {
 73     struct {
 74       unsigned int P0 : 1;
 75       unsigned int P1 : 1;
 76       unsigned int P2 : 1;
 77       unsigned int P3 : 1;
 78       unsigned int P4 : 1;
 79       unsigned int P5 : 1;
 80       unsigned int P6 : 1;
 81       unsigned int P7 : 1;
 82       unsigned int P8 : 1;
 83       unsigned int P9 : 1;
 84       unsigned int P10 : 1;
 85       unsigned int P11 : 1;
 86       unsigned int P12 : 1;
 87       unsigned int P13 : 1;
 88       unsigned int P14 : 1;
 89       unsigned int P15 : 1;
 90       unsigned int P16 : 1;
 91       unsigned int P17 : 1;
 92       unsigned int P18 : 1;
 93       unsigned int P19 : 1;
 94       unsigned int P20 : 1;
 95       unsigned int P21 : 1;
 96       unsigned int P22 : 1;
 97       unsigned int P23 : 1;
 98       unsigned int P24 : 1;
 99       unsigned int P25 : 1;
100       unsigned int P26 : 1;
101       unsigned int P27 : 1;
102       unsigned int P28 : 1;
103       unsigned int P29 : 1;
104       unsigned int P30 : 1;
105       unsigned int P31 : 1;
106     } port;
107     unsigned int port_val;
108 } GPIO_PORT;
109
110 typedef enum {
111     GPIO_PORT0,
112     GPIO_PORT1
113 } GPIO_NUM;
114
115
116 typedef enum {
117     GPIO_WRITE,    //GPIO output
118     GPIO_READ    //GPIO input
119 } GPIO_MODE;
120
121 typedef enum {
122     GPIO_VAL_LOW,
123     GPIO_VAL_HIGH
124 } GPIO_VAL;
125
126 int pyGPIO_init(GPIO_NUM gpio, unsigned int gpio_port, GPIO_MODE gpio_mode);
127 int pyGPIO_write(GPIO_NUM gpio, unsigned int gpio_port, GPIO_VAL gpio_val);
128
129 #endif /* SRC_PYGPIO_H_ */

PyGPIO.h

 1 /*
 2  * PyGPIO.c
 3  *
 4  *  Created on: 2015年5月19日
 5  *      Author: jugg
 6  */
 7 #include <python2.6/Python.h>
 8
 9 #include "PyGPIO.h"
10
11
12 int pyGPIO_init(GPIO_NUM gpio, unsigned int gpio_port, GPIO_MODE gpio_mode)
13 {
14   int file;
15   unsigned int TI81XX_GPIO_BASE;
16   unsigned int *mem_viraddr = NULL;
17   file = open("/dev/mem", O_RDWR|O_SYNC);
18   if(file < 0){
19       printf(" ERROR: /dev/mem open failed !!!\n");
20       return -1;
21   }
22
23   TI81XX_GPIO_BASE = gpio ? TI81XX_GPIO1_BASE:TI81XX_GPIO0_BASE;
24   mem_viraddr = mmap(NULL, GPIO_REG_ADDR_4KB, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, file, TI81XX_GPIO_BASE);
25
26   mem_viraddr[GPIO_SYSCONFIG >> 2] = 0x10;    // No idle
27   mem_viraddr[GPIO_OE >> 2] = gpio_mode ? gpio_port:~gpio_port;     // GPIO mode setting
28   munmap((void *)mem_viraddr, GPIO_REG_ADDR_4KB);
29
30   //mem_viraddr = mmap(NULL, 0x10, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, file, PIN_CTRL_AE28);
31   // MUXMODE = GP1_13
32   //mem_viraddr[0] = 0x00050080;
33   //munmap((void *)mem_viraddr, 0x10);
34   close(file);
35
36   return 0;
37 }
38
39 int pyGPIO_write(GPIO_NUM gpio, unsigned int gpio_port, GPIO_VAL gpio_val)
40 {
41   int file;
42   unsigned int TI81XX_GPIO_BASE;
43   unsigned int *mem_viraddr = NULL;
44   file = open("/dev/mem", O_RDWR|O_SYNC);
45   if(file < 0){
46       printf(" ERROR : /dev/mem open failed write!!!\n");
47       return -1;
48   }
49
50   TI81XX_GPIO_BASE = gpio ? TI81XX_GPIO1_BASE:TI81XX_GPIO0_BASE;
51   mem_viraddr = mmap(NULL, GPIO_REG_ADDR_4KB, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, file, TI81XX_GPIO_BASE);
52
53   mem_viraddr[GPIO_DATAOUT >> 2] = gpio_val ? gpio_port:~gpio_port;
54
55   munmap((void *)mem_viraddr, GPIO_REG_ADDR_4KB);
56   close(file);
57
58   return 0;
59 }

PyGPIO.c

 1 /*
 2  * main.c
 3  *
 4  *  Created on: 2015年5月18日
 5  *      Author: jugg
 6  */
 7 #include "PyGPIO.h"
 8 /*
 9 static PyObject *helloworld(PyObject *self)
10 {
11   return Py_BuildValue("s", "Hello, Python extensions!!");
12 }
13
14 static char helloworld_docs[] = "helloworld():Any message you want to put hele!\n";
15
16 static PyMethodDef helloworld_funcs[] = {
17     {"helloworld", (PyCFunction)helloworld, METH_NOARGS, helloworld_docs},
18     {NULL}
19 };
20
21 void inithelloworld(void)
22 {
23   Py_InitModule3("helloworld", helloworld_funcs, "Extension module example!");
24 }
25 */
26
27 int main()
28 {
29   pyGPIO_init(GPIO_PORT1, GPIO_P13, GPIO_WRITE);
30   printf("GPIO init done!\n");
31   pyGPIO_write(GPIO_PORT1, GPIO_P13, GPIO_VAL_HIGH);
32   printf("GPIO write 1 \n");
33   sleep(1);
34   pyGPIO_write(GPIO_PORT1, GPIO_P13, GPIO_VAL_LOW);
35   printf("GPIO write 0 \n");
36   sleep(1);
37   pyGPIO_write(GPIO_PORT1, GPIO_P13, GPIO_VAL_HIGH);
38   printf("gpio write 1 \n");
39   return 0;
40 }

main.c

编译之后得到PyGPIO,tftp到网络文件系统中执行:

由于DM8148的GPIO1.13引脚是复用引脚,且默认不是作为GPIO引脚,需要在Kernel中对复用引脚进行配置才能作为GPIO使用。但是Kernel重新配置后,驱动都需要重新编译,太麻烦了。所以我就在uboot中直接操作寄存器,将GPIO1.13引脚配置为GPIO。

这样LED灯就可以亮灭了。

时间: 2024-07-31 06:29:01

实现自己的RPi.GPIO(二)-mmap 直接访问硬件的相关文章

实现自己的RPi.GPIO(三)-Python C API

Python C 的扩展按照模板来就行了,其实就4步:参数传递,返回值传递,函数注册,初始化. 直接上代码: 1 /* 2 * PyGPIO.h 3 * 4 * Created on: 2015年5月19日 5 * Author: jugg 6 */ 7 8 #ifndef SRC_PYGPIO_H_ 9 #define SRC_PYGPIO_H_ 10 11 #include <errno.h> 12 #include <string.h> 13 #include <std

【玩转开源】BananaPi R2——移植RPi.GPIO 到 R2

1. 首先给大家介绍一下什么是RPi.GPIO. 简单去讲,RPi.GPIO就是一个运行在树莓派开发板上可以通过Python去控制GPIO的一个中间件. 现在我这边做了一个基础功能的移植,接下来大家可以跟着我去学习一下RPi.GPIO是如何通过Python去实现控制开发板上的GPIO的. 2. 看一下效果图: 2.1 硬件实物运行效果 2.2 执行Python脚本打印的log 3. 那么RPi.GPIO在R2上是如何使用的呢? 3.1 首先在R2上面运行一个Ubuntu镜像,然后下载代码:git

树莓派瞎玩~7~RPi.GPIOのWIKI文档

树莓派瞎玩~7~RPi.GPIOのWIKI文档 RPiGPIO Python Module RPiGPIO module basics Importing the module Pin numbering Warnings Setup up a channel Setup more than one channel Input Output Output to several channels Cleanup RPi Board Information and RPiGPIO version I

实现自己的RPi.GPIO(一)-Python C Extension

树莓派有个RPi.GPIO的Python模块,import之后就可以直接用Python操作ARM芯片的GPIO硬件模块.觉得这个很有意思,于是查资料想在自己画的DM8148平台上面也实现这样的一个模块. DM8148是TI推出的一款达芬奇系列数字图像处理芯片,比DM8168性能略差,但是功耗更低.之前公司的很多图像处理都是用的DM8168,但是散热和功耗问题一直很让人头疼,于是就让我预研更低功耗的DM8148.DM8148可以理解为ARM+DSP的异构核心,我们要用到的就是它的一颗Cortex

二维vector访问

//  方式1 vector<vector<double> > p1(pt1.size(), vector<double>(2)); // 方式2 vector<vector <double>> ps; vector<double> pp; for(int i = 0; i < pt1.size(); i++) { p1[i][0] = pt1[i].x; p1[i][1] = pt1[i].y; pp.push_back(pt

【开源夏令营优秀开题报告】专题之二 - 嵌入式与智能硬件类合集

CSDN开源夏令活动已经正式进入第一实习阶段,我们遴选出部分优秀提案开题报告进行展示.本文是嵌入式与智能硬件类开题报告展示. 编者按:CSDN开源夏令活动,已经正式进入第一实习阶段,我们遴选出了部分提案的优秀开题报告进行展示.优秀开题报告作者将得到CSDN高校俱乐部发出的"2014开源夏令营荣誉证书"及纪念品一份. 提案1:环境数据采集系统  提案简介:该项目是一套利用物联网技术对环境数据进行采集.处理的综合系统:其利用传感器网络,收集环境中的温度.湿度.光照度.风速.紫外线强度.粉尘

【转贴】内存系列二:深入理解硬件原理

内存系列二:深入理解硬件原理 https://www.cnblogs.com/tcicy/p/10087457.html 忘记转这一篇了 内存相关的东西 其实理解了挺好的.. cache还有main memory 本篇文章承接上文继续介绍DDR内存的硬件原理,包括如何寻址,时序和时延以及可以为提高内存的效能可以有哪些方法. 上次虽然解决了小张的问题,却引发了他对内存原理的兴趣.这不他又来找我了,说我还欠他一个解释.这次我们约在一个咖啡馆见面,这次内容有点深入,我带了些图片,小张也点了一大杯美式,

RPi GPIO 图

为了保险,还需要用万用表测量一下我们的判断对不对:在Raspberry Pi的工作状态下,将万用表的“+”接到“1”口上,万用表的“-”接到“6”口上,在看看万用表的显示是不是大约为正3.3V,如果不是,那么说明我们弄错了针脚顺序,需要回头再检查! From WizNote

蓝鸥Unity开发基础二——课时3 访问修饰符

[蓝鸥Unity开发基础二]课时3 访问修饰符 一.访问修饰符 public --公共的,在哪里都能用 private  --私有的,只能够在当前机构体重使用,其他任何地方都不能 访问修饰符举例说明 using System; namespace Lesson_03{           struct Point2{        //public--公共的,在哪里都能用        public float x;        //private  --私有的,只能够在当前机构体重使用,其他