mmap操做荔枝派gpio v3s Linux

1.預備知識linux

https://baike.baidu.com/item/mmap/1322217?fr=aladdin 你們直接看百度百科,比較清楚了。spa

2.代碼code

gpio.c對象

#include "gpio.h" unsigned int fd; PIO_Map *PIO = NULL; unsigned int *gpio_map; unsigned int addr_start, addr_offset; unsigned int PageSize, PageMask; void GPIO_Init(void) { if ((fd = open("/dev/mem", O_RDWR)) == -1) { printf("open error\r\n"); return; } PageSize = sysconf(_SC_PAGESIZE); //使用sysconf查詢系統頁面大小
    PageMask = (~(PageSize - 1));     //頁掩碼
    printf("PageSize:%d,PageMask:0x%.8X\r\n", PageSize, PageMask); addr_start = PIO_BASE_ADDRESS & PageMask;   //0x01C20800 & 0xfffff000 = 0x1C20000
    addr_offset = PIO_BASE_ADDRESS & ~PageMask; //0x01C20800 & 0x00000100 = 0x800
    printf("addr_start:%.8X,addr_offset:0x%.8X\r\n", addr_start, addr_offset); //mmap(系統自動分配內存地址,映射區長度「內存頁的整數倍」,選擇可讀可寫,MAP_SHARED=與其餘全部映射到這個對象的進程共享空間,文件句柄,被映射內容的起點) //offest 映射物理內存的話,必須頁對其!!! 因此這個起始地址應該是0x1000的整數倍,那麼明顯0x01C20800須要減去0x800纔是整數倍!
    if ((gpio_map = mmap(NULL, PageSize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr_start)) == NULL) { printf("mmap error\r\n"); close(fd); return; } printf("gpio_map:%.8X\r\n", gpio_map); //這裏已經將0x1c20000的地址映射到了內存中,可是咱們須要的地址是0x01C20800,因此要再加上地址偏移量~
    PIO = (PIO_Map *)((unsigned int)gpio_map + addr_offset); printf("PIO:0x%.8X\r\n", PIO); close(fd); //映射好以後就能夠關閉文件?
} void GPIO_ConfigPin(PORT port, unsigned int pin, PIN_MODE mode) { if (gpio_map == NULL) return; PIO->Pn[port].CFG[pin / 8] &= ~((unsigned int)0x07 << pin % 8 * 4); PIO->Pn[port].CFG[pin / 8] |= ((unsigned int)mode << pin % 8 * 4); printf("struct PIO_Struct size : %d",sizeof(PIO->Pn[port])); } void GPIO_SetPin(PORT port, unsigned int pin, unsigned int level) { if (gpio_map == NULL) return; if (level) PIO->Pn[port].DAT |= (1 << pin); else PIO->Pn[port].DAT &= ~(1 << pin); } int GPIO_Free(void) { if ((munmap(gpio_map, PageSize * 2)) == 0)//取消映射
 { printf("unmap success!\r\n"); } else { printf("unmap failed!\r\n"); } return 0; }

gpio.hblog

#ifndef __GPIO_H__ #define __GPIO_H__ #include <stdio.h> #include <unistd.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>

#define PIO_BASE_ADDRESS 0x01C20800


//unsigned int 4字節 一個PIO_Struct佔36字節,對應十六進制就是0x24,正好是一個offset值。
typedef struct { unsigned int CFG[4]; unsigned int DAT; unsigned int DRV0; unsigned int DRV1; unsigned int PUL0; unsigned int PUL1; } PIO_Struct; typedef struct { PIO_Struct Pn[7]; } PIO_Map; typedef enum { PA = 0, PB = 1, PC = 2, PD = 3, PE = 4, PF = 5, PG = 6, } PORT; typedef enum { IN = 0x00, OUT = 0x01, AUX = 0x02, INT = 0x06, DISABLE = 0x07, } PIN_MODE; extern PIO_Map *PIO; void GPIO_Init(void); void GPIO_ConfigPin(PORT port, unsigned int pin, PIN_MODE mode); void GPIO_SetPin(PORT port, unsigned int pin, unsigned int level); unsigned int GPIO_GetPin(PORT port, unsigned int pin); int GPIO_Free(void); #endif

main.c進程

#include <stdio.h> #include <unistd.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "gpio.h" #include <stdbool.h>
int main() { int a=0,b=-1,i; GPIO_Init(); GPIO_ConfigPin(PB,4,OUT); GPIO_ConfigPin(PB,5,OUT); for(i=0;i<20;i++) { GPIO_SetPin(PB,4,a=~a);//!!-1的取反是0 1的取反是-2....
        GPIO_SetPin(PB,5,b=~b); //usleep(100000);
        sleep(1); } GPIO_Free(); }

makefileip

TARGET        = myGPIO #可執行文件名稱 ########################編譯參數############################ CC = arm-linux-gnueabihf-gcc CXX = arm-linux-gnueabihf-g++ DEFINES = CFLAGS = -pipe -g -Wall -W -fPIE $(DEFINES) CXXFLAGS = -pipe -g -Wall -W -fPIE $(DEFINES) INCPATH = -I. ########################編譯文件############################ SOURCES = ./main.c ./gpio.c OBJECTS = main.o gpio.o $(TARGET) : $(OBJECTS) $(CC) -o $(TARGET) $(OBJECTS) main.o : main.c gpio.h $(CC) $(include) $(CFLAGS) -c main.c gpio.o : gpio.c gpio.h $(CC) $(include) $(CFLAGS) -c gpio.c clean : rm  $(OBJECTS) $(TARGET)

3.運行內存

將程序編譯出來放到v3s上運行,那麼pb4 pb5 會交替高低電平。it

相關文章
相關標籤/搜索