实现自己的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到网络文件系统中执行:

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

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

这样LED灯就可以亮灭了。

你可能感兴趣的:(map)