通过驱动访问硬件是很方便简洁的事,但是我想直接操作硬件外设的寄存器。好在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-10-05 20:04:13